Merge "Export AIDL files as a filegroup for framework.jar" am: e6161630a1 -s ours am: dbe8513e74 -s ours
am: 40d33758aa -s ours
Change-Id: I6e606ee28398fbedfebf4e6e1403d784cf127831
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..6511b44 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,32 @@
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);
+#if DEBUG
+ ALOGD("openFile: %s, full=%s", path8.string(), fullPath.string());
+#endif
+ 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 DEBUG
+ ALOGD("openFile: fd=%d", fd);
+#endif
if (fd < 0) {
return fd;
}
@@ -80,14 +106,33 @@
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) {
+#if DEBUG
+ ALOGD("openFile: failed selinux write check!");
+#endif
+ 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) {
+#if DEBUG
+ ALOGD("openFile: failed selinux read check!");
+#endif
+ 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;
@@ -131,6 +176,9 @@
proc->setThreadPoolMaxThreadCount(0);
proc->startThreadPool();
+#if DEBUG
+ ALOGD("cmd: starting");
+#endif
sp<IServiceManager> sm = defaultServiceManager();
fflush(stdout);
if (sm == NULL) {
diff --git a/cmds/dumpstate/DumpstateUtil.cpp b/cmds/dumpstate/DumpstateUtil.cpp
index ede4254..85eb464 100644
--- a/cmds/dumpstate/DumpstateUtil.cpp
+++ b/cmds/dumpstate/DumpstateUtil.cpp
@@ -43,7 +43,7 @@
static constexpr const char* kSuPath = "/system/xbin/su";
-static bool waitpid_with_timeout(pid_t pid, int timeout_seconds, int* status) {
+static bool waitpid_with_timeout(pid_t pid, int timeout_ms, int* status) {
sigset_t child_mask, old_mask;
sigemptyset(&child_mask);
sigaddset(&child_mask, SIGCHLD);
@@ -54,10 +54,11 @@
}
timespec ts;
- ts.tv_sec = timeout_seconds;
- ts.tv_nsec = 0;
+ ts.tv_sec = MSEC_TO_SEC(timeout_ms);
+ ts.tv_nsec = (timeout_ms % 1000) * 1000000;
int ret = TEMP_FAILURE_RETRY(sigtimedwait(&child_mask, NULL, &ts));
int saved_errno = errno;
+
// Set the signals back the way they were.
if (sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) {
printf("*** sigprocmask failed: %s\n", strerror(errno));
@@ -91,7 +92,7 @@
CommandOptions CommandOptions::DEFAULT = CommandOptions::WithTimeout(10).Build();
CommandOptions CommandOptions::AS_ROOT = CommandOptions::WithTimeout(10).AsRoot().Build();
-CommandOptions::CommandOptionsBuilder::CommandOptionsBuilder(int64_t timeout) : values(timeout) {
+CommandOptions::CommandOptionsBuilder::CommandOptionsBuilder(int64_t timeout_ms) : values(timeout_ms) {
}
CommandOptions::CommandOptionsBuilder& CommandOptions::CommandOptionsBuilder::Always() {
@@ -130,8 +131,8 @@
return CommandOptions(values);
}
-CommandOptions::CommandOptionsValues::CommandOptionsValues(int64_t timeout)
- : timeout_(timeout),
+CommandOptions::CommandOptionsValues::CommandOptionsValues(int64_t timeout_ms)
+ : timeout_ms_(timeout_ms),
always_(false),
account_mode_(DONT_DROP_ROOT),
output_mode_(NORMAL_OUTPUT),
@@ -142,7 +143,11 @@
}
int64_t CommandOptions::Timeout() const {
- return values.timeout_;
+ return MSEC_TO_SEC(values.timeout_ms_);
+}
+
+int64_t CommandOptions::TimeoutInMs() const {
+ return values.timeout_ms_;
}
bool CommandOptions::Always() const {
@@ -161,8 +166,12 @@
return values.logging_message_;
}
-CommandOptions::CommandOptionsBuilder CommandOptions::WithTimeout(int64_t timeout) {
- return CommandOptions::CommandOptionsBuilder(timeout);
+CommandOptions::CommandOptionsBuilder CommandOptions::WithTimeout(int64_t timeout_sec) {
+ return CommandOptions::CommandOptionsBuilder(SEC_TO_MSEC(timeout_sec));
+}
+
+CommandOptions::CommandOptionsBuilder CommandOptions::WithTimeoutInMs(int64_t timeout_ms) {
+ return CommandOptions::CommandOptionsBuilder(timeout_ms);
}
std::string PropertiesHelper::build_type_ = "";
@@ -314,7 +323,7 @@
/* handle parent case */
int status;
- bool ret = waitpid_with_timeout(pid, options.Timeout(), &status);
+ bool ret = waitpid_with_timeout(pid, options.TimeoutInMs(), &status);
fsync(fd);
uint64_t elapsed = Nanotime() - start;
@@ -333,9 +342,9 @@
static_cast<float>(elapsed) / NANOS_PER_SEC, pid);
}
kill(pid, SIGTERM);
- if (!waitpid_with_timeout(pid, 5, nullptr)) {
+ if (!waitpid_with_timeout(pid, 5000, nullptr)) {
kill(pid, SIGKILL);
- if (!waitpid_with_timeout(pid, 5, nullptr)) {
+ if (!waitpid_with_timeout(pid, 5000, nullptr)) {
if (!silent)
dprintf(fd, "could not kill command '%s' (pid %d) even with SIGKILL.\n",
command, pid);
diff --git a/cmds/dumpstate/DumpstateUtil.h b/cmds/dumpstate/DumpstateUtil.h
index 698ceff..8342099 100644
--- a/cmds/dumpstate/DumpstateUtil.h
+++ b/cmds/dumpstate/DumpstateUtil.h
@@ -19,6 +19,16 @@
#include <cstdint>
#include <string>
+/*
+ * Converts seconds to milliseconds.
+ */
+#define SEC_TO_MSEC(second) (second * 1000)
+
+/*
+ * Converts milliseconds to seconds.
+ */
+#define MSEC_TO_SEC(millisecond) (millisecond / 1000)
+
namespace android {
namespace os {
namespace dumpstate {
@@ -66,9 +76,9 @@
private:
class CommandOptionsValues {
private:
- CommandOptionsValues(int64_t timeout);
+ CommandOptionsValues(int64_t timeout_ms);
- int64_t timeout_;
+ int64_t timeout_ms_;
bool always_;
PrivilegeMode account_mode_;
OutputMode output_mode_;
@@ -102,13 +112,15 @@
CommandOptions Build();
private:
- CommandOptionsBuilder(int64_t timeout);
+ CommandOptionsBuilder(int64_t timeout_ms);
CommandOptionsValues values;
friend class CommandOptions;
};
- /** Gets the command timeout, in seconds. */
+ /** Gets the command timeout in seconds. */
int64_t Timeout() const;
+ /** Gets the command timeout in milliseconds. */
+ int64_t TimeoutInMs() const;
/* Checks whether the command should always be run, even on dry-run mode. */
bool Always() const;
/** Gets the PrivilegeMode of the command. */
@@ -118,8 +130,11 @@
/** Gets the logging message header, it any. */
std::string LoggingMessage() const;
- /** Creates a builder with the requied timeout. */
- static CommandOptionsBuilder WithTimeout(int64_t timeout);
+ /** Creates a builder with the requied timeout in seconds. */
+ static CommandOptionsBuilder WithTimeout(int64_t timeout_sec);
+
+ /** Creates a builder with the requied timeout in milliseconds. */
+ static CommandOptionsBuilder WithTimeoutInMs(int64_t timeout_ms);
// Common options.
static CommandOptions DEFAULT;
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..4b67d8f 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -81,6 +81,7 @@
#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
#define WLUTIL "/vendor/xbin/wlutil"
+#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
// TODO(narayan): Since this information has to be kept in sync
// with tombstoned, we should just put it in a common header.
@@ -112,8 +113,8 @@
}
static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
- long dumpsysTimeout = 0) {
- return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeout);
+ long dumpsysTimeoutMs = 0) {
+ return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs);
}
static int DumpFile(const std::string& title, const std::string& path) {
return ds.DumpFile(title, path);
@@ -829,33 +830,32 @@
}
static void DoLogcat() {
- unsigned long timeout;
+ unsigned long timeout_ms;
// DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
// calculate timeout
- timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
- if (timeout < 20000) {
- timeout = 20000;
+ timeout_ms = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
+ if (timeout_ms < 20000) {
+ timeout_ms = 20000;
}
RunCommand("SYSTEM LOG",
- {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid",
- "-d", "*:v"},
- CommandOptions::WithTimeout(timeout / 1000).Build());
- timeout = logcat_timeout("events");
- if (timeout < 20000) {
- timeout = 20000;
+ {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
+ CommandOptions::WithTimeoutInMs(timeout_ms).Build());
+ timeout_ms = logcat_timeout("events");
+ if (timeout_ms < 20000) {
+ timeout_ms = 20000;
}
RunCommand("EVENT LOG",
{"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid",
"-d", "*:v"},
- CommandOptions::WithTimeout(timeout / 1000).Build());
- timeout = logcat_timeout("radio");
- if (timeout < 20000) {
- timeout = 20000;
+ CommandOptions::WithTimeoutInMs(timeout_ms).Build());
+ timeout_ms = logcat_timeout("radio");
+ if (timeout_ms < 20000) {
+ timeout_ms = 20000;
}
RunCommand("RADIO LOG",
{"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid",
"-d", "*:v"},
- CommandOptions::WithTimeout(timeout / 1000).Build());
+ CommandOptions::WithTimeoutInMs(timeout_ms).Build());
RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
@@ -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(), SEC_TO_MSEC(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"});
@@ -1180,6 +1210,11 @@
DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
+ /* Add window and surface trace files. */
+ if (!PropertiesHelper::IsUserBuild()) {
+ ds.AddDir(WMTRACE_DATA_DIR, false);
+ }
+
ds.DumpstateBoard();
/* Migrate the ril_dumpstate to a device specific dumpstate? */
@@ -1200,8 +1235,7 @@
printf("== Android Framework Services\n");
printf("========================================================\n");
- RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"}, CommandOptions::WithTimeout(90).Build(),
- 10);
+ RunDumpsysNormal();
printf("========================================================\n");
printf("== Checkins\n");
@@ -1273,8 +1307,10 @@
printf("== Android Framework Services\n");
printf("========================================================\n");
- RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(), 10);
- RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(), 10);
+ RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
+ SEC_TO_MSEC(10));
+ RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
+ SEC_TO_MSEC(10));
printf("========================================================\n");
printf("== Running Application Services\n");
@@ -1599,6 +1635,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 +1679,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 +1875,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 +1905,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..8db23a9 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.
@@ -190,19 +196,19 @@
/*
* Runs `dumpsys` with the given arguments, automatically setting its timeout
- * (`-t` argument)
+ * (`-T` argument)
* according to the command options.
*
* |title| description of the command printed on `stdout` (or empty to skip
* description).
* |dumpsys_args| `dumpsys` arguments (except `-t`).
* |options| optional argument defining the command's behavior.
- * |dumpsys_timeout| when > 0, defines the value passed to `dumpsys -t` (otherwise it uses the
+ * |dumpsys_timeout| when > 0, defines the value passed to `dumpsys -T` (otherwise it uses the
* timeout from `options`)
*/
void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
const android::os::dumpstate::CommandOptions& options = DEFAULT_DUMPSYS,
- long dumpsys_timeout = 0);
+ long dumpsys_timeout_ms = 0);
/*
* Prints the contents of a file.
@@ -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/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 92b0c0d..a2e9453 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -1001,7 +1001,7 @@
err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
}
-TEST_F(DumpstateUtilTest, RunCommandTimesout) {
+TEST_F(DumpstateUtilTest, RunCommandTimesoutWithSec) {
CreateFd("RunCommandTimesout.txt");
EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
CommandOptions::WithTimeout(1).Build()));
@@ -1011,6 +1011,17 @@
" --sleep 2' timed out after 1"));
}
+TEST_F(DumpstateUtilTest, RunCommandTimesoutWithMsec) {
+ CreateFd("RunCommandTimesout.txt");
+ EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
+ CommandOptions::WithTimeoutInMs(1000).Build()));
+ EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
+ " --sleep 2' timed out after 1"));
+ EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
+ " --sleep 2' timed out after 1"));
+}
+
+
TEST_F(DumpstateUtilTest, RunCommandIsKilled) {
CreateFd("RunCommandIsKilled.txt");
CaptureStderr();
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index a96a69d..ac48041 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -215,10 +215,10 @@
return progress_;
}
-bool Progress::Inc(int32_t delta) {
+bool Progress::Inc(int32_t delta_sec) {
bool changed = false;
- if (delta >= 0) {
- progress_ += delta;
+ if (delta_sec >= 0) {
+ progress_ += delta_sec;
if (progress_ > max_) {
int32_t old_max = max_;
max_ = floor((float)progress_ * growth_factor_);
@@ -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);
}
@@ -719,9 +723,9 @@
}
void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
- const CommandOptions& options, long dumpsysTimeout) {
- long timeout = dumpsysTimeout > 0 ? dumpsysTimeout : options.Timeout();
- std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-t", std::to_string(timeout)};
+ const CommandOptions& options, long dumpsysTimeoutMs) {
+ long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
+ std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
RunCommand(title, dumpsys, options);
}
@@ -1161,14 +1165,14 @@
}
// TODO: make this function thread safe if sections are generated in parallel.
-void Dumpstate::UpdateProgress(int32_t delta) {
+void Dumpstate::UpdateProgress(int32_t delta_sec) {
if (progress_ == nullptr) {
MYLOGE("UpdateProgress: progress_ not set\n");
return;
}
// Always update progess so stats can be tuned...
- bool max_changed = progress_->Inc(delta);
+ bool max_changed = progress_->Inc(delta_sec);
// ...but only notifiy listeners when necessary.
if (!update_progress_) return;
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..0862a40 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,19 @@
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"
+ " -t TIMEOUT_SEC: TIMEOUT to use in seconds instead of default 10 seconds\n"
+ " -T TIMEOUT_MS: TIMEOUT to use in milliseconds 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 +80,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;
- int timeoutArg = 10;
- static struct option longOptions[] = {
- {"skip", no_argument, 0, 0 },
- {"help", no_argument, 0, 0 },
- { 0, 0, 0, 0 }
- };
+ bool filterByProto = false;
+ int timeoutArgMs = 10000;
+ 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).
@@ -93,7 +120,7 @@
int c;
int optionIndex = 0;
- c = getopt_long(argc, argv, "+t:l", longOptions, &optionIndex);
+ c = getopt_long(argc, argv, "+t:T:l", longOptions, &optionIndex);
if (c == -1) {
break;
@@ -103,18 +130,39 @@
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;
case 't':
{
- char *endptr;
- timeoutArg = strtol(optarg, &endptr, 10);
- if (*endptr != '\0' || timeoutArg <= 0) {
- fprintf(stderr, "Error: invalid timeout number: '%s'\n", optarg);
+ char* endptr;
+ timeoutArgMs = strtol(optarg, &endptr, 10);
+ timeoutArgMs = timeoutArgMs * 1000;
+ if (*endptr != '\0' || timeoutArgMs <= 0) {
+ fprintf(stderr, "Error: invalid timeout(seconds) number: '%s'\n", optarg);
+ return -1;
+ }
+ }
+ break;
+
+ case 'T':
+ {
+ char* endptr;
+ timeoutArgMs = strtol(optarg, &endptr, 10);
+ if (*endptr != '\0' || timeoutArgMs <= 0) {
+ fprintf(stderr, "Error: invalid timeout(milliseconds) number: '%s'\n", optarg);
return -1;
}
}
@@ -151,9 +199,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 +259,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..
@@ -216,7 +282,7 @@
}
});
- auto timeout = std::chrono::seconds(timeoutArg);
+ auto timeout = std::chrono::milliseconds(timeoutArgMs);
auto start = std::chrono::steady_clock::now();
auto end = start + timeout;
@@ -268,8 +334,8 @@
if (timed_out) {
aout << endl
- << "*** SERVICE '" << service_name << "' DUMP TIMEOUT (" << timeoutArg
- << "s) EXPIRED ***" << endl
+ << "*** SERVICE '" << service_name << "' DUMP TIMEOUT (" << timeoutArgMs
+ << "ms) EXPIRED ***" << endl
<< endl;
}
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..bdb0a9a 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");
@@ -246,12 +299,25 @@
}
// Tests 'dumpsys -t 1 service_name' on a service that times out after 2s
-TEST_F(DumpsysTest, DumpRunningServiceTimeout) {
+TEST_F(DumpsysTest, DumpRunningServiceTimeoutInSec) {
sp<BinderMock> binder_mock = ExpectDumpAndHang("Valet", 2, "Here's your car");
CallMain({"-t", "1", "Valet"});
- AssertOutputContains("SERVICE 'Valet' DUMP TIMEOUT (1s) EXPIRED");
+ AssertOutputContains("SERVICE 'Valet' DUMP TIMEOUT (1000ms) EXPIRED");
+ AssertNotDumped("Here's your car");
+
+ // TODO(b/65056227): BinderMock is not destructed because thread is detached on dumpsys.cpp
+ Mock::AllowLeak(binder_mock.get());
+}
+
+// Tests 'dumpsys -T 500 service_name' on a service that times out after 2s
+TEST_F(DumpsysTest, DumpRunningServiceTimeoutInMs) {
+ sp<BinderMock> binder_mock = ExpectDumpAndHang("Valet", 2, "Here's your car");
+
+ CallMain({"-T", "500", "Valet"});
+
+ AssertOutputContains("SERVICE 'Valet' DUMP TIMEOUT (500ms) EXPIRED");
AssertNotDumped("Here's your car");
// TODO(b/65056227): BinderMock is not destructed because thread is detached on dumpsys.cpp
@@ -300,3 +366,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/Android.bp b/cmds/installd/Android.bp
index 7d1537a..90c7da4 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -18,6 +18,7 @@
shared_libs: [
"libbase",
"libbinder",
+ "libcrypto",
"libcutils",
"liblog",
"liblogwrap",
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
index 1d21b3c..b3dc5ec 100644
--- a/cmds/installd/Android.mk
+++ b/cmds/installd/Android.mk
@@ -27,6 +27,7 @@
LOCAL_HEADER_LIBRARIES := dex2oat_headers
LOCAL_SHARED_LIBRARIES := \
libbase \
+ libcrypto \
libcutils \
liblog \
liblogwrap \
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 04e39f9..48d5b36 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -2365,6 +2365,22 @@
return result ? ok() : error();
}
+binder::Status InstalldNativeService::hashSecondaryDexFile(
+ const std::string& dexPath, const std::string& packageName, int32_t uid,
+ const std::unique_ptr<std::string>& volumeUuid, int32_t storageFlag,
+ std::vector<uint8_t>* _aidl_return) {
+ ENFORCE_UID(AID_SYSTEM);
+ CHECK_ARGUMENT_UUID(volumeUuid);
+ CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+
+ // mLock is not taken here since we will never modify the file system.
+ // If a file is modified just as we are reading it this may result in an
+ // anomalous hash, but that's ok.
+ bool result = android::installd::hash_secondary_dex_file(
+ dexPath, packageName, uid, volumeUuid, storageFlag, _aidl_return);
+ return result ? ok() : error();
+}
+
binder::Status InstalldNativeService::invalidateMounts() {
ENFORCE_UID(AID_SYSTEM);
std::lock_guard<std::recursive_mutex> lock(mMountsLock);
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index f205efc..eb7231c 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -120,6 +120,9 @@
binder::Status reconcileSecondaryDexFile(const std::string& dexPath,
const std::string& packageName, int32_t uid, const std::vector<std::string>& isa,
const std::unique_ptr<std::string>& volumeUuid, int32_t storage_flag, bool* _aidl_return);
+ binder::Status hashSecondaryDexFile(const std::string& dexPath,
+ const std::string& packageName, int32_t uid, const std::unique_ptr<std::string>& volumeUuid,
+ int32_t storageFlag, std::vector<uint8_t>* _aidl_return);
binder::Status invalidateMounts();
binder::Status isQuotaSupported(const std::unique_ptr<std::string>& volumeUuid,
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 3374106..16ba2af 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -85,6 +85,9 @@
int uid, in @utf8InCpp String[] isas, @nullable @utf8InCpp String volume_uuid,
int storage_flag);
+ byte[] hashSecondaryDexFile(@utf8InCpp String dexPath, @utf8InCpp String pkgName,
+ int uid, @nullable @utf8InCpp String volumeUuid, int storageFlag);
+
void invalidateMounts();
boolean isQuotaSupported(@nullable @utf8InCpp String uuid);
}
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 8917684..beffe00 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -15,6 +15,7 @@
*/
#define LOG_TAG "installed"
+#include <array>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
@@ -27,6 +28,7 @@
#include <sys/wait.h>
#include <unistd.h>
+#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
@@ -36,6 +38,7 @@
#include <cutils/properties.h>
#include <cutils/sched_policy.h>
#include <log/log.h> // TODO: Move everything to base/logging.
+#include <openssl/sha.h>
#include <private/android_filesystem_config.h>
#include <selinux/android.h>
#include <system/thread_defs.h>
@@ -46,8 +49,10 @@
#include "otapreopt_utils.h"
#include "utils.h"
-using android::base::StringPrintf;
using android::base::EndsWith;
+using android::base::ReadFully;
+using android::base::StringPrintf;
+using android::base::WriteFully;
using android::base::unique_fd;
namespace android {
@@ -2055,6 +2060,90 @@
}
}
+// Compute and return the hash (SHA-256) of the secondary dex file at dex_path.
+// Returns true if all parameters are valid and the hash successfully computed and stored in
+// out_secondary_dex_hash.
+// Also returns true with an empty hash if the file does not currently exist or is not accessible to
+// the app.
+// For any other errors (e.g. if any of the parameters are invalid) returns false.
+bool hash_secondary_dex_file(const std::string& dex_path, const std::string& pkgname, int uid,
+ const std::unique_ptr<std::string>& volume_uuid, int storage_flag,
+ std::vector<uint8_t>* out_secondary_dex_hash) {
+ out_secondary_dex_hash->clear();
+
+ const char* volume_uuid_cstr = volume_uuid == nullptr ? nullptr : volume_uuid->c_str();
+
+ if (storage_flag != FLAG_STORAGE_CE && storage_flag != FLAG_STORAGE_DE) {
+ LOG(ERROR) << "hash_secondary_dex_file called with invalid storage_flag: "
+ << storage_flag;
+ return false;
+ }
+
+ // Pipe to get the hash result back from our child process.
+ unique_fd pipe_read, pipe_write;
+ if (!Pipe(&pipe_read, &pipe_write)) {
+ PLOG(ERROR) << "Failed to create pipe";
+ return false;
+ }
+
+ // Fork so that actual access to the files is done in the app's own UID, to ensure we only
+ // access data the app itself can access.
+ pid_t pid = fork();
+ if (pid == 0) {
+ // child -- drop privileges before continuing
+ drop_capabilities(uid);
+ pipe_read.reset();
+
+ if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid_cstr, uid, storage_flag)) {
+ LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
+ _exit(1);
+ }
+
+ unique_fd fd(TEMP_FAILURE_RETRY(open(dex_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW)));
+ if (fd == -1) {
+ if (errno == EACCES || errno == ENOENT) {
+ // Not treated as an error.
+ _exit(0);
+ }
+ PLOG(ERROR) << "Failed to open secondary dex " << dex_path;
+ _exit(1);
+ }
+
+ SHA256_CTX ctx;
+ SHA256_Init(&ctx);
+
+ std::vector<uint8_t> buffer(65536);
+ while (true) {
+ ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
+ if (bytes_read == 0) {
+ break;
+ } else if (bytes_read == -1) {
+ PLOG(ERROR) << "Failed to read secondary dex " << dex_path;
+ _exit(1);
+ }
+
+ SHA256_Update(&ctx, buffer.data(), bytes_read);
+ }
+
+ std::array<uint8_t, SHA256_DIGEST_LENGTH> hash;
+ SHA256_Final(hash.data(), &ctx);
+ if (!WriteFully(pipe_write, hash.data(), hash.size())) {
+ _exit(1);
+ }
+
+ _exit(0);
+ }
+
+ // parent
+ pipe_write.reset();
+
+ out_secondary_dex_hash->resize(SHA256_DIGEST_LENGTH);
+ if (!ReadFully(pipe_read, out_secondary_dex_hash->data(), out_secondary_dex_hash->size())) {
+ out_secondary_dex_hash->clear();
+ }
+ return wait_child(pid) == 0;
+}
+
// Helper for move_ab, so that we can have common failure-case cleanup.
static bool unlink_and_rename(const char* from, const char* to) {
// Check whether "from" exists, and if so whether it's regular. If it is, unlink. Otherwise,
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index 8ece893..8a9ffd2 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -74,6 +74,10 @@
const std::unique_ptr<std::string>& volumeUuid, int storage_flag,
/*out*/bool* out_secondary_dex_exists);
+bool hash_secondary_dex_file(const std::string& dex_path,
+ const std::string& pkgname, int uid, const std::unique_ptr<std::string>& volume_uuid,
+ int storage_flag, std::vector<uint8_t>* out_secondary_dex_hash);
+
int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set,
int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
const char* volume_uuid, const char* class_loader_context, const char* se_info,
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index e0d23da..0c2d341 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -889,6 +889,7 @@
CHECK(EndsWith(path, "/"));
path = path + "oat";
if (access(path.c_str(), F_OK) == 0) {
+ LOG(INFO) << "Skipping A/B OTA preopt of already preopted package " << apk_path;
return true;
}
}
@@ -900,7 +901,7 @@
// this tool will wipe the OTA artifact cache and try again (for robustness after
// a failed OTA with remaining cache artifacts).
if (access(apk_path, F_OK) != 0) {
- LOG(WARNING) << "Skipping preopt of non-existing package " << apk_path;
+ LOG(WARNING) << "Skipping A/B OTA preopt of non-existing package " << apk_path;
return true;
}
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index 1a22992..47346fb 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -24,6 +24,7 @@
shared_libs: [
"libbase",
"libbinder",
+ "libcrypto",
"libcutils",
"libselinux",
"libutils",
@@ -44,6 +45,7 @@
shared_libs: [
"libbase",
"libbinder",
+ "libcrypto",
"libcutils",
"libselinux",
"libutils",
@@ -64,6 +66,7 @@
shared_libs: [
"libbase",
"libbinder",
+ "libcrypto",
"libcutils",
"libselinux",
"libutils",
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index ca812bd..a5af5d7 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <sys/statvfs.h>
@@ -56,16 +57,19 @@
return create_cache_path_default(path, src, instruction_set);
}
+static std::string get_full_path(const char* path) {
+ return StringPrintf("/data/local/tmp/user/0/%s", path);
+}
+
static void mkdir(const char* path, uid_t owner, gid_t group, mode_t mode) {
- const char* fullPath = StringPrintf("/data/local/tmp/user/0/%s", path).c_str();
- ::mkdir(fullPath, mode);
- ::chown(fullPath, owner, group);
- ::chmod(fullPath, mode);
+ const std::string fullPath = get_full_path(path);
+ ::mkdir(fullPath.c_str(), mode);
+ ::chown(fullPath.c_str(), owner, group);
+ ::chmod(fullPath.c_str(), mode);
}
static void touch(const char* path, uid_t owner, gid_t group, mode_t mode) {
- int fd = ::open(StringPrintf("/data/local/tmp/user/0/%s", path).c_str(),
- O_RDWR | O_CREAT, mode);
+ int fd = ::open(get_full_path(path).c_str(), O_RDWR | O_CREAT, mode);
::fchown(fd, owner, group);
::fchmod(fd, mode);
::close(fd);
@@ -73,13 +77,13 @@
static int stat_gid(const char* path) {
struct stat buf;
- ::stat(StringPrintf("/data/local/tmp/user/0/%s", path).c_str(), &buf);
+ ::stat(get_full_path(path).c_str(), &buf);
return buf.st_gid;
}
static int stat_mode(const char* path) {
struct stat buf;
- ::stat(StringPrintf("/data/local/tmp/user/0/%s", path).c_str(), &buf);
+ ::stat(get_full_path(path).c_str(), &buf);
return buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISGID);
}
@@ -149,6 +153,69 @@
EXPECT_EQ(10000, stat_gid("com.example/bar/file"));
}
+TEST_F(ServiceTest, HashSecondaryDex) {
+ LOG(INFO) << "HashSecondaryDex";
+
+ mkdir("com.example", 10000, 10000, 0700);
+ mkdir("com.example/foo", 10000, 10000, 0700);
+ touch("com.example/foo/file", 10000, 20000, 0700);
+
+ std::vector<uint8_t> result;
+ std::string dexPath = get_full_path("com.example/foo/file");
+ EXPECT_TRUE(service->hashSecondaryDexFile(
+ dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result).isOk());
+
+ EXPECT_EQ(result.size(), 32U);
+
+ std::ostringstream output;
+ output << std::hex << std::setfill('0');
+ for (auto b : result) {
+ output << std::setw(2) << +b;
+ }
+
+ // This is the SHA256 of an empty string (sha256sum /dev/null)
+ EXPECT_EQ(output.str(), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
+}
+
+TEST_F(ServiceTest, HashSecondaryDex_NoSuch) {
+ LOG(INFO) << "HashSecondaryDex_NoSuch";
+
+ std::vector<uint8_t> result;
+ std::string dexPath = get_full_path("com.example/foo/file");
+ EXPECT_TRUE(service->hashSecondaryDexFile(
+ dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result).isOk());
+
+ EXPECT_EQ(result.size(), 0U);
+}
+
+TEST_F(ServiceTest, HashSecondaryDex_Unreadable) {
+ LOG(INFO) << "HashSecondaryDex_Unreadable";
+
+ mkdir("com.example", 10000, 10000, 0700);
+ mkdir("com.example/foo", 10000, 10000, 0700);
+ touch("com.example/foo/file", 10000, 20000, 0300);
+
+ std::vector<uint8_t> result;
+ std::string dexPath = get_full_path("com.example/foo/file");
+ EXPECT_TRUE(service->hashSecondaryDexFile(
+ dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result).isOk());
+
+ EXPECT_EQ(result.size(), 0U);
+}
+
+TEST_F(ServiceTest, HashSecondaryDex_WrongApp) {
+ LOG(INFO) << "HashSecondaryDex_WrongApp";
+
+ mkdir("com.example", 10000, 10000, 0700);
+ mkdir("com.example/foo", 10000, 10000, 0700);
+ touch("com.example/foo/file", 10000, 20000, 0700);
+
+ std::vector<uint8_t> result;
+ std::string dexPath = get_full_path("com.example/foo/file");
+ EXPECT_FALSE(service->hashSecondaryDexFile(
+ dexPath, "com.wrong", 10000, testUuid, FLAG_STORAGE_CE, &result).isOk());
+}
+
TEST_F(ServiceTest, CalculateOat) {
char buf[PKG_PATH_MAX];
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/Status.cpp b/libs/binder/Status.cpp
index 006f7f9..a9d5055 100644
--- a/libs/binder/Status.cpp
+++ b/libs/binder/Status.cpp
@@ -102,6 +102,15 @@
}
mMessage = String8(message);
+ // Skip over the remote stack trace data
+ int32_t remote_stack_trace_header_size;
+ status = parcel.readInt32(&remote_stack_trace_header_size);
+ if (status != OK) {
+ setFromStatusT(status);
+ return status;
+ }
+ parcel.setDataPosition(parcel.dataPosition() + remote_stack_trace_header_size);
+
if (mException == EX_SERVICE_SPECIFIC) {
status = parcel.readInt32(&mErrorCode);
} else if (mException == EX_PARCELABLE) {
@@ -137,6 +146,7 @@
return status;
}
status = parcel->writeString16(String16(mMessage));
+ status = parcel->writeInt32(0); // Empty remote stack trace header
if (mException == EX_SERVICE_SPECIFIC) {
status = parcel->writeInt32(mErrorCode);
} else if (mException == EX_PARCELABLE) {
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/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 39b5829..f46e9f6 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -22,6 +22,7 @@
#include <log/log.h>
#include <nativeloader/dlext_namespaces.h>
+#include <nativeloader/native_loader.h>
// TODO(b/37049319) Get this from a header once one exists
extern "C" {
@@ -45,6 +46,32 @@
mDriverPath = path;
}
+void GraphicsEnv::setLayerPaths(android_namespace_t* appNamespace, const std::string layerPaths) {
+ if (mLayerPaths.empty()) {
+ mLayerPaths = layerPaths;
+ mAppNamespace = appNamespace;
+ } else {
+ ALOGV("Vulkan layer search path already set, not clobbering with '%s' for namespace %p'",
+ layerPaths.c_str(), appNamespace);
+ }
+}
+
+android_namespace_t* GraphicsEnv::getAppNamespace() {
+ return mAppNamespace;
+}
+
+const std::string GraphicsEnv::getLayerPaths(){
+ return mLayerPaths;
+}
+
+const std::string GraphicsEnv::getDebugLayers() {
+ return mDebugLayers;
+}
+
+void GraphicsEnv::setDebugLayers(const std::string layers) {
+ mDebugLayers = layers;
+}
+
android_namespace_t* GraphicsEnv::getDriverNamespace() {
static std::once_flag once;
std::call_once(once, [this]() {
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 7817076..213580c 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -35,10 +35,20 @@
void setDriverPath(const std::string path);
android_namespace_t* getDriverNamespace();
+ void setLayerPaths(android_namespace_t* appNamespace, const std::string layerPaths);
+ android_namespace_t* getAppNamespace();
+ const std::string getLayerPaths();
+
+ void setDebugLayers(const std::string layers);
+ const std::string getDebugLayers();
+
private:
GraphicsEnv() = default;
std::string mDriverPath;
+ std::string mDebugLayers;
+ std::string mLayerPaths;
android_namespace_t* mDriverNamespace = nullptr;
+ android_namespace_t* mAppNamespace = nullptr;
};
} // namespace android
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 8e7f814..5de84ec 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>
@@ -101,17 +100,13 @@
remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
}
- virtual status_t 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)
- {
+ virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
+ ISurfaceComposer::Rotation rotation) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
- data.writeStrongBinder(IInterface::asBinder(producer));
data.write(sourceCrop);
data.writeUint32(reqWidth);
data.writeUint32(reqHeight);
@@ -119,8 +114,45 @@
data.writeInt32(maxLayerZ);
data.writeInt32(static_cast<int32_t>(useIdentityTransform));
data.writeInt32(static_cast<int32_t>(rotation));
- remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
- return reply.readInt32();
+ status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
+
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ err = reply.readInt32();
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ *outBuffer = new GraphicBuffer();
+ reply.read(**outBuffer);
+ return err;
+ }
+
+ virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder,
+ sp<GraphicBuffer>* outBuffer, const Rect& sourceCrop,
+ float frameScale) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ data.writeStrongBinder(layerHandleBinder);
+ data.write(sourceCrop);
+ data.writeFloat(frameScale);
+ status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply);
+
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ err = reply.readInt32();
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ *outBuffer = new GraphicBuffer();
+ reply.read(**outBuffer);
+
+ return err;
}
virtual bool authenticateSurfaceTexture(
@@ -571,8 +603,7 @@
case CAPTURE_SCREEN: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> display = data.readStrongBinder();
- sp<IGraphicBufferProducer> producer =
- interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
+ sp<GraphicBuffer> outBuffer;
Rect sourceCrop(Rect::EMPTY_RECT);
data.read(sourceCrop);
uint32_t reqWidth = data.readUint32();
@@ -582,11 +613,28 @@
bool useIdentityTransform = static_cast<bool>(data.readInt32());
int32_t rotation = data.readInt32();
- status_t res = captureScreen(display, producer,
- sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
- useIdentityTransform,
- static_cast<ISurfaceComposer::Rotation>(rotation));
+ status_t res = captureScreen(display, &outBuffer, sourceCrop, reqWidth, reqHeight,
+ minLayerZ, maxLayerZ, useIdentityTransform,
+ static_cast<ISurfaceComposer::Rotation>(rotation));
reply->writeInt32(res);
+ if (res == NO_ERROR) {
+ reply->write(*outBuffer);
+ }
+ return NO_ERROR;
+ }
+ case CAPTURE_LAYERS: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ sp<IBinder> layerHandleBinder = data.readStrongBinder();
+ sp<GraphicBuffer> outBuffer;
+ Rect sourceCrop(Rect::EMPTY_RECT);
+ data.read(sourceCrop);
+ float frameScale = data.readFloat();
+
+ status_t res = captureLayers(layerHandleBinder, &outBuffer, sourceCrop, frameScale);
+ reply->writeInt32(res);
+ if (res == NO_ERROR) {
+ reply->write(*outBuffer);
+ }
return NO_ERROR;
}
case AUTHENTICATE_SURFACE: {
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..80216bc 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;
@@ -1754,4 +1760,25 @@
return OK;
}
+status_t Surface::attachAndQueueBuffer(Surface* surface, sp<GraphicBuffer> buffer) {
+ if (buffer == nullptr) {
+ return BAD_VALUE;
+ }
+ int err = static_cast<ANativeWindow*>(surface)->perform(surface, NATIVE_WINDOW_API_CONNECT,
+ NATIVE_WINDOW_API_CPU);
+ if (err != OK) {
+ return err;
+ }
+ err = surface->attachBuffer(buffer->getNativeBuffer());
+ if (err != OK) {
+ return err;
+ }
+ err = static_cast<ANativeWindow*>(surface)->queueBuffer(surface, buffer->getNativeBuffer(), -1);
+ if (err != OK) {
+ return err;
+ }
+ err = surface->disconnect(NATIVE_WINDOW_API_CPU);
+ return err;
+}
+
}; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 7ae2672..0dbe786 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)
{
@@ -940,149 +717,27 @@
// ----------------------------------------------------------------------------
-status_t ScreenshotClient::capture(
- const sp<IBinder>& display,
- const sp<IGraphicBufferProducer>& producer,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform) {
+status_t ScreenshotClient::capture(const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth,
+ uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ,
+ bool useIdentityTransform, uint32_t rotation,
+ sp<GraphicBuffer>* outBuffer) {
sp<ISurfaceComposer> s(ComposerService::getComposerService());
if (s == NULL) return NO_INIT;
- return s->captureScreen(display, producer, sourceCrop,
- reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform);
-}
-
-status_t ScreenshotClient::captureToBuffer(const sp<IBinder>& display,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
- uint32_t rotation,
- sp<GraphicBuffer>* outBuffer) {
- sp<ISurfaceComposer> s(ComposerService::getComposerService());
- if (s == NULL) return NO_INIT;
-
- sp<IGraphicBufferConsumer> gbpConsumer;
- sp<IGraphicBufferProducer> producer;
- BufferQueue::createBufferQueue(&producer, &gbpConsumer);
- sp<BufferItemConsumer> consumer(new BufferItemConsumer(gbpConsumer,
- GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_NEVER,
- 1, true));
-
- status_t ret = s->captureScreen(display, producer, sourceCrop, reqWidth, reqHeight,
- minLayerZ, maxLayerZ, useIdentityTransform,
- static_cast<ISurfaceComposer::Rotation>(rotation));
+ status_t ret = s->captureScreen(display, outBuffer, sourceCrop, reqWidth, reqHeight, minLayerZ,
+ maxLayerZ, useIdentityTransform,
+ static_cast<ISurfaceComposer::Rotation>(rotation));
if (ret != NO_ERROR) {
return ret;
}
- BufferItem b;
- consumer->acquireBuffer(&b, 0, true);
- *outBuffer = b.mGraphicBuffer;
return ret;
}
-ScreenshotClient::ScreenshotClient()
- : mHaveBuffer(false) {
- memset(&mBuffer, 0, sizeof(mBuffer));
-}
-
-ScreenshotClient::~ScreenshotClient() {
- ScreenshotClient::release();
-}
-
-sp<CpuConsumer> ScreenshotClient::getCpuConsumer() const {
- if (mCpuConsumer == NULL) {
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&mProducer, &consumer);
- mCpuConsumer = new CpuConsumer(consumer, 1);
- mCpuConsumer->setName(String8("ScreenshotClient"));
- }
- return mCpuConsumer;
-}
-
-status_t ScreenshotClient::update(const sp<IBinder>& display,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform, uint32_t rotation) {
+status_t ScreenshotClient::captureLayers(const sp<IBinder>& layerHandle, Rect sourceCrop,
+ float frameScale, sp<GraphicBuffer>* outBuffer) {
sp<ISurfaceComposer> s(ComposerService::getComposerService());
if (s == NULL) return NO_INIT;
- sp<CpuConsumer> cpuConsumer = getCpuConsumer();
-
- if (mHaveBuffer) {
- mCpuConsumer->unlockBuffer(mBuffer);
- memset(&mBuffer, 0, sizeof(mBuffer));
- mHaveBuffer = false;
- }
-
- status_t err = s->captureScreen(display, mProducer, sourceCrop,
- reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform,
- static_cast<ISurfaceComposer::Rotation>(rotation));
-
- if (err == NO_ERROR) {
- err = mCpuConsumer->lockNextBuffer(&mBuffer);
- if (err == NO_ERROR) {
- mHaveBuffer = true;
- }
- }
- return err;
+ status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale);
+ return ret;
}
-
-status_t ScreenshotClient::update(const sp<IBinder>& display,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform) {
-
- return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight,
- minLayerZ, maxLayerZ, useIdentityTransform, ISurfaceComposer::eRotateNone);
-}
-
-status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop,
- bool useIdentityTransform) {
- return ScreenshotClient::update(display, sourceCrop, 0, 0,
- INT32_MIN, INT32_MAX,
- useIdentityTransform, ISurfaceComposer::eRotateNone);
-}
-
-status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop,
- uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform) {
- return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight,
- INT32_MIN, INT32_MAX,
- useIdentityTransform, ISurfaceComposer::eRotateNone);
-}
-
-void ScreenshotClient::release() {
- if (mHaveBuffer) {
- mCpuConsumer->unlockBuffer(mBuffer);
- memset(&mBuffer, 0, sizeof(mBuffer));
- mHaveBuffer = false;
- }
- mCpuConsumer.clear();
-}
-
-void const* ScreenshotClient::getPixels() const {
- return mBuffer.data;
-}
-
-uint32_t ScreenshotClient::getWidth() const {
- return mBuffer.width;
-}
-
-uint32_t ScreenshotClient::getHeight() const {
- return mBuffer.height;
-}
-
-PixelFormat ScreenshotClient::getFormat() const {
- return mBuffer.format;
-}
-
-uint32_t ScreenshotClient::getStride() const {
- return mBuffer.stride;
-}
-
-size_t ScreenshotClient::getSize() const {
- return mBuffer.stride * mBuffer.height * bytesPerPixel(mBuffer.format);
-}
-
-android_dataspace ScreenshotClient::getDataSpace() const {
- return mBuffer.dataSpace;
-}
-
// ----------------------------------------------------------------------------
}; // namespace android
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/ConsumerBase.h b/libs/gui/include/gui/ConsumerBase.h
index e9fc8fd..4a86021 100644
--- a/libs/gui/include/gui/ConsumerBase.h
+++ b/libs/gui/include/gui/ConsumerBase.h
@@ -187,7 +187,7 @@
// ConsumerBase::releaseBufferLocked.
virtual status_t releaseBufferLocked(int slot,
const sp<GraphicBuffer> graphicBuffer,
- EGLDisplay display, EGLSyncKHR eglFence);
+ EGLDisplay display = EGL_NO_DISPLAY, EGLSyncKHR eglFence = EGL_NO_SYNC_KHR);
// returns true iff the slot still has the graphicBuffer in it.
bool stillTracking(int slot, const sp<GraphicBuffer> graphicBuffer);
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index b226742..e26e332 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -29,6 +29,7 @@
#include <ui/FrameStats.h>
#include <ui/PixelFormat.h>
+#include <ui/GraphicBuffer.h>
#include <vector>
@@ -167,12 +168,14 @@
/* Capture the specified screen. requires READ_FRAME_BUFFER permission
* This function will fail if there is a secure window on screen.
*/
- virtual status_t 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,
- Rotation rotation = eRotateNone) = 0;
+ virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
+ Rotation rotation = eRotateNone) = 0;
+
+ virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder,
+ sp<GraphicBuffer>* outBuffer, const Rect& sourceCrop,
+ float frameScale = 1.0) = 0;
/* Clears the frame statistics for animations.
*
@@ -226,6 +229,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..354f23a 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -281,6 +281,10 @@
// detachNextBuffer, or attachBuffer call.
status_t getAndFlushRemovedBuffers(std::vector<sp<GraphicBuffer>>* out);
+ android_dataspace_t getBuffersDataSpace();
+
+ static status_t attachAndQueueBuffer(Surface* surface, sp<GraphicBuffer> buffer);
+
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..3f13946 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,157 +122,173 @@
//! 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;
};
// ---------------------------------------------------------------------------
-class ScreenshotClient
-{
+class ScreenshotClient {
public:
// if cropping isn't required, callers may pass in a default Rect, e.g.:
// capture(display, producer, Rect(), reqWidth, ...);
- static status_t capture(
- const sp<IBinder>& display,
- const sp<IGraphicBufferProducer>& producer,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform);
- static status_t captureToBuffer(
- const sp<IBinder>& display,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform,
- uint32_t rotation,
- sp<GraphicBuffer>* outbuffer);
-private:
- mutable sp<CpuConsumer> mCpuConsumer;
- mutable sp<IGraphicBufferProducer> mProducer;
- CpuConsumer::LockedBuffer mBuffer;
- bool mHaveBuffer;
-
-public:
- ScreenshotClient();
- ~ScreenshotClient();
-
- // frees the previous screenshot and captures a new one
- // if cropping isn't required, callers may pass in a default Rect, e.g.:
- // update(display, Rect(), useIdentityTransform);
- status_t update(const sp<IBinder>& display,
- Rect sourceCrop, bool useIdentityTransform);
- status_t update(const sp<IBinder>& display,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- bool useIdentityTransform);
- status_t update(const sp<IBinder>& display,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform);
- status_t update(const sp<IBinder>& display,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform, uint32_t rotation);
-
- sp<CpuConsumer> getCpuConsumer() const;
-
- // release memory occupied by the screenshot
- void release();
-
- // pixels are valid until this object is freed or
- // release() or update() is called
- void const* getPixels() const;
-
- uint32_t getWidth() const;
- uint32_t getHeight() const;
- PixelFormat getFormat() const;
- uint32_t getStride() const;
- // size of allocated memory in bytes
- size_t getSize() const;
- android_dataspace getDataSpace() const;
+ static status_t capture(const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth,
+ uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ,
+ bool useIdentityTransform, uint32_t rotation,
+ sp<GraphicBuffer>* outBuffer);
+ static status_t captureLayers(const sp<IBinder>& layerHandle, Rect sourceCrop, float fameScale,
+ sp<GraphicBuffer>* outBuffer);
};
// ---------------------------------------------------------------------------
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..470a338 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);
@@ -114,14 +116,11 @@
sp<ANativeWindow> anw(mSurface);
// Verify the screenshot works with no protected buffers.
- 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));
- ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(),
+ sp<GraphicBuffer> outBuffer;
+ ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(),
64, 64, 0, 0x7fffffff, false));
ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(),
@@ -152,7 +151,7 @@
&buf));
ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1));
}
- ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(),
+ ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(),
64, 64, 0, 0x7fffffff, false));
}
@@ -522,11 +521,16 @@
status_t setActiveColorMode(const sp<IBinder>& /*display*/,
android_color_mode_t /*colorMode*/) override { return NO_ERROR; }
status_t captureScreen(const sp<IBinder>& /*display*/,
- const sp<IGraphicBufferProducer>& /*producer*/,
+ sp<GraphicBuffer>* /*outBuffer*/,
Rect /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/,
int32_t /*minLayerZ*/, int32_t /*maxLayerZ*/,
bool /*useIdentityTransform*/,
Rotation /*rotation*/) override { return NO_ERROR; }
+ virtual status_t captureLayers(const sp<IBinder>& /*parentHandle*/,
+ sp<GraphicBuffer>* /*outBuffer*/,
+ const Rect& /*sourceCrop*/, float /*frameScale*/) 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..f86f876 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";
@@ -253,11 +254,15 @@
ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent());
}
-TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountLessThan1_ReturnsError) {
+TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenSequenceNumberIsZero_ReturnsError) {
status_t status;
- const size_t pointerCount = 0;
+ const size_t pointerCount = 1;
PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
+ for (size_t i = 0; i < pointerCount; i++) {
+ pointerProperties[i].clear();
+ pointerCoords[i].clear();
+ }
status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pointerCount, pointerProperties, pointerCoords);
@@ -265,7 +270,20 @@
<< "publisher publishMotionEvent should return BAD_VALUE";
}
-TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountGreaterThanMax_ReturnsError) {
+TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountLessThan1_ReturnsError) {
+ status_t status;
+ const size_t pointerCount = 0;
+ PointerProperties pointerProperties[pointerCount];
+ PointerCoords pointerCoords[pointerCount];
+
+ status = mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ pointerCount, pointerProperties, pointerCoords);
+ ASSERT_EQ(BAD_VALUE, status)
+ << "publisher publishMotionEvent should return BAD_VALUE";
+}
+
+TEST_F(InputPublisherAndConsumerTest,
+ PublishMotionEvent_WhenPointerCountGreaterThanMax_ReturnsError) {
status_t status;
const size_t pointerCount = MAX_POINTERS + 1;
PointerProperties pointerProperties[pointerCount];
@@ -275,7 +293,7 @@
pointerCoords[i].clear();
}
- status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ status = mPublisher->publishMotionEvent(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE";
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 a2287e1..9481c37 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -29,6 +29,7 @@
sharedLibraries = [
"libbase",
+ "libbinder",
"libcutils",
"libhardware",
"liblog",
@@ -63,10 +64,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 b279875..8241809 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/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index 221bc4f..ace01a6 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -9,16 +9,6 @@
namespace dvr {
/* static */
-sp<BufferHubQueueProducer> BufferHubQueueProducer::Create() {
- sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer;
- auto config = ProducerQueueConfigBuilder()
- .SetMetadata<DvrNativeBufferMetadata>()
- .Build();
- producer->queue_ = ProducerQueue::Create(config, UsagePolicy{});
- return producer;
-}
-
-/* static */
sp<BufferHubQueueProducer> BufferHubQueueProducer::Create(
const std::shared_ptr<ProducerQueue>& queue) {
if (queue->metadata_size() != sizeof(DvrNativeBufferMetadata)) {
@@ -33,6 +23,19 @@
return producer;
}
+/* static */
+sp<BufferHubQueueProducer> BufferHubQueueProducer::Create(
+ ProducerQueueParcelable parcelable) {
+ if (!parcelable.IsValid()) {
+ ALOGE("BufferHubQueueProducer::Create: Invalid producer parcelable.");
+ return nullptr;
+ }
+
+ sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer;
+ producer->queue_ = ProducerQueue::Import(parcelable.TakeChannelHandle());
+ return producer;
+}
+
status_t BufferHubQueueProducer::requestBuffer(int slot,
sp<GraphicBuffer>* buf) {
ALOGD_IF(TRACE, "requestBuffer: slot=%d", slot);
@@ -475,6 +478,13 @@
return BAD_VALUE;
}
+ if (!queue_->is_connected()) {
+ ALOGE(
+ "BufferHubQueueProducer::connect: This BufferHubQueueProducer is not "
+ "connected to bufferhud. Has it been taken out as a parcelable?");
+ return BAD_VALUE;
+ }
+
switch (api) {
case NATIVE_WINDOW_API_EGL:
case NATIVE_WINDOW_API_CPU:
@@ -617,6 +627,39 @@
return NO_ERROR;
}
+status_t BufferHubQueueProducer::TakeAsParcelable(
+ ProducerQueueParcelable* out_parcelable) {
+ if (!out_parcelable || out_parcelable->IsValid())
+ return BAD_VALUE;
+
+ if (connected_api_ != kNoConnectedApi) {
+ ALOGE(
+ "BufferHubQueueProducer::TakeAsParcelable: BufferHubQueueProducer has "
+ "connected client. Must disconnect first.");
+ return BAD_VALUE;
+ }
+
+ if (!queue_->is_connected()) {
+ ALOGE(
+ "BufferHubQueueProducer::TakeAsParcelable: This BufferHubQueueProducer "
+ "is not connected to bufferhud. Has it been taken out as a "
+ "parcelable?");
+ return BAD_VALUE;
+ }
+
+ auto status = queue_->TakeAsParcelable();
+ if (!status) {
+ ALOGE(
+ "BufferHubQueueProducer::TakeAsParcelable: Failed to take out "
+ "ProducuerQueueParcelable from the producer queue, error: %s.",
+ status.GetErrorMessage().c_str());
+ return BAD_VALUE;
+ }
+
+ *out_parcelable = status.take();
+ return NO_ERROR;
+}
+
status_t BufferHubQueueProducer::AllocateBuffer(uint32_t width, uint32_t height,
uint32_t layer_count,
PixelFormat format,
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..5b320a4 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(); }
@@ -68,7 +74,8 @@
return available_buffers_.size() >= kMaxQueueCapacity;
}
- explicit operator bool() const { return epoll_fd_.IsValid(); }
+ // Returns whether the buffer queue is connected to bufferhubd.
+ bool is_connected() const { return !!GetChannel(); }
int GetBufferId(size_t slot) const {
return (slot < buffers_.size() && buffers_[slot]) ? buffers_[slot]->id()
@@ -337,6 +344,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/include/private/dvr/buffer_hub_queue_producer.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
index 7ed55fb..9c85048 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
@@ -3,6 +3,7 @@
#include <gui/IGraphicBufferProducer.h>
#include <private/dvr/buffer_hub_queue_client.h>
+#include <private/dvr/buffer_hub_queue_parcelable.h>
namespace android {
namespace dvr {
@@ -17,14 +18,16 @@
// that.
static constexpr int kDefaultUndequeuedBuffers = 1;
- // Create a BufferHubQueueProducer instance by creating a new producer queue.
- static sp<BufferHubQueueProducer> Create();
-
- // Create a BufferHubQueueProducer instance by importing an existing prodcuer
+ // Creates a BufferHubQueueProducer instance by importing an existing prodcuer
// queue.
static sp<BufferHubQueueProducer> Create(
const std::shared_ptr<ProducerQueue>& producer);
+ // Creates a BufferHubQueueProducer instance by importing an existing prodcuer
+ // parcelable. Note that this call takes the ownership of the parcelable
+ // object and is guaranteed to succeed if parcelable object is valid.
+ static sp<BufferHubQueueProducer> Create(ProducerQueueParcelable parcelable);
+
// See |IGraphicBufferProducer::requestBuffer|
status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override;
@@ -115,6 +118,14 @@
// See |IGraphicBufferProducer::getConsumerUsage|
status_t getConsumerUsage(uint64_t* out_usage) const override;
+ // Takes out the current producer as a binder parcelable object. Note that the
+ // producer must be disconnected to be exportable. After successful export,
+ // the producer queue can no longer be connected again. Returns NO_ERROR when
+ // takeout is successful and out_parcelable will hold the new parcelable
+ // object. Also note that out_parcelable cannot be NULL and must points to an
+ // invalid parcelable.
+ status_t TakeAsParcelable(ProducerQueueParcelable* out_parcelable);
+
private:
using LocalHandle = pdx::LocalHandle;
diff --git a/libs/vr/libbufferhubqueue/tests/Android.bp b/libs/vr/libbufferhubqueue/tests/Android.bp
index d8a9b90..abeb719 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 {
@@ -56,3 +58,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..3efa723 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 {
@@ -23,6 +25,8 @@
constexpr uint32_t kBufferLayerCount = 1;
constexpr uint32_t kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
constexpr uint64_t kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;
+constexpr int kTimeoutMs = 100;
+constexpr int kNoTimeout = 0;
class BufferHubQueueTest : public ::testing::Test {
public:
@@ -82,41 +86,49 @@
};
TEST_F(BufferHubQueueTest, TestDequeue) {
- const size_t nb_dequeue_times = 16;
+ const int64_t nb_dequeue_times = 16;
- ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<size_t>().Build(),
- UsagePolicy{}));
+ ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
// Allocate only one buffer.
AllocateBuffer();
// But dequeue multiple times.
- for (size_t i = 0; i < nb_dequeue_times; i++) {
+ for (int64_t i = 0; i < nb_dequeue_times; i++) {
size_t slot;
LocalHandle fence;
- auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
- ASSERT_TRUE(p1_status.ok());
+ DvrNativeBufferMetadata mi, mo;
+
+ // Producer gains a buffer.
+ auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
+ EXPECT_TRUE(p1_status.ok());
auto p1 = p1_status.take();
- ASSERT_NE(nullptr, p1);
- size_t mi = i;
- ASSERT_EQ(p1->Post(LocalHandle(), &mi, sizeof(mi)), 0);
- size_t mo;
- auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
- ASSERT_TRUE(c1_status.ok());
+ ASSERT_NE(p1, nullptr);
+
+ // Producer posts the buffer.
+ mi.index = i;
+ EXPECT_EQ(p1->PostAsync(&mi, LocalHandle()), 0);
+
+ // Consumer acquires a buffer.
+ auto c1_status = consumer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
+ EXPECT_TRUE(c1_status.ok());
auto c1 = c1_status.take();
- ASSERT_NE(nullptr, c1);
- ASSERT_EQ(mi, mo);
- c1->Release(LocalHandle());
+ ASSERT_NE(c1, nullptr);
+ EXPECT_EQ(mi.index, i);
+ EXPECT_EQ(mo.index, i);
+
+ // Consumer releases the buffer.
+ EXPECT_EQ(c1->ReleaseAsync(&mi, LocalHandle()), 0);
}
}
TEST_F(BufferHubQueueTest, TestProducerConsumer) {
const size_t kBufferCount = 16;
size_t slot;
- uint64_t seq;
+ DvrNativeBufferMetadata mi, mo;
+ LocalHandle fence;
- ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<uint64_t>().Build(),
- UsagePolicy{}));
+ ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
for (size_t i = 0; i < kBufferCount; i++) {
AllocateBuffer();
@@ -131,8 +143,7 @@
ASSERT_EQ(consumer_queue_->capacity(), i);
// Dequeue returns timeout since no buffer is ready to consumer, but
// this implicitly triggers buffer import and bump up |capacity|.
- LocalHandle fence;
- auto status = consumer_queue_->Dequeue(100, &slot, &seq, &fence);
+ auto status = consumer_queue_->Dequeue(kNoTimeout, &slot, &mo, &fence);
ASSERT_FALSE(status.ok());
ASSERT_EQ(ETIMEDOUT, status.error());
ASSERT_EQ(consumer_queue_->capacity(), i + 1);
@@ -142,37 +153,37 @@
LocalHandle post_fence(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
for (size_t i = 0; i < kBufferCount; i++) {
- LocalHandle fence;
-
// First time there is no buffer available to dequeue.
- auto consumer_status = consumer_queue_->Dequeue(100, &slot, &seq, &fence);
+ auto consumer_status =
+ consumer_queue_->Dequeue(kNoTimeout, &slot, &mo, &fence);
ASSERT_FALSE(consumer_status.ok());
- ASSERT_EQ(ETIMEDOUT, consumer_status.error());
+ ASSERT_EQ(consumer_status.error(), ETIMEDOUT);
// Make sure Producer buffer is POSTED so that it's ready to Accquire
// in the consumer's Dequeue() function.
- auto producer_status = producer_queue_->Dequeue(100, &slot, &fence);
+ auto producer_status =
+ producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
ASSERT_TRUE(producer_status.ok());
auto producer = producer_status.take();
ASSERT_NE(nullptr, producer);
- uint64_t seq_in = static_cast<uint64_t>(i);
- ASSERT_EQ(producer->Post(post_fence, &seq_in, sizeof(seq_in)), 0);
+ mi.index = static_cast<int64_t>(i);
+ ASSERT_EQ(producer->PostAsync(&mi, post_fence), 0);
// Second time the just the POSTED buffer should be dequeued.
- uint64_t seq_out = 0;
- consumer_status = consumer_queue_->Dequeue(100, &slot, &seq_out, &fence);
+ consumer_status = consumer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
ASSERT_TRUE(consumer_status.ok());
EXPECT_TRUE(fence.IsValid());
auto consumer = consumer_status.take();
ASSERT_NE(nullptr, consumer);
- ASSERT_EQ(seq_in, seq_out);
+ ASSERT_EQ(mi.index, mo.index);
}
}
TEST_F(BufferHubQueueTest, TestRemoveBuffer) {
ASSERT_TRUE(CreateProducerQueue(config_builder_.Build(), UsagePolicy{}));
+ DvrNativeBufferMetadata mo;
// Allocate buffers.
const size_t kBufferCount = 4u;
@@ -201,7 +212,7 @@
for (size_t i = 0; i < kBufferCount; i++) {
Entry* entry = &buffers[i];
auto producer_status = producer_queue_->Dequeue(
- /*timeout_ms=*/100, &entry->slot, &entry->fence);
+ kTimeoutMs, &entry->slot, &mo, &entry->fence);
ASSERT_TRUE(producer_status.ok());
entry->buffer = producer_status.take();
ASSERT_NE(nullptr, entry->buffer);
@@ -221,7 +232,7 @@
buffers[0].buffer = nullptr;
// Now the consumer queue should know it's gone.
- EXPECT_FALSE(WaitAndHandleOnce(consumer_queue_.get(), /*timeout_ms=*/100));
+ EXPECT_FALSE(WaitAndHandleOnce(consumer_queue_.get(), kTimeoutMs));
ASSERT_EQ(kBufferCount - 1, consumer_queue_->capacity());
// Allocate a new buffer. This should take the first empty slot.
@@ -290,126 +301,154 @@
ASSERT_NE(nullptr, silent_queue);
// Check that silent queue doesn't import buffers on creation.
- EXPECT_EQ(0, silent_queue->capacity());
+ EXPECT_EQ(silent_queue->capacity(), 0U);
// Dequeue and post a buffer.
size_t slot;
LocalHandle fence;
+ DvrNativeBufferMetadata mi, mo;
auto producer_status =
- producer_queue_->Dequeue(/*timeout_ms=*/100, &slot, &fence);
- ASSERT_TRUE(producer_status.ok());
+ producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
+ EXPECT_TRUE(producer_status.ok());
auto producer_buffer = producer_status.take();
- ASSERT_NE(nullptr, producer_buffer);
- ASSERT_EQ(0, producer_buffer->Post<void>({}));
+ ASSERT_NE(producer_buffer, nullptr);
+ EXPECT_EQ(producer_buffer->PostAsync(&mi, {}), 0);
// After post, check the number of remaining available buffers.
- EXPECT_EQ(kBufferCount - 1, producer_queue_->count());
+ EXPECT_EQ(producer_queue_->count(), kBufferCount - 1);
// Currently we expect no buffer to be available prior to calling
// WaitForBuffers/HandleQueueEvents.
// TODO(eieio): Note this behavior may change in the future.
- EXPECT_EQ(0u, silent_queue->count());
+ EXPECT_EQ(silent_queue->count(), 0U);
EXPECT_FALSE(silent_queue->HandleQueueEvents());
- EXPECT_EQ(0u, silent_queue->count());
+ EXPECT_EQ(silent_queue->count(), 0U);
// Build a new consumer queue to test multi-consumer queue features.
consumer_queue_ = silent_queue->CreateConsumerQueue();
- ASSERT_NE(nullptr, consumer_queue_);
+ ASSERT_NE(consumer_queue_, nullptr);
// Check that buffers are correctly imported on construction.
- EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
- EXPECT_EQ(1u, consumer_queue_->count());
+ EXPECT_EQ(consumer_queue_->capacity(), kBufferCount);
+ EXPECT_EQ(consumer_queue_->count(), 1U);
// Reclaim released/ignored buffers.
- ASSERT_EQ(kBufferCount - 1, producer_queue_->count());
+ EXPECT_EQ(producer_queue_->count(), kBufferCount - 1);
usleep(10000);
- WaitAndHandleOnce(producer_queue_.get(), /*timeout_ms=*/100);
- ASSERT_EQ(kBufferCount - 1, producer_queue_->count());
+ WaitAndHandleOnce(producer_queue_.get(), kTimeoutMs);
+ EXPECT_EQ(producer_queue_->count(), kBufferCount - 1);
// Post another buffer.
- producer_status = producer_queue_->Dequeue(/*timeout_ms=*/100, &slot, &fence);
- ASSERT_TRUE(producer_status.ok());
+ producer_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
+ EXPECT_TRUE(producer_status.ok());
producer_buffer = producer_status.take();
- ASSERT_NE(nullptr, producer_buffer);
- ASSERT_EQ(0, producer_buffer->Post<void>({}));
+ ASSERT_NE(producer_buffer, nullptr);
+ EXPECT_EQ(producer_buffer->PostAsync(&mi, {}), 0);
// Verify that the consumer queue receives it.
size_t consumer_queue_count = consumer_queue_->count();
- WaitAndHandleOnce(consumer_queue_.get(), /*timeout_ms=*/100);
- EXPECT_LT(consumer_queue_count, consumer_queue_->count());
+ WaitAndHandleOnce(consumer_queue_.get(), kTimeoutMs);
+ EXPECT_GT(consumer_queue_->count(), consumer_queue_count);
// Save the current consumer queue buffer count to compare after the dequeue.
consumer_queue_count = consumer_queue_->count();
// Dequeue and acquire/release (discard) buffers on the consumer end.
auto consumer_status =
- consumer_queue_->Dequeue(/*timeout_ms=*/100, &slot, &fence);
- ASSERT_TRUE(consumer_status.ok());
+ consumer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
+ EXPECT_TRUE(consumer_status.ok());
auto consumer_buffer = consumer_status.take();
- ASSERT_NE(nullptr, consumer_buffer);
+ ASSERT_NE(consumer_buffer, nullptr);
consumer_buffer->Discard();
// Buffer should be returned to the producer queue without being handled by
// the silent consumer queue.
- EXPECT_GT(consumer_queue_count, consumer_queue_->count());
- EXPECT_EQ(kBufferCount - 2, producer_queue_->count());
- EXPECT_TRUE(producer_queue_->HandleQueueEvents());
- EXPECT_EQ(kBufferCount - 1, producer_queue_->count());
+ EXPECT_LT(consumer_queue_->count(), consumer_queue_count);
+ EXPECT_EQ(producer_queue_->count(), kBufferCount - 2);
+
+ WaitAndHandleOnce(producer_queue_.get(), kTimeoutMs);
+ EXPECT_EQ(producer_queue_->count(), kBufferCount - 1);
}
-struct TestMetadata {
+struct TestUserMetadata {
char a;
int32_t b;
int64_t c;
};
-TEST_F(BufferHubQueueTest, TestMetadata) {
- ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<TestMetadata>().Build(),
- UsagePolicy{}));
+constexpr uint64_t kUserMetadataSize =
+ static_cast<uint64_t>(sizeof(TestUserMetadata));
+
+TEST_F(BufferHubQueueTest, TestUserMetadata) {
+ ASSERT_TRUE(CreateQueues(
+ config_builder_.SetMetadata<TestUserMetadata>().Build(), UsagePolicy{}));
AllocateBuffer();
- std::vector<TestMetadata> ms = {
+ std::vector<TestUserMetadata> user_metadata_list = {
{'0', 0, 0}, {'1', 10, 3333}, {'@', 123, 1000000000}};
- for (auto mi : ms) {
+ for (auto user_metadata : user_metadata_list) {
size_t slot;
LocalHandle fence;
- auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
- ASSERT_TRUE(p1_status.ok());
+ DvrNativeBufferMetadata mi, mo;
+
+ auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
+ EXPECT_TRUE(p1_status.ok());
auto p1 = p1_status.take();
- ASSERT_NE(nullptr, p1);
- ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0);
- TestMetadata mo;
- auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
- ASSERT_TRUE(c1_status.ok());
+ ASSERT_NE(p1, nullptr);
+
+ // TODO(b/69469185): Test against metadata from consumer once we implement
+ // release metadata properly.
+ // EXPECT_EQ(mo.user_metadata_ptr, 0U);
+ // EXPECT_EQ(mo.user_metadata_size, 0U);
+
+ mi.user_metadata_size = kUserMetadataSize;
+ mi.user_metadata_ptr = reinterpret_cast<uint64_t>(&user_metadata);
+ EXPECT_EQ(p1->PostAsync(&mi, {}), 0);
+ auto c1_status = consumer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
+ EXPECT_TRUE(c1_status.ok());
auto c1 = c1_status.take();
- ASSERT_EQ(mi.a, mo.a);
- ASSERT_EQ(mi.b, mo.b);
- ASSERT_EQ(mi.c, mo.c);
- c1->Release(LocalHandle(-1));
+ ASSERT_NE(c1, nullptr);
+
+ EXPECT_EQ(mo.user_metadata_size, kUserMetadataSize);
+ auto out_user_metadata =
+ reinterpret_cast<TestUserMetadata*>(mo.user_metadata_ptr);
+ EXPECT_EQ(user_metadata.a, out_user_metadata->a);
+ EXPECT_EQ(user_metadata.b, out_user_metadata->b);
+ EXPECT_EQ(user_metadata.c, out_user_metadata->c);
+
+ // When release, empty metadata is also legit.
+ mi.user_metadata_size = 0U;
+ mi.user_metadata_ptr = 0U;
+ c1->ReleaseAsync(&mi, {});
}
}
-TEST_F(BufferHubQueueTest, TestMetadataMismatch) {
- ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
- UsagePolicy{}));
+TEST_F(BufferHubQueueTest, TestUserMetadataMismatch) {
+ ASSERT_TRUE(CreateQueues(
+ config_builder_.SetMetadata<TestUserMetadata>().Build(), UsagePolicy{}));
AllocateBuffer();
- int64_t mi = 3;
+ TestUserMetadata user_metadata;
size_t slot;
LocalHandle fence;
- auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
- ASSERT_TRUE(p1_status.ok());
+ DvrNativeBufferMetadata mi, mo;
+ auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
+ EXPECT_TRUE(p1_status.ok());
auto p1 = p1_status.take();
- ASSERT_NE(nullptr, p1);
- ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0);
+ ASSERT_NE(p1, nullptr);
- int32_t mo;
- // Acquire a buffer with mismatched metadata is not OK.
- auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
- ASSERT_FALSE(c1_status.ok());
+ // Post with mismatched user metadata size will fail. But the producer buffer
+ // itself should stay untouched.
+ mi.user_metadata_ptr = reinterpret_cast<uint64_t>(&user_metadata);
+ mi.user_metadata_size = kUserMetadataSize + 1;
+ EXPECT_EQ(p1->PostAsync(&mi, {}), -E2BIG);
+ // Post with the exact same user metdata size can success.
+ mi.user_metadata_ptr = reinterpret_cast<uint64_t>(&user_metadata);
+ mi.user_metadata_size = kUserMetadataSize;
+ EXPECT_EQ(p1->PostAsync(&mi, {}), 0);
}
TEST_F(BufferHubQueueTest, TestEnqueue) {
@@ -419,32 +458,32 @@
size_t slot;
LocalHandle fence;
- auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
+ DvrNativeBufferMetadata mo;
+ auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
ASSERT_TRUE(p1_status.ok());
auto p1 = p1_status.take();
ASSERT_NE(nullptr, p1);
- int64_t mo;
producer_queue_->Enqueue(p1, slot, 0ULL);
- auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
+ auto c1_status = consumer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
ASSERT_FALSE(c1_status.ok());
}
TEST_F(BufferHubQueueTest, TestAllocateBuffer) {
- ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
- UsagePolicy{}));
+ ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
- size_t s1;
+ size_t ps1;
AllocateBuffer();
LocalHandle fence;
- auto p1_status = producer_queue_->Dequeue(100, &s1, &fence);
+ DvrNativeBufferMetadata mi, mo;
+ auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &ps1, &mo, &fence);
ASSERT_TRUE(p1_status.ok());
auto p1 = p1_status.take();
- ASSERT_NE(nullptr, p1);
+ ASSERT_NE(p1, nullptr);
// producer queue is exhausted
- size_t s2;
- auto p2_status = producer_queue_->Dequeue(100, &s2, &fence);
+ size_t ps2;
+ auto p2_status = producer_queue_->Dequeue(kTimeoutMs, &ps2, &mo, &fence);
ASSERT_FALSE(p2_status.ok());
ASSERT_EQ(ETIMEDOUT, p2_status.error());
@@ -454,41 +493,43 @@
ASSERT_EQ(producer_queue_->capacity(), 2U);
// now we can dequeue again
- p2_status = producer_queue_->Dequeue(100, &s2, &fence);
+ p2_status = producer_queue_->Dequeue(kTimeoutMs, &ps2, &mo, &fence);
ASSERT_TRUE(p2_status.ok());
auto p2 = p2_status.take();
- ASSERT_NE(nullptr, p2);
+ ASSERT_NE(p2, nullptr);
ASSERT_EQ(producer_queue_->count(), 0U);
// p1 and p2 should have different slot number
- ASSERT_NE(s1, s2);
+ ASSERT_NE(ps1, ps2);
// Consumer queue does not import buffers until |Dequeue| or |ImportBuffers|
// are called. So far consumer_queue_ should be empty.
ASSERT_EQ(consumer_queue_->count(), 0U);
int64_t seq = 1;
- ASSERT_EQ(p1->Post(LocalHandle(), seq), 0);
+ mi.index = seq;
+ ASSERT_EQ(p1->PostAsync(&mi, {}), 0);
+
size_t cs1, cs2;
- auto c1_status = consumer_queue_->Dequeue(100, &cs1, &seq, &fence);
+ auto c1_status = consumer_queue_->Dequeue(kTimeoutMs, &cs1, &mo, &fence);
ASSERT_TRUE(c1_status.ok());
auto c1 = c1_status.take();
- ASSERT_NE(nullptr, c1);
+ ASSERT_NE(c1, nullptr);
ASSERT_EQ(consumer_queue_->count(), 0U);
ASSERT_EQ(consumer_queue_->capacity(), 2U);
- ASSERT_EQ(cs1, s1);
+ ASSERT_EQ(cs1, ps1);
- ASSERT_EQ(p2->Post(LocalHandle(), seq), 0);
- auto c2_status = consumer_queue_->Dequeue(100, &cs2, &seq, &fence);
+ ASSERT_EQ(p2->PostAsync(&mi, {}), 0);
+ auto c2_status = consumer_queue_->Dequeue(kTimeoutMs, &cs2, &mo, &fence);
ASSERT_TRUE(c2_status.ok());
auto c2 = c2_status.take();
- ASSERT_NE(nullptr, c2);
- ASSERT_EQ(cs2, s2);
+ ASSERT_NE(c2, nullptr);
+ ASSERT_EQ(cs2, ps2);
}
TEST_F(BufferHubQueueTest, TestUsageSetMask) {
const uint32_t set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
- ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
- UsagePolicy{set_mask, 0, 0, 0}));
+ ASSERT_TRUE(
+ CreateQueues(config_builder_.Build(), UsagePolicy{set_mask, 0, 0, 0}));
// When allocation, leave out |set_mask| from usage bits on purpose.
auto status = producer_queue_->AllocateBuffer(
@@ -498,7 +539,8 @@
LocalHandle fence;
size_t slot;
- auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
+ DvrNativeBufferMetadata mo;
+ auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
ASSERT_TRUE(p1_status.ok());
auto p1 = p1_status.take();
ASSERT_EQ(p1->usage() & set_mask, set_mask);
@@ -506,8 +548,8 @@
TEST_F(BufferHubQueueTest, TestUsageClearMask) {
const uint32_t clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
- ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
- UsagePolicy{0, clear_mask, 0, 0}));
+ ASSERT_TRUE(
+ CreateQueues(config_builder_.Build(), UsagePolicy{0, clear_mask, 0, 0}));
// When allocation, add |clear_mask| into usage bits on purpose.
auto status = producer_queue_->AllocateBuffer(
@@ -517,10 +559,11 @@
LocalHandle fence;
size_t slot;
- auto p1_status = producer_queue_->Dequeue(100, &slot, &fence);
+ DvrNativeBufferMetadata mo;
+ auto p1_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
ASSERT_TRUE(p1_status.ok());
auto p1 = p1_status.take();
- ASSERT_EQ(0u, p1->usage() & clear_mask);
+ ASSERT_EQ(p1->usage() & clear_mask, 0U);
}
TEST_F(BufferHubQueueTest, TestUsageDenySetMask) {
@@ -598,16 +641,15 @@
EXPECT_EQ(producer_queue_->capacity(), num_buffers);
size_t slot;
- uint64_t seq;
LocalHandle fence;
pdx::Status<void> status;
pdx::Status<std::shared_ptr<BufferConsumer>> consumer_status;
pdx::Status<std::shared_ptr<BufferProducer>> producer_status;
std::shared_ptr<BufferConsumer> consumer_buffer;
std::shared_ptr<BufferProducer> producer_buffer;
+ DvrNativeBufferMetadata mi, mo;
- ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<uint64_t>().Build(),
- UsagePolicy{}));
+ ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
// Free all buffers when buffers are avaible for dequeue.
CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
@@ -616,7 +658,7 @@
// Free all buffers when one buffer is dequeued.
CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
- producer_status = producer_queue_->Dequeue(100, &slot, &fence);
+ producer_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
ASSERT_TRUE(producer_status.ok());
status = producer_queue_->FreeAllBuffers();
EXPECT_TRUE(status.ok());
@@ -624,7 +666,7 @@
// Free all buffers when all buffers are dequeued.
CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
for (size_t i = 0; i < kBufferCount; i++) {
- producer_status = producer_queue_->Dequeue(100, &slot, &fence);
+ producer_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
ASSERT_TRUE(producer_status.ok());
}
status = producer_queue_->FreeAllBuffers();
@@ -632,22 +674,22 @@
// Free all buffers when one buffer is posted.
CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
- producer_status = producer_queue_->Dequeue(100, &slot, &fence);
+ producer_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
ASSERT_TRUE(producer_status.ok());
producer_buffer = producer_status.take();
ASSERT_NE(nullptr, producer_buffer);
- ASSERT_EQ(0, producer_buffer->Post(fence, &seq, sizeof(seq)));
+ ASSERT_EQ(0, producer_buffer->PostAsync(&mi, fence));
status = producer_queue_->FreeAllBuffers();
EXPECT_TRUE(status.ok());
// Free all buffers when all buffers are posted.
CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
for (size_t i = 0; i < kBufferCount; i++) {
- producer_status = producer_queue_->Dequeue(100, &slot, &fence);
+ producer_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
ASSERT_TRUE(producer_status.ok());
producer_buffer = producer_status.take();
- ASSERT_NE(nullptr, producer_buffer);
- ASSERT_EQ(0, producer_buffer->Post(fence, &seq, sizeof(seq)));
+ ASSERT_NE(producer_buffer, nullptr);
+ ASSERT_EQ(producer_buffer->PostAsync(&mi, fence), 0);
}
status = producer_queue_->FreeAllBuffers();
EXPECT_TRUE(status.ok());
@@ -655,12 +697,12 @@
// Free all buffers when all buffers are acquired.
CHECK_NO_BUFFER_THEN_ALLOCATE(kBufferCount);
for (size_t i = 0; i < kBufferCount; i++) {
- producer_status = producer_queue_->Dequeue(100, &slot, &fence);
+ producer_status = producer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
ASSERT_TRUE(producer_status.ok());
producer_buffer = producer_status.take();
- ASSERT_NE(nullptr, producer_buffer);
- ASSERT_EQ(0, producer_buffer->Post(fence, &seq, sizeof(seq)));
- consumer_status = consumer_queue_->Dequeue(100, &slot, &seq, &fence);
+ ASSERT_NE(producer_buffer, nullptr);
+ ASSERT_EQ(producer_buffer->PostAsync(&mi, fence), 0);
+ consumer_status = consumer_queue_->Dequeue(kTimeoutMs, &slot, &mo, &fence);
ASSERT_TRUE(consumer_status.ok());
}
@@ -680,6 +722,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();
+ ASSERT_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(kTimeoutMs, &slot, &consumer_meta, &fence);
+ EXPECT_TRUE(s4.ok());
+ EXPECT_EQ(consumer_queue_->capacity(), 1U);
+
+ auto consumer = s4.take();
+ ASSERT_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();
+ ASSERT_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(kTimeoutMs, &slot, &consumer_meta, &fence);
+ EXPECT_TRUE(s3.ok());
+ EXPECT_EQ(consumer_queue_->capacity(), 1U);
+
+ auto consumer = s3.take();
+ ASSERT_NE(consumer, nullptr);
+ EXPECT_EQ(producer_meta.timestamp, consumer_meta.timestamp);
+}
+
} // namespace
} // namespace dvr
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
index 28cd63a..96f5404 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue_producer-test.cpp
@@ -3,12 +3,15 @@
#include <base/logging.h>
#include <gui/IProducerListener.h>
#include <gui/Surface.h>
+#include <pdx/default_transport/channel_parcelable.h>
#include <gtest/gtest.h>
namespace android {
namespace dvr {
+using pdx::LocalHandle;
+
namespace {
// Default dimensions before setDefaultBufferSize is called by the consumer.
@@ -92,7 +95,13 @@
ALOGD_IF(TRACE, "Begin test: %s.%s", testInfo->test_case_name(),
testInfo->name());
- mProducer = BufferHubQueueProducer::Create();
+ auto config = ProducerQueueConfigBuilder()
+ .SetMetadata<DvrNativeBufferMetadata>()
+ .Build();
+ auto queue = ProducerQueue::Create(config, UsagePolicy{});
+ ASSERT_TRUE(queue != nullptr);
+
+ mProducer = BufferHubQueueProducer::Create(std::move(queue));
ASSERT_TRUE(mProducer != nullptr);
mSurface = new Surface(mProducer, true);
ASSERT_TRUE(mSurface != nullptr);
@@ -546,6 +555,55 @@
EXPECT_EQ(NO_ERROR, mProducer->disconnect(kTestApi));
}
+TEST_F(BufferHubQueueProducerTest, TakeAsParcelable) {
+ // Connected producer cannot be taken out as a parcelable.
+ EXPECT_NO_FATAL_FAILURE(ConnectProducer());
+ ProducerQueueParcelable producer_parcelable;
+ EXPECT_EQ(mProducer->TakeAsParcelable(&producer_parcelable), BAD_VALUE);
+
+ // Create a valid dummy producer parcelable.
+ auto dummy_channel_parcelable =
+ std::make_unique<pdx::default_transport::ChannelParcelable>(
+ LocalHandle(0), LocalHandle(0), LocalHandle(0));
+ EXPECT_TRUE(dummy_channel_parcelable->IsValid());
+ ProducerQueueParcelable dummy_producer_parcelable(
+ std::move(dummy_channel_parcelable));
+ EXPECT_TRUE(dummy_producer_parcelable.IsValid());
+
+ // Disconnect producer can be taken out, but only to an invalid parcelable.
+ ASSERT_EQ(mProducer->disconnect(kTestApi), NO_ERROR);
+ EXPECT_EQ(mProducer->TakeAsParcelable(&dummy_producer_parcelable), BAD_VALUE);
+ EXPECT_FALSE(producer_parcelable.IsValid());
+ EXPECT_EQ(mProducer->TakeAsParcelable(&producer_parcelable), NO_ERROR);
+ EXPECT_TRUE(producer_parcelable.IsValid());
+
+ // Should still be able to query buffer dimension after disconnect.
+ int32_t value = -1;
+ EXPECT_EQ(NO_ERROR, mProducer->query(NATIVE_WINDOW_WIDTH, &value));
+ EXPECT_EQ(static_cast<uint32_t>(value), kDefaultWidth);
+
+ EXPECT_EQ(mProducer->query(NATIVE_WINDOW_HEIGHT, &value), NO_ERROR);
+ EXPECT_EQ(static_cast<uint32_t>(value), kDefaultHeight);
+
+ EXPECT_EQ(mProducer->query(NATIVE_WINDOW_FORMAT, &value), NO_ERROR);
+ EXPECT_EQ(value, kDefaultFormat);
+
+ // But connect to API will fail.
+ IGraphicBufferProducer::QueueBufferOutput output;
+ EXPECT_EQ(mProducer->connect(kDummyListener, kTestApi, kTestControlledByApp,
+ &output),
+ BAD_VALUE);
+
+ // Create a new producer from the parcelable and connect to kTestApi should
+ // succeed.
+ sp<BufferHubQueueProducer> new_producer =
+ BufferHubQueueProducer::Create(std::move(producer_parcelable));
+ ASSERT_TRUE(new_producer != nullptr);
+ EXPECT_EQ(new_producer->connect(kDummyListener, kTestApi,
+ kTestControlledByApp, &output),
+ NO_ERROR);
+}
+
} // 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 8213ca2..69dbc84 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 6a46876..7c32dbb 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/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index ac68a5e..a18ff1a 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -38,10 +38,12 @@
namespace dvr {
DisplayService::DisplayService(Hwc2::Composer* hidl,
+ hwc2_display_t primary_display_id,
RequestDisplayCallback request_display_callback)
: BASE("DisplayService",
Endpoint::Create(display::DisplayProtocol::kClientPath)) {
- hardware_composer_.Initialize(hidl, request_display_callback);
+ hardware_composer_.Initialize(
+ hidl, primary_display_id, request_display_callback);
}
bool DisplayService::IsInitialized() const {
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index 55e33ab..a3ee7bb 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -81,6 +81,7 @@
using RequestDisplayCallback = std::function<void(bool)>;
DisplayService(android::Hwc2::Composer* hidl,
+ hwc2_display_t primary_display_id,
RequestDisplayCallback request_display_callback);
pdx::Status<BorrowedNativeBufferHandle> OnGetGlobalBuffer(
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index fb69d5c..be17ecf 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -121,7 +121,8 @@
}
bool HardwareComposer::Initialize(
- Hwc2::Composer* composer, RequestDisplayCallback request_display_callback) {
+ Hwc2::Composer* composer, hwc2_display_t primary_display_id,
+ RequestDisplayCallback request_display_callback) {
if (initialized_) {
ALOGE("HardwareComposer::Initialize: already initialized.");
return false;
@@ -134,7 +135,7 @@
HWC::Error error = HWC::Error::None;
Hwc2::Config config;
- error = composer->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
+ error = composer->getActiveConfig(primary_display_id, &config);
if (error != HWC::Error::None) {
ALOGE("HardwareComposer: Failed to get current display config : %d",
@@ -142,7 +143,7 @@
return false;
}
- error = GetDisplayMetrics(composer, HWC_DISPLAY_PRIMARY, config,
+ error = GetDisplayMetrics(composer, primary_display_id, config,
&native_display_metrics_);
if (error != HWC::Error::None) {
@@ -233,7 +234,10 @@
composer_.reset(new Hwc2::Composer("default"));
composer_callback_ = new ComposerCallback;
composer_->registerCallback(composer_callback_);
+ LOG_ALWAYS_FATAL_IF(!composer_callback_->HasDisplayId(),
+ "Registered composer callback but didn't get primary display");
Layer::SetComposer(composer_.get());
+ Layer::SetDisplayId(composer_callback_->GetDisplayId());
} else {
SetPowerMode(true);
}
@@ -263,6 +267,7 @@
composer_callback_ = nullptr;
composer_.reset(nullptr);
Layer::SetComposer(nullptr);
+ Layer::SetDisplayId(0);
} else {
SetPowerMode(false);
}
@@ -290,7 +295,7 @@
HWC::Error HardwareComposer::EnableVsync(bool enabled) {
return composer_->setVsyncEnabled(
- HWC_DISPLAY_PRIMARY,
+ composer_callback_->GetDisplayId(),
(Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE
: HWC2_VSYNC_DISABLE));
}
@@ -298,7 +303,8 @@
HWC::Error HardwareComposer::SetPowerMode(bool active) {
HWC::PowerMode power_mode = active ? HWC::PowerMode::On : HWC::PowerMode::Off;
return composer_->setPowerMode(
- HWC_DISPLAY_PRIMARY, power_mode.cast<Hwc2::IComposerClient::PowerMode>());
+ composer_callback_->GetDisplayId(),
+ power_mode.cast<Hwc2::IComposerClient::PowerMode>());
}
HWC::Error HardwareComposer::Present(hwc2_display_t display) {
@@ -419,7 +425,7 @@
layer.Prepare();
}
- HWC::Error error = Validate(HWC_DISPLAY_PRIMARY);
+ HWC::Error error = Validate(composer_callback_->GetDisplayId());
if (error != HWC::Error::None) {
ALOGE("HardwareComposer::PostLayers: Validate failed: %s",
error.to_string().c_str());
@@ -466,7 +472,7 @@
}
#endif
- error = Present(HWC_DISPLAY_PRIMARY);
+ error = Present(composer_callback_->GetDisplayId());
if (error != HWC::Error::None) {
ALOGE("HardwareComposer::PostLayers: Present failed: %s",
error.to_string().c_str());
@@ -475,8 +481,8 @@
std::vector<Hwc2::Layer> out_layers;
std::vector<int> out_fences;
- error = composer_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
- &out_fences);
+ error = composer_->getReleaseFences(composer_callback_->GetDisplayId(),
+ &out_layers, &out_fences);
ALOGE_IF(error != HWC::Error::None,
"HardwareComposer::PostLayers: Failed to get release fences: %s",
error.to_string().c_str());
@@ -570,6 +576,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;
}
}
@@ -612,14 +621,6 @@
}
}
-Status<int64_t> HardwareComposer::GetVSyncTime() {
- auto status = composer_callback_->GetVsyncTime(HWC_DISPLAY_PRIMARY);
- ALOGE_IF(!status,
- "HardwareComposer::GetVSyncTime: Failed to get vsync timestamp: %s",
- status.GetErrorMessage().c_str());
- return status;
-}
-
// Waits for the next vsync and returns the timestamp of the vsync event. If
// vsync already passed since the last call, returns the latest vsync timestamp
// instead of blocking.
@@ -792,8 +793,7 @@
// Signal all of the vsync clients. Because absolute time is used for the
// wakeup time below, this can take a little time if necessary.
if (vsync_callback_)
- vsync_callback_(HWC_DISPLAY_PRIMARY, vsync_timestamp,
- /*frame_time_estimate*/ 0, vsync_count_);
+ vsync_callback_(vsync_timestamp, /*frame_time_estimate*/ 0, vsync_count_);
{
// Sleep until shortly before vsync.
@@ -816,7 +816,7 @@
// If the layer config changed we need to validateDisplay() even if
// we're going to drop the frame, to flush the Composer object's
// internal command buffer and apply our layer changes.
- Validate(HWC_DISPLAY_PRIMARY);
+ Validate(composer_callback_->GetDisplayId());
}
continue;
}
@@ -824,7 +824,7 @@
}
{
- auto status = GetVSyncTime();
+ auto status = composer_callback_->GetVsyncTime();
if (!status) {
ALOGE("HardwareComposer::PostThread: Failed to get VSYNC time: %s",
status.GetErrorMessage().c_str());
@@ -943,10 +943,17 @@
}
Return<void> HardwareComposer::ComposerCallback::onHotplug(
- Hwc2::Display display, IComposerCallback::Connection /*conn*/) {
- // See if the driver supports the vsync_event node in sysfs.
- if (display < HWC_NUM_PHYSICAL_DISPLAY_TYPES &&
- !displays_[display].driver_vsync_event_fd) {
+ Hwc2::Display display, IComposerCallback::Connection conn) {
+ // Our first onHotplug callback is always for the primary display.
+ //
+ // Ignore any other hotplug callbacks since the primary display is never
+ // disconnected and we don't care about other displays.
+ if (!has_display_id_) {
+ LOG_ALWAYS_FATAL_IF(conn != IComposerCallback::Connection::CONNECTED,
+ "Initial onHotplug callback should be primary display connected");
+ has_display_id_ = true;
+ display_id_ = display;
+
std::array<char, 1024> buffer;
snprintf(buffer.data(), buffer.size(),
"/sys/class/graphics/fb%" PRIu64 "/vsync_event", display);
@@ -955,7 +962,7 @@
"HardwareComposer::ComposerCallback::onHotplug: Driver supports "
"vsync_event node for display %" PRIu64,
display);
- displays_[display].driver_vsync_event_fd = std::move(handle);
+ driver_vsync_event_fd_ = std::move(handle);
} else {
ALOGI(
"HardwareComposer::ComposerCallback::onHotplug: Driver does not "
@@ -974,36 +981,23 @@
Return<void> HardwareComposer::ComposerCallback::onVsync(Hwc2::Display display,
int64_t timestamp) {
- TRACE_FORMAT("vsync_callback|display=%" PRIu64 ";timestamp=%" PRId64 "|",
- display, timestamp);
- if (display < HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
- displays_[display].callback_vsync_timestamp = timestamp;
- } else {
- ALOGW(
- "HardwareComposer::ComposerCallback::onVsync: Received vsync on "
- "non-physical display: display=%" PRId64,
- display);
+ // Ignore any onVsync callbacks for the non-primary display.
+ if (has_display_id_ && display == display_id_) {
+ TRACE_FORMAT("vsync_callback|display=%" PRIu64 ";timestamp=%" PRId64 "|",
+ display, timestamp);
+ callback_vsync_timestamp_ = timestamp;
}
return Void();
}
-Status<int64_t> HardwareComposer::ComposerCallback::GetVsyncTime(
- Hwc2::Display display) {
- if (display >= HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
- ALOGE(
- "HardwareComposer::ComposerCallback::GetVsyncTime: Invalid physical "
- "display requested: display=%" PRIu64,
- display);
- return ErrorStatus(EINVAL);
- }
-
+Status<int64_t> HardwareComposer::ComposerCallback::GetVsyncTime() {
// See if the driver supports direct vsync events.
- LocalHandle& event_fd = displays_[display].driver_vsync_event_fd;
+ LocalHandle& event_fd = driver_vsync_event_fd_;
if (!event_fd) {
// Fall back to returning the last timestamp returned by the vsync
// callback.
std::lock_guard<std::mutex> autolock(vsync_mutex_);
- return displays_[display].callback_vsync_timestamp;
+ return callback_vsync_timestamp_;
}
// When the driver supports the vsync_event sysfs node we can use it to
@@ -1053,10 +1047,11 @@
Hwc2::Composer* Layer::composer_{nullptr};
HWCDisplayMetrics Layer::display_metrics_{0, 0, {0, 0}, 0};
+hwc2_display_t Layer::display_id_{0};
void Layer::Reset() {
if (hardware_composer_layer_) {
- composer_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
+ composer_->destroyLayer(display_id_, hardware_composer_layer_);
hardware_composer_layer_ = 0;
}
@@ -1151,17 +1146,16 @@
pending_visibility_settings_ = false;
HWC::Error error;
- hwc2_display_t display = HWC_DISPLAY_PRIMARY;
error = composer_->setLayerBlendMode(
- display, hardware_composer_layer_,
+ display_id_, hardware_composer_layer_,
blending_.cast<Hwc2::IComposerClient::BlendMode>());
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting layer blend mode: %s",
error.to_string().c_str());
- error =
- composer_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
+ error = composer_->setLayerZOrder(display_id_, hardware_composer_layer_,
+ z_order_);
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting z_ order: %s",
error.to_string().c_str());
@@ -1170,36 +1164,35 @@
void Layer::UpdateLayerSettings() {
HWC::Error error;
- hwc2_display_t display = HWC_DISPLAY_PRIMARY;
UpdateVisibilitySettings();
// TODO(eieio): Use surface attributes or some other mechanism to control
// the layer display frame.
error = composer_->setLayerDisplayFrame(
- display, hardware_composer_layer_,
+ display_id_, hardware_composer_layer_,
{0, 0, display_metrics_.width, display_metrics_.height});
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting layer display frame: %s",
error.to_string().c_str());
error = composer_->setLayerVisibleRegion(
- display, hardware_composer_layer_,
+ display_id_, hardware_composer_layer_,
{{0, 0, display_metrics_.width, display_metrics_.height}});
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting layer visible region: %s",
error.to_string().c_str());
- error =
- composer_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
+ error = composer_->setLayerPlaneAlpha(display_id_, hardware_composer_layer_,
+ 1.0f);
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting layer plane alpha: %s",
error.to_string().c_str());
}
void Layer::CommonLayerSetup() {
- HWC::Error error =
- composer_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
+ HWC::Error error = composer_->createLayer(display_id_,
+ &hardware_composer_layer_);
ALOGE_IF(error != HWC::Error::None,
"Layer::CommonLayerSetup: Failed to create layer on primary "
"display: %s",
@@ -1243,10 +1236,10 @@
if (composition_type_ == HWC::Composition::Invalid) {
composition_type_ = HWC::Composition::SolidColor;
composer_->setLayerCompositionType(
- HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+ display_id_, hardware_composer_layer_,
composition_type_.cast<Hwc2::IComposerClient::Composition>());
Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0};
- composer_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+ composer_->setLayerColor(display_id_, hardware_composer_layer_,
layer_color);
} else {
// The composition type is already set. Nothing else to do until a
@@ -1256,7 +1249,7 @@
if (composition_type_ != target_composition_type_) {
composition_type_ = target_composition_type_;
composer_->setLayerCompositionType(
- HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+ display_id_, hardware_composer_layer_,
composition_type_.cast<Hwc2::IComposerClient::Composition>());
}
@@ -1267,7 +1260,7 @@
HWC::Error error{HWC::Error::None};
error =
- composer_->setLayerBuffer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+ composer_->setLayerBuffer(display_id_, hardware_composer_layer_,
slot, handle, acquire_fence_.Get());
ALOGE_IF(error != HWC::Error::None,
@@ -1277,7 +1270,7 @@
if (!surface_rect_functions_applied_) {
const float float_right = right;
const float float_bottom = bottom;
- error = composer_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
+ error = composer_->setLayerSourceCrop(display_id_,
hardware_composer_layer_,
{0, 0, float_right, float_bottom});
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index 7010db9..9ed4b22 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -152,6 +152,11 @@
display_metrics_ = display_metrics;
}
+ // Sets the display id used by all Layer instances.
+ static void SetDisplayId(hwc2_display_t display_id) {
+ display_id_ = display_id;
+ }
+
private:
void CommonLayerSetup();
@@ -180,6 +185,11 @@
// thereafter.
static HWCDisplayMetrics display_metrics_;
+ // Id of the primary display. Shared by all instances of Layer. This must be
+ // set whenever the primary display id changes. This can be left unset as long
+ // as there are no instances of Layer that might need to use it.
+ static hwc2_display_t display_id_;
+
// The hardware composer layer and metrics to use during the prepare cycle.
hwc2_layer_t hardware_composer_layer_ = 0;
@@ -298,13 +308,14 @@
class HardwareComposer {
public:
// Type for vsync callback.
- using VSyncCallback = std::function<void(int, int64_t, int64_t, uint32_t)>;
+ using VSyncCallback = std::function<void(int64_t, int64_t, uint32_t)>;
using RequestDisplayCallback = std::function<void(bool)>;
HardwareComposer();
~HardwareComposer();
bool Initialize(Hwc2::Composer* composer,
+ hwc2_display_t primary_display_id,
RequestDisplayCallback request_display_callback);
bool IsInitialized() const { return initialized_; }
@@ -362,16 +373,16 @@
hardware::Return<void> onVsync(Hwc2::Display display,
int64_t timestamp) override;
- pdx::Status<int64_t> GetVsyncTime(Hwc2::Display display);
+ bool HasDisplayId() { return has_display_id_; }
+ hwc2_display_t GetDisplayId() { return display_id_; }
+ pdx::Status<int64_t> GetVsyncTime();
private:
std::mutex vsync_mutex_;
-
- struct Display {
- pdx::LocalHandle driver_vsync_event_fd;
- int64_t callback_vsync_timestamp{0};
- };
- std::array<Display, HWC_NUM_PHYSICAL_DISPLAY_TYPES> displays_;
+ bool has_display_id_ = false;
+ hwc2_display_t display_id_;
+ pdx::LocalHandle driver_vsync_event_fd_;
+ int64_t callback_vsync_timestamp_{0};
};
HWC::Error Validate(hwc2_display_t display);
@@ -412,7 +423,6 @@
// kPostThreadInterrupted.
int ReadWaitPPState();
pdx::Status<int64_t> WaitForVSync();
- pdx::Status<int64_t> GetVSyncTime();
int SleepUntil(int64_t wakeup_timestamp);
// Reconfigures the layer stack if the display surfaces changed since the last
diff --git a/libs/vr/libvrflinger/include/dvr/vr_flinger.h b/libs/vr/libvrflinger/include/dvr/vr_flinger.h
index 33cbc84..c740dde 100644
--- a/libs/vr/libvrflinger/include/dvr/vr_flinger.h
+++ b/libs/vr/libvrflinger/include/dvr/vr_flinger.h
@@ -4,6 +4,12 @@
#include <thread>
#include <memory>
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
#include <pdx/service_dispatcher.h>
#include <vr/vr_manager/vr_manager.h>
@@ -21,7 +27,9 @@
public:
using RequestDisplayCallback = std::function<void(bool)>;
static std::unique_ptr<VrFlinger> Create(
- Hwc2::Composer* hidl, RequestDisplayCallback request_display_callback);
+ Hwc2::Composer* hidl,
+ hwc2_display_t primary_display_id,
+ RequestDisplayCallback request_display_callback);
~VrFlinger();
// These functions are all called on surface flinger's main thread.
@@ -35,6 +43,7 @@
private:
VrFlinger();
bool Init(Hwc2::Composer* hidl,
+ hwc2_display_t primary_display_id,
RequestDisplayCallback request_display_callback);
// Needs to be a separate class for binder's ref counting
diff --git a/libs/vr/libvrflinger/vr_flinger.cpp b/libs/vr/libvrflinger/vr_flinger.cpp
index 85dc586..5e7abd7 100644
--- a/libs/vr/libvrflinger/vr_flinger.cpp
+++ b/libs/vr/libvrflinger/vr_flinger.cpp
@@ -29,9 +29,10 @@
namespace dvr {
std::unique_ptr<VrFlinger> VrFlinger::Create(
- Hwc2::Composer* hidl, RequestDisplayCallback request_display_callback) {
+ Hwc2::Composer* hidl, hwc2_display_t primary_display_id,
+ RequestDisplayCallback request_display_callback) {
std::unique_ptr<VrFlinger> vr_flinger(new VrFlinger);
- if (vr_flinger->Init(hidl, request_display_callback))
+ if (vr_flinger->Init(hidl, primary_display_id, request_display_callback))
return vr_flinger;
else
return nullptr;
@@ -56,6 +57,7 @@
}
bool VrFlinger::Init(Hwc2::Composer* hidl,
+ hwc2_display_t primary_display_id,
RequestDisplayCallback request_display_callback) {
if (!hidl || !request_display_callback)
return false;
@@ -74,8 +76,8 @@
dispatcher_ = android::pdx::ServiceDispatcher::Create();
CHECK_ERROR(!dispatcher_, error, "Failed to create service dispatcher.");
- display_service_ =
- android::dvr::DisplayService::Create(hidl, request_display_callback);
+ display_service_ = android::dvr::DisplayService::Create(
+ hidl, primary_display_id, request_display_callback);
CHECK_ERROR(!display_service_, error, "Failed to create display service.");
dispatcher_->AddService(display_service_);
@@ -91,7 +93,7 @@
std::bind(&android::dvr::VSyncService::VSyncEvent,
std::static_pointer_cast<android::dvr::VSyncService>(service),
std::placeholders::_1, std::placeholders::_2,
- std::placeholders::_3, std::placeholders::_4));
+ std::placeholders::_3));
dispatcher_thread_ = std::thread([this]() {
prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrDispatch"), 0, 0, 0);
diff --git a/libs/vr/libvrflinger/vsync_service.cpp b/libs/vr/libvrflinger/vsync_service.cpp
index fdeb899..b8d8b08 100644
--- a/libs/vr/libvrflinger/vsync_service.cpp
+++ b/libs/vr/libvrflinger/vsync_service.cpp
@@ -32,21 +32,19 @@
VSyncService::~VSyncService() {}
-void VSyncService::VSyncEvent(int display, int64_t timestamp_ns,
+void VSyncService::VSyncEvent(int64_t timestamp_ns,
int64_t compositor_time_ns,
uint32_t vsync_count) {
ATRACE_NAME("VSyncService::VSyncEvent");
std::lock_guard<std::mutex> autolock(mutex_);
- if (display == HWC_DISPLAY_PRIMARY) {
- last_vsync_ = current_vsync_;
- current_vsync_ = timestamp_ns;
- compositor_time_ns_ = compositor_time_ns;
- current_vsync_count_ = vsync_count;
+ last_vsync_ = current_vsync_;
+ current_vsync_ = timestamp_ns;
+ compositor_time_ns_ = compositor_time_ns;
+ current_vsync_count_ = vsync_count;
- NotifyWaiters();
- UpdateClients();
- }
+ NotifyWaiters();
+ UpdateClients();
}
std::shared_ptr<Channel> VSyncService::OnChannelOpen(pdx::Message& message) {
diff --git a/libs/vr/libvrflinger/vsync_service.h b/libs/vr/libvrflinger/vsync_service.h
index 215948e..822f02b 100644
--- a/libs/vr/libvrflinger/vsync_service.h
+++ b/libs/vr/libvrflinger/vsync_service.h
@@ -63,9 +63,10 @@
const std::shared_ptr<pdx::Channel>& channel) override;
// Called by the hardware composer HAL, or similar, whenever a vsync event
- // occurs. |compositor_time_ns| is the number of ns before the next vsync when
- // the compositor will preempt the GPU to do EDS and lens warp.
- void VSyncEvent(int display, int64_t timestamp_ns, int64_t compositor_time_ns,
+ // occurs on the primary display. |compositor_time_ns| is the number of ns
+ // before the next vsync when the compositor will preempt the GPU to do EDS
+ // and lens warp.
+ void VSyncEvent(int64_t timestamp_ns, int64_t compositor_time_ns,
uint32_t vsync_count);
private:
diff --git a/libs/vr/libvrsensor/Android.bp b/libs/vr/libvrsensor/Android.bp
index e92178a..fe54b4b 100644
--- a/libs/vr/libvrsensor/Android.bp
+++ b/libs/vr/libvrsensor/Android.bp
@@ -14,7 +14,6 @@
sourceFiles = [
"pose_client.cpp",
- "sensor_client.cpp",
"latency_model.cpp",
]
@@ -33,6 +32,7 @@
sharedLibraries = [
"libbase",
+ "libbinder",
"libcutils",
"libhardware",
"liblog",
diff --git a/libs/vr/libvrsensor/include/private/dvr/sensor-ipc.h b/libs/vr/libvrsensor/include/private/dvr/sensor-ipc.h
deleted file mode 100644
index b2ebd95..0000000
--- a/libs/vr/libvrsensor/include/private/dvr/sensor-ipc.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef ANDROID_DVR_SENSOR_IPC_H_
-#define ANDROID_DVR_SENSOR_IPC_H_
-
-#define DVR_SENSOR_SERVICE_BASE "system/vr/sensors"
-
-#define DVR_SENSOR_SERVICE_CLIENT (DVR_SENSOR_SERVICE_BASE "/client")
-
-/*
- * Endpoint ops
- */
-enum {
- DVR_SENSOR_START = 0,
- DVR_SENSOR_STOP,
- DVR_SENSOR_POLL,
-};
-
-#endif // ANDROID_DVR_SENSOR_IPC_H_
diff --git a/libs/vr/libvrsensor/include/private/dvr/sensor_client.h b/libs/vr/libvrsensor/include/private/dvr/sensor_client.h
deleted file mode 100644
index 15a9b8f..0000000
--- a/libs/vr/libvrsensor/include/private/dvr/sensor_client.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef ANDROID_DVR_SENSOR_CLIENT_H_
-#define ANDROID_DVR_SENSOR_CLIENT_H_
-
-#include <hardware/sensors.h>
-#include <pdx/client.h>
-#include <poll.h>
-
-namespace android {
-namespace dvr {
-
-// SensorClient is a remote interface to the sensor service in sensord.
-class SensorClient : public pdx::ClientBase<SensorClient> {
- public:
- ~SensorClient();
-
- int StartSensor();
- int StopSensor();
- int Poll(sensors_event_t* events, int max_count);
-
- private:
- friend BASE;
-
- // Set up a channel associated with the sensor of the indicated type.
- // NOTE(segal): If our hardware ends up with multiple sensors of the same
- // type, we'll have to change this.
- explicit SensorClient(int sensor_type);
-
- int sensor_type_;
-
- SensorClient(const SensorClient&);
- SensorClient& operator=(const SensorClient&);
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_SENSOR_CLIENT_H_
diff --git a/libs/vr/libvrsensor/sensor_client.cpp b/libs/vr/libvrsensor/sensor_client.cpp
deleted file mode 100644
index 04e88cc..0000000
--- a/libs/vr/libvrsensor/sensor_client.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-#define LOG_TAG "SensorClient"
-#include <private/dvr/sensor_client.h>
-
-#include <log/log.h>
-#include <poll.h>
-
-#include <pdx/default_transport/client_channel_factory.h>
-#include <private/dvr/sensor-ipc.h>
-
-using android::pdx::Transaction;
-
-namespace android {
-namespace dvr {
-
-SensorClient::SensorClient(int sensor_type)
- : BASE(pdx::default_transport::ClientChannelFactory::Create(
- DVR_SENSOR_SERVICE_CLIENT)),
- sensor_type_(sensor_type) {}
-
-SensorClient::~SensorClient() {}
-
-int SensorClient::StartSensor() {
- Transaction trans{*this};
- auto status = trans.Send<int>(DVR_SENSOR_START, &sensor_type_,
- sizeof(sensor_type_), nullptr, 0);
- ALOGE_IF(!status, "startSensor() failed because: %s\n",
- status.GetErrorMessage().c_str());
- return ReturnStatusOrError(status);
-}
-
-int SensorClient::StopSensor() {
- Transaction trans{*this};
- auto status = trans.Send<int>(DVR_SENSOR_STOP);
- ALOGE_IF(!status, "stopSensor() failed because: %s\n",
- status.GetErrorMessage().c_str());
- return ReturnStatusOrError(status);
-}
-
-int SensorClient::Poll(sensors_event_t* events, int max_events) {
- int num_events = 0;
- struct iovec rvec[] = {
- {.iov_base = &num_events, .iov_len = sizeof(int)},
- {.iov_base = events, .iov_len = max_events * sizeof(sensors_event_t)},
- };
- Transaction trans{*this};
- auto status = trans.SendVector<int>(DVR_SENSOR_POLL, nullptr, rvec);
- ALOGE_IF(!status, "Sensor poll() failed because: %s\n",
- status.GetErrorMessage().c_str());
- return !status ? -status.error() : num_events;
-}
-
-} // namespace dvr
-} // namespace android
-
-// Entrypoints to simplify using the library when programmatically dynamicly
-// loading it.
-// Allows us to call this library without linking it, as, for instance,
-// when compiling GVR in Google3.
-// NOTE(segal): It's kind of a hack.
-
-extern "C" uint64_t dvrStartSensor(int type) {
- android::dvr::SensorClient* service =
- android::dvr::SensorClient::Create(type).release();
- service->StartSensor();
- return (uint64_t)service;
-}
-
-extern "C" void dvrStopSensor(uint64_t service) {
- android::dvr::SensorClient* iss =
- reinterpret_cast<android::dvr::SensorClient*>(service);
- iss->StopSensor();
- delete iss;
-}
-
-extern "C" int dvrPollSensor(uint64_t service, int max_count,
- sensors_event_t* events) {
- return reinterpret_cast<android::dvr::SensorClient*>(service)->Poll(
- events, max_count);
-}
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/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..deead06 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -14,17 +14,21 @@
FrameTracker.cpp \
GpuService.cpp \
Layer.cpp \
- LayerDim.cpp \
+ BufferLayer.cpp \
+ ColorLayer.cpp \
LayerRejecter.cpp \
LayerVector.cpp \
MessageQueue.cpp \
MonitoredProducer.cpp \
+ SurfaceFlinger.cpp \
SurfaceFlingerConsumer.cpp \
SurfaceInterceptor.cpp \
+ SurfaceTracing.cpp \
Transform.cpp \
DisplayHardware/ComposerHal.cpp \
DisplayHardware/FramebufferSurface.cpp \
DisplayHardware/HWC2.cpp \
+ DisplayHardware/HWComposer.cpp \
DisplayHardware/HWComposerBufferCache.cpp \
DisplayHardware/PowerHAL.cpp \
DisplayHardware/VirtualDisplaySurface.cpp \
@@ -37,8 +41,11 @@
RenderEngine/ProgramCache.cpp \
RenderEngine/GLExtensions.cpp \
RenderEngine/RenderEngine.cpp \
+ RenderEngine/Surface.cpp \
RenderEngine/Texture.cpp \
RenderEngine/GLES20RenderEngine.cpp \
+ LayerProtoHelper.cpp \
+ RenderArea.cpp \
LOCAL_MODULE := libsurfaceflinger
LOCAL_C_INCLUDES := \
@@ -49,17 +56,6 @@
LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-ifeq ($(TARGET_USES_HWC2),true)
- LOCAL_CFLAGS += -DUSE_HWC2
- LOCAL_SRC_FILES += \
- SurfaceFlinger.cpp \
- DisplayHardware/HWComposer.cpp
-else
- LOCAL_SRC_FILES += \
- SurfaceFlinger_hwc1.cpp \
- DisplayHardware/HWComposer_hwc1.cpp
-endif
-
LOCAL_CFLAGS += -fvisibility=hidden -Werror=format
LOCAL_STATIC_LIBRARIES := \
@@ -67,7 +63,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 +94,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 \
@@ -120,10 +120,6 @@
LOCAL_INIT_RC := surfaceflinger.rc
-ifeq ($(TARGET_USES_HWC2),true)
- LOCAL_CFLAGS += -DUSE_HWC2
-endif
-
LOCAL_SRC_FILES := \
main_surfaceflinger.cpp
@@ -142,10 +138,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
@@ -153,7 +151,7 @@
LOCAL_32_BIT_ONLY := true
endif
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
+LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code -std=c++1z
include $(BUILD_EXECUTABLE)
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
new file mode 100644
index 0000000..0d947b1
--- /dev/null
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -0,0 +1,954 @@
+/*
+ * 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) {
+ ALOGV("Creating Layer %s", name.string());
+
+ 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);
+
+ if (!getBE().mHwcLayers.empty()) {
+ ALOGE("Found stale hardware composer layers when destroying "
+ "surface flinger layer %s",
+ mName.string());
+ destroyAllHwcLayers();
+ }
+}
+
+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>& buffer(getBE().mBuffer);
+ return (buffer != 0) &&
+ (buffer->getUsage() & GRALLOC_USAGE_PROTECTED);
+}
+
+bool BufferLayer::isVisible() const {
+ return !(isHiddenByPolicy()) && getAlpha() > 0.0f &&
+ (getBE().mBuffer != NULL || getBE().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(getBE().mBuffer == 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(getBE().mBuffer->getWidth(),
+ getBE().mBuffer->getHeight());
+ mTexture.setFiltering(useFiltering);
+ mTexture.setMatrix(textureMatrix);
+
+ engine.setupLayerTexturing(mTexture);
+ } else {
+ engine.setupLayerBlackedOut();
+ }
+ drawWithOpenGL(renderArea, useIdentityTransform);
+ engine.disableTexturing();
+}
+
+void BufferLayer::onLayerDisplayed(const sp<Fence>& releaseFence) {
+ mSurfaceFlingerConsumer->setReleaseFence(releaseFence);
+}
+
+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();
+}
+
+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));
+ }
+}
+
+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();
+ // replicated in LayerBE until FE/BE is ready to be synchronized
+ getBE().mSidebandStream = mSidebandStream;
+ if (getBE().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> oldBuffer = getBE().mBuffer;
+
+ 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
+ getBE().mBuffer =
+ mSurfaceFlingerConsumer->getCurrentBuffer(&getBE().mBufferSlot);
+ // replicated in LayerBE until FE/BE is ready to be synchronized
+ mActiveBuffer = getBE().mBuffer;
+ if (getBE().mBuffer == 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);
+ }
+
+ mRefreshPending = true;
+ mFrameLatencyNeeded = true;
+ if (oldBuffer == 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 (oldBuffer != NULL) {
+ uint32_t bufWidth = getBE().mBuffer->getWidth();
+ uint32_t bufHeight = getBE().mBuffer->getHeight();
+ if (bufWidth != uint32_t(oldBuffer->width) ||
+ bufHeight != uint32_t(oldBuffer->height)) {
+ recomputeVisibleRegions = true;
+ }
+ }
+
+ mCurrentOpacity = getOpacityForFormat(getBE().mBuffer->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);
+}
+
+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 = getBE().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 (getBE().mSidebandStream.get()) {
+ setCompositionType(hwcId, HWC2::Composition::Sideband);
+ ALOGV("[%s] Requesting Sideband composition", mName.string());
+ error = hwcLayer->setSidebandStream(getBE().mSidebandStream->handle());
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(),
+ getBE().mSidebandStream->handle(), 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(getBE().mBufferSlot,
+ getBE().mBuffer, &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(),
+ getBE().mBuffer->handle, to_string(error).c_str(),
+ static_cast<int32_t>(error));
+ }
+}
+
+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 ((getBE().mSidebandStream == nullptr) && (getBE().mBuffer == 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, getBE().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(getBE().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());
+ engine.setSourceDataSpace(mCurrentState.dataSpace);
+ engine.drawMesh(getBE().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 {
+ 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;
+}
+
+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..1127952
--- /dev/null
+++ b/services/surfaceflinger/BufferLayer.h
@@ -0,0 +1,196 @@
+/*
+ * 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 <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;
+
+ void onLayerDisplayed(const sp<Fence>& releaseFence) override;
+
+ 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;
+
+ // If a buffer was replaced this frame, release the former buffer
+ void releasePendingBuffer(nsecs_t dequeueReadyTime);
+
+ /*
+ * 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;
+
+ void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override;
+
+ 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..b784c8d
--- /dev/null
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -0,0 +1,94 @@
+/*
+ * 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;
+}
+
+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 = getBE().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));
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h
new file mode 100644
index 0000000..4022b31
--- /dev/null
+++ b/services/surfaceflinger/ColorLayer.h
@@ -0,0 +1,71 @@
+/*
+ * 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; }
+ void releasePendingBuffer(nsecs_t) override {}
+ 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 {}
+ void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override;
+ 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 95802bd..2753f11 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>
@@ -37,9 +38,7 @@
#include "DisplayHardware/DisplaySurface.h"
#include "DisplayHardware/HWComposer.h"
-#ifdef USE_HWC2
#include "DisplayHardware/HWC2.h"
-#endif
#include "RenderEngine/RenderEngine.h"
#include "clz.h"
@@ -54,12 +53,6 @@
using namespace android;
// ----------------------------------------------------------------------------
-#ifdef EGL_ANDROID_swap_rectangle
-static constexpr bool kEGLAndroidSwapRectangle = true;
-#else
-static constexpr bool kEGLAndroidSwapRectangle = false;
-#endif
-
// retrieve triple buffer setting from configstore
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
@@ -67,12 +60,6 @@
static bool useTripleFramebuffer = getInt64< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::maxFrameBufferAcquiredBuffers>(2) >= 3;
-#if !defined(EGL_EGLEXT_PROTOTYPES) || !defined(EGL_ANDROID_swap_rectangle)
-// Dummy implementation in case it is missing.
-inline void eglSetSwapRectangleANDROID (EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint) {
-}
-#endif
-
/*
* Initialize the display to the specified values.
*
@@ -85,14 +72,10 @@
const sp<SurfaceFlinger>& flinger,
DisplayType type,
int32_t hwcId,
-#ifndef USE_HWC2
- int format,
-#endif
bool isSecure,
const wp<IBinder>& displayToken,
const sp<DisplaySurface>& displaySurface,
const sp<IGraphicBufferProducer>& producer,
- EGLConfig config,
bool supportWideColor)
: lastCompositionHadVisibleLayers(false),
mFlinger(flinger),
@@ -100,14 +83,9 @@
mHwcDisplayId(hwcId),
mDisplayToken(displayToken),
mDisplaySurface(displaySurface),
- mDisplay(EGL_NO_DISPLAY),
- mSurface(EGL_NO_SURFACE),
+ mSurface{flinger->getRenderEngine()},
mDisplayWidth(),
mDisplayHeight(),
-#ifndef USE_HWC2
- mFormat(),
-#endif
- mFlags(),
mPageFlipCount(),
mIsSecure(isSecure),
mLayerStack(NO_LAYER_STACK),
@@ -120,30 +98,16 @@
mNativeWindow = surface = new Surface(producer, false);
ANativeWindow* const window = mNativeWindow.get();
-#ifdef USE_HWC2
mActiveColorMode = HAL_COLOR_MODE_NATIVE;
mDisplayHasWideColor = supportWideColor;
-#else
- (void) supportWideColor;
-#endif
/*
* Create our display's surface
*/
-
- EGLSurface eglSurface;
- EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (config == EGL_NO_CONFIG) {
-#ifdef USE_HWC2
- config = RenderEngine::chooseEglConfig(display, PIXEL_FORMAT_RGBA_8888,
- /*logConfig*/ false);
-#else
- config = RenderEngine::chooseEglConfig(display, format,
- /*logConfig*/ false);
-#endif
- }
- eglSurface = eglCreateWindowSurface(display, config, window, NULL);
- eglQuerySurface(display, eglSurface, EGL_WIDTH, &mDisplayWidth);
- eglQuerySurface(display, eglSurface, EGL_HEIGHT, &mDisplayHeight);
+ mSurface.setCritical(mType == DisplayDevice::DISPLAY_PRIMARY);
+ mSurface.setAsync(mType >= DisplayDevice::DISPLAY_VIRTUAL);
+ mSurface.setNativeWindow(window);
+ mDisplayWidth = mSurface.queryWidth();
+ mDisplayHeight = mSurface.queryHeight();
// Make sure that composition can never be stalled by a virtual display
// consumer that isn't processing buffers fast enough. We have to do this
@@ -155,12 +119,6 @@
if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
window->setSwapInterval(window, 0);
- mConfig = config;
- mDisplay = display;
- mSurface = eglSurface;
-#ifndef USE_HWC2
- mFormat = format;
-#endif
mPageFlipCount = 0;
mViewport.makeInvalid();
mFrame.makeInvalid();
@@ -192,19 +150,11 @@
}
DisplayDevice::~DisplayDevice() {
- if (mSurface != EGL_NO_SURFACE) {
- eglDestroySurface(mDisplay, mSurface);
- mSurface = EGL_NO_SURFACE;
- }
}
void DisplayDevice::disconnect(HWComposer& hwc) {
if (mHwcDisplayId >= 0) {
hwc.disconnectDisplay(mHwcDisplayId);
-#ifndef USE_HWC2
- if (mHwcDisplayId >= DISPLAY_VIRTUAL)
- hwc.freeDisplayId(mHwcDisplayId);
-#endif
mHwcDisplayId = -1;
}
}
@@ -221,16 +171,6 @@
return mDisplayHeight;
}
-#ifndef USE_HWC2
-PixelFormat DisplayDevice::getFormat() const {
- return mFormat;
-}
-#endif
-
-EGLSurface DisplayDevice::getEGLSurface() const {
- return mSurface;
-}
-
void DisplayDevice::setDisplayName(const String8& displayName) {
if (!displayName.isEmpty()) {
// never override the name with an empty name
@@ -242,25 +182,9 @@
return mPageFlipCount;
}
-#ifndef USE_HWC2
-status_t DisplayDevice::compositionComplete() const {
- return mDisplaySurface->compositionComplete();
-}
-#endif
-
-void DisplayDevice::flip(const Region& dirty) const
+void DisplayDevice::flip() const
{
mFlinger->getRenderEngine().checkErrors();
-
- if (kEGLAndroidSwapRectangle) {
- if (mFlags & SWAP_RECTANGLE) {
- const Region newDirty(dirty.intersect(bounds()));
- const Rect b(newDirty.getBounds());
- eglSetSwapRectangleANDROID(mDisplay, mSurface,
- b.left, b.top, b.width(), b.height());
- }
- }
-
mPageFlipCount++;
}
@@ -268,7 +192,6 @@
return mDisplaySurface->beginFrame(mustRecompose);
}
-#ifdef USE_HWC2
status_t DisplayDevice::prepareFrame(HWComposer& hwc) {
status_t error = hwc.prepare(*this);
if (error != NO_ERROR) {
@@ -292,53 +215,10 @@
}
return mDisplaySurface->prepareFrame(compositionType);
}
-#else
-status_t DisplayDevice::prepareFrame(const HWComposer& hwc) const {
- DisplaySurface::CompositionType compositionType;
- bool haveGles = hwc.hasGlesComposition(mHwcDisplayId);
- bool haveHwc = hwc.hasHwcComposition(mHwcDisplayId);
- if (haveGles && haveHwc) {
- compositionType = DisplaySurface::COMPOSITION_MIXED;
- } else if (haveGles) {
- compositionType = DisplaySurface::COMPOSITION_GLES;
- } else if (haveHwc) {
- compositionType = DisplaySurface::COMPOSITION_HWC;
- } else {
- // Nothing to do -- when turning the screen off we get a frame like
- // this. Call it a HWC frame since we won't be doing any GLES work but
- // will do a prepare/set cycle.
- compositionType = DisplaySurface::COMPOSITION_HWC;
- }
- return mDisplaySurface->prepareFrame(compositionType);
-}
-#endif
void DisplayDevice::swapBuffers(HWComposer& hwc) const {
-#ifdef USE_HWC2
if (hwc.hasClientComposition(mHwcDisplayId)) {
-#else
- // We need to call eglSwapBuffers() if:
- // (1) we don't have a hardware composer, or
- // (2) we did GLES composition this frame, and either
- // (a) we have framebuffer target support (not present on legacy
- // devices, where HWComposer::commit() handles things); or
- // (b) this is a virtual display
- if (hwc.initCheck() != NO_ERROR ||
- (hwc.hasGlesComposition(mHwcDisplayId) &&
- (hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) {
-#endif
- EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
- if (!success) {
- EGLint error = eglGetError();
- if (error == EGL_CONTEXT_LOST ||
- mType == DisplayDevice::DISPLAY_PRIMARY) {
- LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x",
- mDisplay, mSurface, error);
- } else {
- ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x",
- mDisplay, mSurface, error);
- }
- }
+ mSurface.swapBuffers();
}
status_t result = mDisplaySurface->advanceFrame();
@@ -348,35 +228,14 @@
}
}
-#ifdef USE_HWC2
void DisplayDevice::onSwapBuffersCompleted() const {
mDisplaySurface->onFrameCommitted();
}
-#else
-void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
- if (hwc.initCheck() == NO_ERROR) {
- mDisplaySurface->onFrameCommitted();
- }
-}
-#endif
-uint32_t DisplayDevice::getFlags() const
-{
- return mFlags;
-}
-
-EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy, EGLContext ctx) const {
- EGLBoolean result = EGL_TRUE;
- EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
- if (sur != mSurface) {
- result = eglMakeCurrent(dpy, mSurface, mSurface, ctx);
- if (result == EGL_TRUE) {
- if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
- eglSwapInterval(dpy, 0);
- }
- }
+bool DisplayDevice::makeCurrent() const {
+ bool success = mFlinger->getRenderEngine().setCurrentSurface(mSurface);
setViewportAndProjection();
- return result;
+ return success;
}
void DisplayDevice::setViewportAndProjection() const {
@@ -444,7 +303,6 @@
}
// ----------------------------------------------------------------------------
-#ifdef USE_HWC2
void DisplayDevice::setActiveColorMode(android_color_mode_t mode) {
mActiveColorMode = mode;
}
@@ -457,7 +315,6 @@
ANativeWindow* const window = mNativeWindow.get();
native_window_set_buffers_data_space(window, dataspace);
}
-#endif
// ----------------------------------------------------------------------------
@@ -514,17 +371,14 @@
void DisplayDevice::setDisplaySize(const int newWidth, const int newHeight) {
dirtyRegion.set(getBounds());
- if (mSurface != EGL_NO_SURFACE) {
- eglDestroySurface(mDisplay, mSurface);
- mSurface = EGL_NO_SURFACE;
- }
+ mSurface.setNativeWindow(nullptr);
mDisplaySurface->resizeBuffers(newWidth, newHeight);
ANativeWindow* const window = mNativeWindow.get();
- mSurface = eglCreateWindowSurface(mDisplay, mConfig, window, NULL);
- eglQuerySurface(mDisplay, mSurface, EGL_WIDTH, &mDisplayWidth);
- eglQuerySurface(mDisplay, mSurface, EGL_HEIGHT, &mDisplayHeight);
+ mSurface.setNativeWindow(window);
+ mDisplayWidth = mSurface.queryWidth();
+ mDisplayHeight = mSurface.queryHeight();
LOG_FATAL_IF(mDisplayWidth != newWidth,
"Unable to set new width to %d", newWidth);
@@ -625,18 +479,15 @@
void DisplayDevice::dump(String8& result) const {
const Transform& tr(mGlobalTransform);
- EGLint redSize, greenSize, blueSize, alphaSize;
- eglGetConfigAttrib(mDisplay, mConfig, EGL_RED_SIZE, &redSize);
- eglGetConfigAttrib(mDisplay, mConfig, EGL_GREEN_SIZE, &greenSize);
- eglGetConfigAttrib(mDisplay, mConfig, EGL_BLUE_SIZE, &blueSize);
- eglGetConfigAttrib(mDisplay, mConfig, EGL_ALPHA_SIZE, &alphaSize);
+ ANativeWindow* const window = mNativeWindow.get();
result.appendFormat("+ DisplayDevice: %s\n", mDisplayName.string());
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,
+ mSurface.queryRedSize(), mSurface.queryGreenSize(), mSurface.queryBlueSize(),
+ mSurface.queryAlphaSize(), 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",
@@ -644,6 +495,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 e8a5929..499bf8e 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -21,27 +21,20 @@
#include <stdlib.h>
-#ifndef USE_HWC2
-#include <ui/PixelFormat.h>
-#endif
#include <ui/Region.h>
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-#ifdef USE_HWC2
#include <binder/IBinder.h>
#include <utils/RefBase.h>
-#endif
#include <utils/Mutex.h>
#include <utils/String8.h>
#include <utils/Timers.h>
+#include <gui/ISurfaceComposer.h>
#include <hardware/hwcomposer_defs.h>
+#include "RenderArea.h"
+#include "RenderEngine/Surface.h"
-#ifdef USE_HWC2
#include <memory>
-#endif
struct ANativeWindow;
@@ -61,8 +54,6 @@
// region in layer-stack space
mutable Region dirtyRegion;
// region in screen space
- mutable Region swapRegion;
- // region in screen space
Region undefinedRegion;
bool lastCompositionHadVisibleLayers;
@@ -75,11 +66,6 @@
};
enum {
- PARTIAL_UPDATES = 0x00020000, // video driver feature
- SWAP_RECTANGLE = 0x00080000,
- };
-
- enum {
NO_LAYER_STACK = 0xFFFFFFFF,
};
@@ -88,14 +74,10 @@
const sp<SurfaceFlinger>& flinger,
DisplayType type,
int32_t hwcId,
-#ifndef USE_HWC2
- int format,
-#endif
bool isSecure,
const wp<IBinder>& displayToken,
const sp<DisplaySurface>& displaySurface,
const sp<IGraphicBufferProducer>& producer,
- EGLConfig config,
bool supportWideColor);
// clang-format on
@@ -111,16 +93,10 @@
// Flip the front and back buffers if the back buffer is "dirty". Might
// be instantaneous, might involve copying the frame buffer around.
- void flip(const Region& dirty) const;
+ void flip() const;
int getWidth() const;
int getHeight() const;
-#ifndef USE_HWC2
- PixelFormat getFormat() const;
-#endif
- uint32_t getFlags() const;
-
- EGLSurface getEGLSurface() const;
void setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers);
const Vector< sp<Layer> >& getVisibleLayersSortedByZ() const;
@@ -150,24 +126,13 @@
// We pass in mustRecompose so we can keep VirtualDisplaySurface's state
// machine happy without actually queueing a buffer if nothing has changed
status_t beginFrame(bool mustRecompose) const;
-#ifdef USE_HWC2
status_t prepareFrame(HWComposer& hwc);
bool getWideColorSupport() const { return mDisplayHasWideColor; }
-#else
- status_t prepareFrame(const HWComposer& hwc) const;
-#endif
void swapBuffers(HWComposer& hwc) const;
-#ifndef USE_HWC2
- status_t compositionComplete() const;
-#endif
// called after h/w composer has completed its set() call
-#ifdef USE_HWC2
void onSwapBuffersCompleted() const;
-#else
- void onSwapBuffersCompleted(HWComposer& hwc) const;
-#endif
Rect getBounds() const {
return Rect(mDisplayWidth, mDisplayHeight);
@@ -177,7 +142,7 @@
void setDisplayName(const String8& displayName);
const String8& getDisplayName() const { return mDisplayName; }
- EGLBoolean makeCurrent(EGLDisplay dpy, EGLContext ctx) const;
+ bool makeCurrent() const;
void setViewportAndProjection() const;
const sp<Fence>& getClientTargetAcquireFence() const;
@@ -189,11 +154,9 @@
void setPowerMode(int mode);
bool isDisplayOn() const;
-#ifdef USE_HWC2
android_color_mode_t getActiveColorMode() const;
void setActiveColorMode(android_color_mode_t mode);
void setCompositionDataSpace(android_dataspace dataspace);
-#endif
/* ------------------------------------------------------------------------
* Display active config management.
@@ -223,15 +186,9 @@
sp<ANativeWindow> mNativeWindow;
sp<DisplaySurface> mDisplaySurface;
- EGLConfig mConfig;
- EGLDisplay mDisplay;
- EGLSurface mSurface;
+ RE::Surface mSurface;
int mDisplayWidth;
int mDisplayHeight;
-#ifndef USE_HWC2
- PixelFormat mFormat;
-#endif
- uint32_t mFlags;
mutable uint32_t mPageFlipCount;
String8 mDisplayName;
bool mIsSecure;
@@ -271,7 +228,6 @@
int mPowerMode;
// Current active config
int mActiveConfig;
-#ifdef USE_HWC2
// current active color mode
android_color_mode_t mActiveColorMode;
@@ -279,7 +235,6 @@
// Initialized by SurfaceFlinger when the DisplayDevice is created.
// Fed to RenderEngine during composition.
bool mDisplayHasWideColor;
-#endif
};
struct DisplayDeviceState {
@@ -304,6 +259,33 @@
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; }
+ bool getWideColorSupport() const override { return mDevice->getWideColorSupport(); }
+ android_color_mode_t getActiveColorMode() const override {
+ return mDevice->getActiveColorMode();
+ }
+
+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/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
index cb08f08..f744f5c 100644
--- a/services/surfaceflinger/DisplayHardware/DisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
@@ -50,14 +50,6 @@
};
virtual status_t prepareFrame(CompositionType compositionType) = 0;
-#ifndef USE_HWC2
- // Should be called when composition rendering is complete for a frame (but
- // eglSwapBuffers hasn't necessarily been called). Required by certain
- // older drivers for synchronization.
- // TODO: Remove this when we drop support for HWC 1.0.
- virtual status_t compositionComplete() = 0;
-#endif
-
// Inform the surface that GLES composition is complete for this frame, and
// the surface should make sure that HWComposer has the correct buffer for
// this frame. Some implementations may only push a new buffer to
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 93c6d54..8b5d4c9 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -27,8 +27,6 @@
#include <utils/String8.h>
#include <log/log.h>
-#include <EGL/egl.h>
-
#include <hardware/hardware.h>
#include <gui/BufferItem.h>
#include <gui/BufferQueue.h>
@@ -59,32 +57,21 @@
mCurrentBufferSlot(-1),
mCurrentBuffer(),
mCurrentFence(Fence::NO_FENCE),
-#ifdef USE_HWC2
mHwc(hwc),
mHasPendingRelease(false),
mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),
mPreviousBuffer()
-#else
- mHwc(hwc)
-#endif
{
-#ifdef USE_HWC2
ALOGV("Creating for display %d", disp);
-#endif
mName = "FramebufferSurface";
mConsumer->setConsumerName(mName);
mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
GRALLOC_USAGE_HW_RENDER |
GRALLOC_USAGE_HW_COMPOSER);
-#ifdef USE_HWC2
const auto& activeConfig = mHwc.getActiveConfig(disp);
mConsumer->setDefaultBufferSize(activeConfig->getWidth(),
activeConfig->getHeight());
-#else
- mConsumer->setDefaultBufferFormat(mHwc.getFormat(disp));
- mConsumer->setDefaultBufferSize(mHwc.getWidth(disp), mHwc.getHeight(disp));
-#endif
mConsumer->setMaxAcquiredBufferCount(
SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1);
}
@@ -98,7 +85,6 @@
}
status_t FramebufferSurface::advanceFrame() {
-#ifdef USE_HWC2
uint32_t slot = 0;
sp<GraphicBuffer> buf;
sp<Fence> acquireFence(Fence::NO_FENCE);
@@ -110,32 +96,18 @@
strerror(-result), result);
}
return result;
-#else
- // Once we remove FB HAL support, we can call nextBuffer() from here
- // instead of using onFrameAvailable(). No real benefit, except it'll be
- // more like VirtualDisplaySurface.
- return NO_ERROR;
-#endif
}
-#ifdef USE_HWC2
status_t FramebufferSurface::nextBuffer(uint32_t& outSlot,
sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence,
android_dataspace_t& outDataspace) {
-#else
-status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
-#endif
Mutex::Autolock lock(mMutex);
BufferItem item;
status_t err = acquireBufferLocked(&item, 0);
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
-#ifdef USE_HWC2
mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
&outSlot, &outBuffer);
-#else
- outBuffer = mCurrentBuffer;
-#endif
return NO_ERROR;
} else if (err != NO_ERROR) {
ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err);
@@ -152,26 +124,15 @@
// had released the old buffer first.
if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT &&
item.mSlot != mCurrentBufferSlot) {
-#ifdef USE_HWC2
mHasPendingRelease = true;
mPreviousBufferSlot = mCurrentBufferSlot;
mPreviousBuffer = mCurrentBuffer;
-#else
- // Release the previous buffer.
- err = releaseBufferLocked(mCurrentBufferSlot, mCurrentBuffer,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
- if (err < NO_ERROR) {
- ALOGE("error releasing buffer: %s (%d)", strerror(-err), err);
- return err;
- }
-#endif
}
mCurrentBufferSlot = item.mSlot;
mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
mCurrentFence = item.mFence;
outFence = item.mFence;
-#ifdef USE_HWC2
mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
&outSlot, &outBuffer);
outDataspace = item.mDataSpace;
@@ -181,31 +142,10 @@
ALOGE("error posting framebuffer: %d", result);
return result;
}
-#else
- outBuffer = mCurrentBuffer;
-#endif
return NO_ERROR;
}
-#ifndef USE_HWC2
-// Overrides ConsumerBase::onFrameAvailable(), does not call base class impl.
-void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) {
- sp<GraphicBuffer> buf;
- sp<Fence> acquireFence;
- status_t err = nextBuffer(buf, acquireFence);
- if (err != NO_ERROR) {
- ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)",
- strerror(-err), err);
- return;
- }
- err = mHwc.fbPost(mDisplayType, acquireFence, buf);
- if (err != NO_ERROR) {
- ALOGE("error posting framebuffer: %d", err);
- }
-}
-#endif
-
void FramebufferSurface::freeBufferLocked(int slotIndex) {
ConsumerBase::freeBufferLocked(slotIndex);
if (slotIndex == mCurrentBufferSlot) {
@@ -214,7 +154,6 @@
}
void FramebufferSurface::onFrameCommitted() {
-#ifdef USE_HWC2
if (mHasPendingRelease) {
sp<Fence> fence = mHwc.getPresentFence(mDisplayType);
if (fence->isValid()) {
@@ -223,33 +162,15 @@
ALOGE_IF(result != NO_ERROR, "onFrameCommitted: failed to add the"
" fence: %s (%d)", strerror(-result), result);
}
- status_t result = releaseBufferLocked(mPreviousBufferSlot,
- mPreviousBuffer, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
+ status_t result = releaseBufferLocked(mPreviousBufferSlot, mPreviousBuffer);
ALOGE_IF(result != NO_ERROR, "onFrameCommitted: error releasing buffer:"
" %s (%d)", strerror(-result), result);
mPreviousBuffer.clear();
mHasPendingRelease = false;
}
-#else
- sp<Fence> fence = mHwc.getAndResetReleaseFence(mDisplayType);
- if (fence->isValid() &&
- mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) {
- status_t err = addReleaseFence(mCurrentBufferSlot,
- mCurrentBuffer, fence);
- ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)",
- strerror(-err), err);
- }
-#endif
}
-#ifndef USE_HWC2
-status_t FramebufferSurface::compositionComplete()
-{
- return mHwc.fbCompositionComplete();
-}
-#endif
-
void FramebufferSurface::dumpAsString(String8& result) const {
Mutex::Autolock lock(mMutex);
result.appendFormat("FramebufferSurface: dataspace: %s(%d)\n",
@@ -259,9 +180,6 @@
void FramebufferSurface::dumpLocked(String8& result, const char* prefix) const
{
-#ifndef USE_HWC2
- mHwc.fbDump(result);
-#endif
ConsumerBase::dumpLocked(result, prefix);
}
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index a1756ca..4186b7a 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -42,9 +42,6 @@
virtual status_t beginFrame(bool mustRecompose);
virtual status_t prepareFrame(CompositionType compositionType);
-#ifndef USE_HWC2
- virtual status_t compositionComplete();
-#endif
virtual status_t advanceFrame();
virtual void onFrameCommitted();
virtual void dumpAsString(String8& result) const;
@@ -58,9 +55,6 @@
private:
virtual ~FramebufferSurface() { }; // this class cannot be overloaded
-#ifndef USE_HWC2
- virtual void onFrameAvailable(const BufferItem& item);
-#endif
virtual void freeBufferLocked(int slotIndex);
virtual void dumpLocked(String8& result, const char* prefix) const;
@@ -68,12 +62,8 @@
// nextBuffer waits for and then latches the next buffer from the
// BufferQueue and releases the previously latched buffer to the
// BufferQueue. The new buffer is returned in the 'buffer' argument.
-#ifdef USE_HWC2
status_t nextBuffer(uint32_t& outSlot, sp<GraphicBuffer>& outBuffer,
sp<Fence>& outFence, android_dataspace_t& outDataspace);
-#else
- status_t nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence);
-#endif
// mDisplayType must match one of the HWC display types
int mDisplayType;
@@ -100,14 +90,12 @@
// Hardware composer, owned by SurfaceFlinger.
HWComposer& mHwc;
-#ifdef USE_HWC2
HWComposerBufferCache mHwcBufferCache;
// Previous buffer to release after getting an updated retire fence
bool mHasPendingRelease;
int mPreviousBufferSlot;
sp<GraphicBuffer> mPreviousBuffer;
-#endif
};
// ---------------------------------------------------------------------------
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..60b85c5 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));
@@ -865,6 +868,14 @@
result.append(mHwcDevice->dump().c_str());
}
+std::optional<hwc2_display_t>
+HWComposer::getHwcDisplayId(int32_t displayId) const {
+ if (!isValidDisplay(displayId)) {
+ return {};
+ }
+ return mDisplayData[displayId].hwcDisplay->getId();
+}
+
// ---------------------------------------------------------------------------
HWComposer::DisplayData::DisplayData()
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 3640bb5..74b3a38 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -14,10 +14,6 @@
* limitations under the License.
*/
-#ifndef USE_HWC2
-#include "HWComposer_hwc1.h"
-#else
-
#ifndef ANDROID_SF_HWCOMPOSER_H
#define ANDROID_SF_HWCOMPOSER_H
@@ -37,6 +33,7 @@
#include <utils/Vector.h>
#include <memory>
+#include <optional>
#include <set>
#include <vector>
@@ -165,6 +162,8 @@
void dump(String8& out) const;
android::Hwc2::Composer* getComposer() const { return mHwcDevice->getComposer(); }
+
+ std::optional<hwc2_display_t> getHwcDisplayId(int32_t displayId) const;
private:
static const int32_t VIRTUAL_DISPLAY_ID_BASE = 2;
@@ -219,5 +218,3 @@
}; // namespace android
#endif // ANDROID_SF_HWCOMPOSER_H
-
-#endif // #ifdef USE_HWC2
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
deleted file mode 100644
index dcb2913..0000000
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
+++ /dev/null
@@ -1,1346 +0,0 @@
-/*
- * Copyright (C) 2010 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 ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include <inttypes.h>
-#include <math.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/misc.h>
-#include <utils/NativeHandle.h>
-#include <utils/String8.h>
-#include <utils/Thread.h>
-#include <utils/Trace.h>
-#include <utils/Vector.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include <hardware/hardware.h>
-#include <hardware/hwcomposer.h>
-
-#include <android/configuration.h>
-
-#include <cutils/properties.h>
-#include <log/log.h>
-
-#include <system/graphics.h>
-
-#include "HWComposer.h"
-
-#include "../Layer.h" // needed only for debugging
-#include "../SurfaceFlinger.h"
-
-namespace android {
-
-#define MIN_HWC_HEADER_VERSION HWC_HEADER_VERSION
-
-static uint32_t hwcApiVersion(const hwc_composer_device_1_t* hwc) {
- uint32_t hwcVersion = hwc->common.version;
- return hwcVersion & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
-}
-
-static uint32_t hwcHeaderVersion(const hwc_composer_device_1_t* hwc) {
- uint32_t hwcVersion = hwc->common.version;
- return hwcVersion & HARDWARE_API_VERSION_2_HEADER_MASK;
-}
-
-static bool hwcHasApiVersion(const hwc_composer_device_1_t* hwc,
- uint32_t version) {
- return hwcApiVersion(hwc) >= (version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK);
-}
-
-// ---------------------------------------------------------------------------
-
-struct HWComposer::cb_context {
- struct callbacks : public hwc_procs_t {
- // these are here to facilitate the transition when adding
- // new callbacks (an implementation can check for NULL before
- // calling a new callback).
- void (*zero[4])(void);
- };
- callbacks procs;
- HWComposer* hwc;
-};
-
-// ---------------------------------------------------------------------------
-
-HWComposer::HWComposer(
- const sp<SurfaceFlinger>& flinger,
- EventHandler& handler)
- : mFlinger(flinger),
- mFbDev(0), mHwc(0), mNumDisplays(1),
- mCBContext(new cb_context),
- mEventHandler(handler),
- mDebugForceFakeVSync(false)
-{
- for (size_t i =0 ; i<MAX_HWC_DISPLAYS ; i++) {
- mLists[i] = 0;
- }
-
- for (size_t i=0 ; i<HWC_NUM_PHYSICAL_DISPLAY_TYPES ; i++) {
- mLastHwVSync[i] = 0;
- mVSyncCounts[i] = 0;
- }
-
- char value[PROPERTY_VALUE_MAX];
- property_get("debug.sf.no_hw_vsync", value, "0");
- mDebugForceFakeVSync = atoi(value);
-
- bool needVSyncThread = true;
-
- // Note: some devices may insist that the FB HAL be opened before HWC.
- int fberr = loadFbHalModule();
- loadHwcModule();
-
- if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
- // close FB HAL if we don't needed it.
- // FIXME: this is temporary until we're not forced to open FB HAL
- // before HWC.
- framebuffer_close(mFbDev);
- mFbDev = NULL;
- }
-
- // If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory.
- if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
- && !mFbDev) {
- ALOGE("ERROR: failed to open framebuffer (%s), aborting",
- strerror(-fberr));
- abort();
- }
-
- // these display IDs are always reserved
- for (size_t i=0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
- mAllocatedDisplayIDs.markBit(i);
- }
-
- if (mHwc) {
- ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
- (hwcApiVersion(mHwc) >> 24) & 0xff,
- (hwcApiVersion(mHwc) >> 16) & 0xff);
- if (mHwc->registerProcs) {
- mCBContext->hwc = this;
- mCBContext->procs.invalidate = &hook_invalidate;
- mCBContext->procs.vsync = &hook_vsync;
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
- mCBContext->procs.hotplug = &hook_hotplug;
- else
- mCBContext->procs.hotplug = NULL;
- memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
- mHwc->registerProcs(mHwc, &mCBContext->procs);
- }
-
- // don't need a vsync thread if we have a hardware composer
- needVSyncThread = false;
- // always turn vsync off when we start
- eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
-
- // the number of displays we actually have depends on the
- // hw composer version
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
- // 1.3 adds support for virtual displays
- mNumDisplays = MAX_HWC_DISPLAYS;
- } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
- // 1.1 adds support for multiple displays
- mNumDisplays = NUM_BUILTIN_DISPLAYS;
- } else {
- mNumDisplays = 1;
- }
- }
-
- if (mFbDev) {
- ALOG_ASSERT(!(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)),
- "should only have fbdev if no hwc or hwc is 1.0");
-
- DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]);
- disp.connected = true;
- disp.format = mFbDev->format;
- DisplayConfig config = DisplayConfig();
- config.width = mFbDev->width;
- config.height = mFbDev->height;
- config.xdpi = mFbDev->xdpi;
- config.ydpi = mFbDev->ydpi;
- config.refresh = nsecs_t(1e9 / mFbDev->fps);
- disp.configs.push_back(config);
- disp.currentConfig = 0;
- } else if (mHwc) {
- // here we're guaranteed to have at least HWC 1.1
- for (size_t i =0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
- queryDisplayProperties(i);
- }
- }
-
- if (needVSyncThread) {
- // we don't have VSYNC support, we need to fake it
- mVSyncThread = new VSyncThread(*this);
- }
-}
-
-HWComposer::~HWComposer() {
- if (mHwc) {
- eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
- }
- if (mVSyncThread != NULL) {
- mVSyncThread->requestExitAndWait();
- }
- if (mHwc) {
- hwc_close_1(mHwc);
- }
- if (mFbDev) {
- framebuffer_close(mFbDev);
- }
- delete mCBContext;
-}
-
-// Load and prepare the hardware composer module. Sets mHwc.
-void HWComposer::loadHwcModule()
-{
- hw_module_t const* module;
-
- if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) {
- ALOGE("%s module not found", HWC_HARDWARE_MODULE_ID);
- return;
- }
-
- int err = hwc_open_1(module, &mHwc);
- if (err) {
- ALOGE("%s device failed to initialize (%s)",
- HWC_HARDWARE_COMPOSER, strerror(-err));
- return;
- }
-
- if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0) ||
- hwcHeaderVersion(mHwc) < MIN_HWC_HEADER_VERSION ||
- hwcHeaderVersion(mHwc) > HWC_HEADER_VERSION) {
- ALOGE("%s device version %#x unsupported, will not be used",
- HWC_HARDWARE_COMPOSER, mHwc->common.version);
- hwc_close_1(mHwc);
- mHwc = NULL;
- return;
- }
-}
-
-// Load and prepare the FB HAL, which uses the gralloc module. Sets mFbDev.
-int HWComposer::loadFbHalModule()
-{
- hw_module_t const* module;
-
- int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
- if (err != 0) {
- ALOGE("%s module not found", GRALLOC_HARDWARE_MODULE_ID);
- return err;
- }
-
- return framebuffer_open(module, &mFbDev);
-}
-
-status_t HWComposer::initCheck() const {
- return mHwc ? NO_ERROR : NO_INIT;
-}
-
-void HWComposer::hook_invalidate(const struct hwc_procs* procs) {
- cb_context* ctx = reinterpret_cast<cb_context*>(
- const_cast<hwc_procs_t*>(procs));
- ctx->hwc->invalidate();
-}
-
-void HWComposer::hook_vsync(const struct hwc_procs* procs, int disp,
- int64_t timestamp) {
- cb_context* ctx = reinterpret_cast<cb_context*>(
- const_cast<hwc_procs_t*>(procs));
- ctx->hwc->vsync(disp, timestamp);
-}
-
-void HWComposer::hook_hotplug(const struct hwc_procs* procs, int disp,
- int connected) {
- cb_context* ctx = reinterpret_cast<cb_context*>(
- const_cast<hwc_procs_t*>(procs));
- ctx->hwc->hotplug(disp, connected);
-}
-
-void HWComposer::invalidate() {
- mEventHandler.onInvalidateReceived(this);
-}
-
-void HWComposer::vsync(int disp, int64_t timestamp) {
- if (uint32_t(disp) < HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
- {
- Mutex::Autolock _l(mLock);
-
- // There have been reports of HWCs that signal several vsync events
- // with the same timestamp when turning the display off and on. This
- // is a bug in the HWC implementation, but filter the extra events
- // out here so they don't cause havoc downstream.
- if (timestamp == mLastHwVSync[disp]) {
- ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")",
- timestamp);
- return;
- }
-
- mLastHwVSync[disp] = timestamp;
- }
-
- char tag[16];
- snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
- ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);
-
- mEventHandler.onVSyncReceived(this, disp, timestamp);
- }
-}
-
-void HWComposer::hotplug(int disp, int connected) {
- if (disp >= VIRTUAL_DISPLAY_ID_BASE) {
- ALOGE("hotplug event received for invalid display: disp=%d connected=%d",
- disp, connected);
- return;
- }
- queryDisplayProperties(disp);
- // Do not teardown or recreate the primary display
- if (disp != HWC_DISPLAY_PRIMARY) {
- mEventHandler.onHotplugReceived(this, disp, bool(connected));
- }
-}
-
-static float getDefaultDensity(uint32_t width, uint32_t height) {
- // Default density is based on TVs: 1080p displays get XHIGH density,
- // lower-resolution displays get TV density. Maybe eventually we'll need
- // to update it for 4K displays, though hopefully those just report
- // accurate DPI information to begin with. This is also used for virtual
- // displays and even primary displays with older hwcomposers, so be
- // careful about orientation.
-
- uint32_t h = width < height ? width : height;
- if (h >= 1080) return ACONFIGURATION_DENSITY_XHIGH;
- else return ACONFIGURATION_DENSITY_TV;
-}
-
-static const uint32_t DISPLAY_ATTRIBUTES[] = {
- HWC_DISPLAY_VSYNC_PERIOD,
- HWC_DISPLAY_WIDTH,
- HWC_DISPLAY_HEIGHT,
- HWC_DISPLAY_DPI_X,
- HWC_DISPLAY_DPI_Y,
- HWC_DISPLAY_COLOR_TRANSFORM,
- HWC_DISPLAY_NO_ATTRIBUTE,
-};
-#define NUM_DISPLAY_ATTRIBUTES (sizeof(DISPLAY_ATTRIBUTES) / sizeof(DISPLAY_ATTRIBUTES)[0])
-
-static const uint32_t PRE_HWC15_DISPLAY_ATTRIBUTES[] = {
- HWC_DISPLAY_VSYNC_PERIOD,
- HWC_DISPLAY_WIDTH,
- HWC_DISPLAY_HEIGHT,
- HWC_DISPLAY_DPI_X,
- HWC_DISPLAY_DPI_Y,
- HWC_DISPLAY_NO_ATTRIBUTE,
-};
-
-status_t HWComposer::queryDisplayProperties(int disp) {
-
- LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
-
- // use zero as default value for unspecified attributes
- int32_t values[NUM_DISPLAY_ATTRIBUTES - 1];
- memset(values, 0, sizeof(values));
-
- const size_t MAX_NUM_CONFIGS = 128;
- uint32_t configs[MAX_NUM_CONFIGS] = {0};
- size_t numConfigs = MAX_NUM_CONFIGS;
- status_t err = mHwc->getDisplayConfigs(mHwc, disp, configs, &numConfigs);
- if (err != NO_ERROR) {
- // this can happen if an unpluggable display is not connected
- mDisplayData[disp].connected = false;
- return err;
- }
-
- mDisplayData[disp].currentConfig = 0;
- for (size_t c = 0; c < numConfigs; ++c) {
- err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
- DISPLAY_ATTRIBUTES, values);
- // If this is a pre-1.5 HWC, it may not know about color transform, so
- // try again with a smaller set of attributes
- if (err != NO_ERROR) {
- err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
- PRE_HWC15_DISPLAY_ATTRIBUTES, values);
- }
- if (err != NO_ERROR) {
- // we can't get this display's info. turn it off.
- mDisplayData[disp].connected = false;
- return err;
- }
-
- DisplayConfig config = DisplayConfig();
- for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
- switch (DISPLAY_ATTRIBUTES[i]) {
- case HWC_DISPLAY_VSYNC_PERIOD:
- config.refresh = nsecs_t(values[i]);
- break;
- case HWC_DISPLAY_WIDTH:
- config.width = values[i];
- break;
- case HWC_DISPLAY_HEIGHT:
- config.height = values[i];
- break;
- case HWC_DISPLAY_DPI_X:
- config.xdpi = values[i] / 1000.0f;
- break;
- case HWC_DISPLAY_DPI_Y:
- config.ydpi = values[i] / 1000.0f;
- break;
- case HWC_DISPLAY_COLOR_TRANSFORM:
- config.colorMode = static_cast<android_color_mode_t>(values[i]);
- break;
- default:
- ALOG_ASSERT(false, "unknown display attribute[%zu] %#x",
- i, DISPLAY_ATTRIBUTES[i]);
- break;
- }
- }
-
- if (config.xdpi == 0.0f || config.ydpi == 0.0f) {
- float dpi = getDefaultDensity(config.width, config.height);
- config.xdpi = dpi;
- config.ydpi = dpi;
- }
-
- mDisplayData[disp].configs.push_back(config);
- }
-
- // FIXME: what should we set the format to?
- mDisplayData[disp].format = HAL_PIXEL_FORMAT_RGBA_8888;
- mDisplayData[disp].connected = true;
- return NO_ERROR;
-}
-
-status_t HWComposer::setVirtualDisplayProperties(int32_t id,
- uint32_t w, uint32_t h, uint32_t format) {
- if (id < VIRTUAL_DISPLAY_ID_BASE || id >= int32_t(mNumDisplays) ||
- !mAllocatedDisplayIDs.hasBit(id)) {
- return BAD_INDEX;
- }
- size_t configId = mDisplayData[id].currentConfig;
- mDisplayData[id].format = format;
- DisplayConfig& config = mDisplayData[id].configs.editItemAt(configId);
- config.width = w;
- config.height = h;
- config.xdpi = config.ydpi = getDefaultDensity(w, h);
- return NO_ERROR;
-}
-
-int32_t HWComposer::allocateDisplayId() {
- if (mAllocatedDisplayIDs.count() >= mNumDisplays) {
- return NO_MEMORY;
- }
- int32_t id = mAllocatedDisplayIDs.firstUnmarkedBit();
- mAllocatedDisplayIDs.markBit(id);
- mDisplayData[id].connected = true;
- mDisplayData[id].configs.resize(1);
- mDisplayData[id].currentConfig = 0;
- return id;
-}
-
-status_t HWComposer::freeDisplayId(int32_t id) {
- if (id < NUM_BUILTIN_DISPLAYS) {
- // cannot free the reserved IDs
- return BAD_VALUE;
- }
- if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
- return BAD_INDEX;
- }
- mAllocatedDisplayIDs.clearBit(id);
- mDisplayData[id].connected = false;
- return NO_ERROR;
-}
-
-nsecs_t HWComposer::getRefreshTimestamp(int disp) const {
- // this returns the last refresh timestamp.
- // if the last one is not available, we estimate it based on
- // the refresh period and whatever closest timestamp we have.
- Mutex::Autolock _l(mLock);
- nsecs_t now = systemTime(CLOCK_MONOTONIC);
- size_t configId = mDisplayData[disp].currentConfig;
- return now - ((now - mLastHwVSync[disp]) %
- mDisplayData[disp].configs[configId].refresh);
-}
-
-sp<Fence> HWComposer::getDisplayFence(int disp) const {
- return mDisplayData[disp].lastDisplayFence;
-}
-
-uint32_t HWComposer::getFormat(int disp) const {
- if (static_cast<uint32_t>(disp) >= MAX_HWC_DISPLAYS || !mAllocatedDisplayIDs.hasBit(disp)) {
- return HAL_PIXEL_FORMAT_RGBA_8888;
- } else {
- return mDisplayData[disp].format;
- }
-}
-
-bool HWComposer::isConnected(int disp) const {
- return mDisplayData[disp].connected;
-}
-
-uint32_t HWComposer::getWidth(int disp) const {
- size_t currentConfig = mDisplayData[disp].currentConfig;
- return mDisplayData[disp].configs[currentConfig].width;
-}
-
-uint32_t HWComposer::getHeight(int disp) const {
- size_t currentConfig = mDisplayData[disp].currentConfig;
- return mDisplayData[disp].configs[currentConfig].height;
-}
-
-float HWComposer::getDpiX(int disp) const {
- size_t currentConfig = mDisplayData[disp].currentConfig;
- return mDisplayData[disp].configs[currentConfig].xdpi;
-}
-
-float HWComposer::getDpiY(int disp) const {
- size_t currentConfig = mDisplayData[disp].currentConfig;
- return mDisplayData[disp].configs[currentConfig].ydpi;
-}
-
-nsecs_t HWComposer::getRefreshPeriod(int disp) const {
- size_t currentConfig = mDisplayData[disp].currentConfig;
- return mDisplayData[disp].configs[currentConfig].refresh;
-}
-
-android_color_mode_t HWComposer::getColorMode(int disp) const {
- size_t currentConfig = mDisplayData[disp].currentConfig;
- return mDisplayData[disp].configs[currentConfig].colorMode;
-}
-
-const Vector<HWComposer::DisplayConfig>& HWComposer::getConfigs(int disp) const {
- return mDisplayData[disp].configs;
-}
-
-size_t HWComposer::getCurrentConfig(int disp) const {
- return mDisplayData[disp].currentConfig;
-}
-
-void HWComposer::eventControl(int disp, int event, int enabled) {
- if (uint32_t(disp)>31 || !mAllocatedDisplayIDs.hasBit(disp)) {
- ALOGD("eventControl ignoring event %d on unallocated disp %d (en=%d)",
- event, disp, enabled);
- return;
- }
- if (event != EVENT_VSYNC) {
- ALOGW("eventControl got unexpected event %d (disp=%d en=%d)",
- event, disp, enabled);
- return;
- }
- status_t err = NO_ERROR;
- if (mHwc && !mDebugForceFakeVSync) {
- // NOTE: we use our own internal lock here because we have to call
- // into the HWC with the lock held, and we want to make sure
- // that even if HWC blocks (which it shouldn't), it won't
- // affect other threads.
- Mutex::Autolock _l(mEventControlLock);
- const int32_t eventBit = 1UL << event;
- const int32_t newValue = enabled ? eventBit : 0;
- const int32_t oldValue = mDisplayData[disp].events & eventBit;
- if (newValue != oldValue) {
- ATRACE_CALL();
- err = mHwc->eventControl(mHwc, disp, event, enabled);
- if (!err) {
- int32_t& events(mDisplayData[disp].events);
- events = (events & ~eventBit) | newValue;
-
- char tag[16];
- snprintf(tag, sizeof(tag), "HW_VSYNC_ON_%1u", disp);
- ATRACE_INT(tag, enabled);
- }
- }
- // error here should not happen -- not sure what we should
- // do if it does.
- ALOGE_IF(err, "eventControl(%d, %d) failed %s",
- event, enabled, strerror(-err));
- }
-
- if (err == NO_ERROR && mVSyncThread != NULL) {
- mVSyncThread->setEnabled(enabled);
- }
-}
-
-status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
- if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
- return BAD_INDEX;
- }
-
- if (mHwc) {
- DisplayData& disp(mDisplayData[id]);
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
- // we need space for the HWC_FRAMEBUFFER_TARGET
- numLayers++;
- }
- if (disp.capacity < numLayers || disp.list == NULL) {
- size_t size = sizeof(hwc_display_contents_1_t)
- + numLayers * sizeof(hwc_layer_1_t);
- free(disp.list);
- disp.list = (hwc_display_contents_1_t*)malloc(size);
- disp.capacity = numLayers;
- }
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
- disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1];
- memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t));
- const DisplayConfig& currentConfig =
- disp.configs[disp.currentConfig];
- const hwc_rect_t r = { 0, 0,
- (int) currentConfig.width, (int) currentConfig.height };
- disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
- disp.framebufferTarget->hints = 0;
- disp.framebufferTarget->flags = 0;
- disp.framebufferTarget->handle = disp.fbTargetHandle;
- disp.framebufferTarget->transform = 0;
- disp.framebufferTarget->blending = HWC_BLENDING_PREMULT;
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
- disp.framebufferTarget->sourceCropf.left = 0;
- disp.framebufferTarget->sourceCropf.top = 0;
- disp.framebufferTarget->sourceCropf.right =
- currentConfig.width;
- disp.framebufferTarget->sourceCropf.bottom =
- currentConfig.height;
- } else {
- disp.framebufferTarget->sourceCrop = r;
- }
- disp.framebufferTarget->displayFrame = r;
- disp.framebufferTarget->visibleRegionScreen.numRects = 1;
- disp.framebufferTarget->visibleRegionScreen.rects =
- &disp.framebufferTarget->displayFrame;
- disp.framebufferTarget->acquireFenceFd = -1;
- disp.framebufferTarget->releaseFenceFd = -1;
- disp.framebufferTarget->planeAlpha = 0xFF;
- }
- disp.list->retireFenceFd = -1;
- disp.list->flags = HWC_GEOMETRY_CHANGED;
- disp.list->numHwLayers = numLayers;
- }
- return NO_ERROR;
-}
-
-status_t HWComposer::setFramebufferTarget(int32_t id,
- const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf) {
- if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
- return BAD_INDEX;
- }
- DisplayData& disp(mDisplayData[id]);
- if (!disp.framebufferTarget) {
- // this should never happen, but apparently eglCreateWindowSurface()
- // triggers a Surface::queueBuffer() on some
- // devices (!?) -- log and ignore.
- ALOGE("HWComposer: framebufferTarget is null");
- return NO_ERROR;
- }
-
- int acquireFenceFd = -1;
- if (acquireFence->isValid()) {
- acquireFenceFd = acquireFence->dup();
- }
-
- // ALOGD("fbPost: handle=%p, fence=%d", buf->handle, acquireFenceFd);
- disp.fbTargetHandle = buf->handle;
- disp.framebufferTarget->handle = disp.fbTargetHandle;
- disp.framebufferTarget->acquireFenceFd = acquireFenceFd;
- return NO_ERROR;
-}
-
-status_t HWComposer::prepare() {
- Mutex::Autolock _l(mDisplayLock);
- for (size_t i=0 ; i<mNumDisplays ; i++) {
- DisplayData& disp(mDisplayData[i]);
- if (disp.framebufferTarget) {
- // make sure to reset the type to HWC_FRAMEBUFFER_TARGET
- // DO NOT reset the handle field to NULL, because it's possible
- // that we have nothing to redraw (eg: eglSwapBuffers() not called)
- // in which case, we should continue to use the same buffer.
- LOG_FATAL_IF(disp.list == NULL);
- disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
- }
- if (!disp.connected && disp.list != NULL) {
- ALOGW("WARNING: disp %zu: connected, non-null list, layers=%zu",
- i, disp.list->numHwLayers);
- }
- mLists[i] = disp.list;
- if (mLists[i]) {
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
- mLists[i]->outbuf = disp.outbufHandle;
- mLists[i]->outbufAcquireFenceFd = -1;
- } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
- // garbage data to catch improper use
- mLists[i]->dpy = (hwc_display_t)0xDEADBEEF;
- mLists[i]->sur = (hwc_surface_t)0xDEADBEEF;
- } else {
- mLists[i]->dpy = EGL_NO_DISPLAY;
- mLists[i]->sur = EGL_NO_SURFACE;
- }
- }
- }
-
- int err = mHwc->prepare(mHwc, mNumDisplays, mLists);
- ALOGE_IF(err, "HWComposer: prepare failed (%s)", strerror(-err));
-
- if (err == NO_ERROR) {
- // here we're just making sure that "skip" layers are set
- // to HWC_FRAMEBUFFER and we're also counting how many layers
- // we have of each type.
- //
- // If there are no window layers, we treat the display has having FB
- // composition, because SurfaceFlinger will use GLES to draw the
- // wormhole region.
- for (size_t i=0 ; i<mNumDisplays ; i++) {
- DisplayData& disp(mDisplayData[i]);
- disp.hasFbComp = false;
- disp.hasOvComp = false;
- if (disp.list) {
- for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
- hwc_layer_1_t& l = disp.list->hwLayers[i];
-
- //ALOGD("prepare: %d, type=%d, handle=%p",
- // i, l.compositionType, l.handle);
-
- if (l.flags & HWC_SKIP_LAYER) {
- l.compositionType = HWC_FRAMEBUFFER;
- }
- if (l.compositionType == HWC_FRAMEBUFFER) {
- disp.hasFbComp = true;
- }
- if (l.compositionType == HWC_OVERLAY) {
- disp.hasOvComp = true;
- }
- if (l.compositionType == HWC_CURSOR_OVERLAY) {
- disp.hasOvComp = true;
- }
- }
- if (disp.list->numHwLayers == (disp.framebufferTarget ? 1 : 0)) {
- disp.hasFbComp = true;
- }
- } else {
- disp.hasFbComp = true;
- }
- }
- }
- return (status_t)err;
-}
-
-bool HWComposer::hasHwcComposition(int32_t id) const {
- if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
- return false;
- return mDisplayData[id].hasOvComp;
-}
-
-bool HWComposer::hasGlesComposition(int32_t id) const {
- if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
- return true;
- return mDisplayData[id].hasFbComp;
-}
-
-sp<Fence> HWComposer::getAndResetReleaseFence(int32_t id) {
- if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
- return Fence::NO_FENCE;
-
- int fd = INVALID_OPERATION;
- if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
- const DisplayData& disp(mDisplayData[id]);
- if (disp.framebufferTarget) {
- fd = disp.framebufferTarget->releaseFenceFd;
- disp.framebufferTarget->acquireFenceFd = -1;
- disp.framebufferTarget->releaseFenceFd = -1;
- }
- }
- return fd >= 0 ? new Fence(fd) : Fence::NO_FENCE;
-}
-
-status_t HWComposer::commit() {
- int err = NO_ERROR;
- if (mHwc) {
- if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
- // On version 1.0, the OpenGL ES target surface is communicated
- // by the (dpy, sur) fields and we are guaranteed to have only
- // a single display.
- mLists[0]->dpy = eglGetCurrentDisplay();
- mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW);
- }
-
- for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) {
- DisplayData& disp(mDisplayData[i]);
- if (disp.outbufHandle) {
- mLists[i]->outbuf = disp.outbufHandle;
- mLists[i]->outbufAcquireFenceFd =
- disp.outbufAcquireFence->dup();
- }
- }
-
- err = mHwc->set(mHwc, mNumDisplays, mLists);
-
- for (size_t i=0 ; i<mNumDisplays ; i++) {
- DisplayData& disp(mDisplayData[i]);
- disp.lastDisplayFence = disp.lastRetireFence;
- disp.lastRetireFence = Fence::NO_FENCE;
- if (disp.list) {
- if (disp.list->retireFenceFd != -1) {
- disp.lastRetireFence = new Fence(disp.list->retireFenceFd);
- disp.list->retireFenceFd = -1;
- }
- disp.list->flags &= ~HWC_GEOMETRY_CHANGED;
- }
- }
- }
- return (status_t)err;
-}
-
-status_t HWComposer::setPowerMode(int disp, int mode) {
- LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
- if (mHwc) {
- if (mode == HWC_POWER_MODE_OFF) {
- eventControl(disp, HWC_EVENT_VSYNC, 0);
- }
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
- return (status_t)mHwc->setPowerMode(mHwc, disp, mode);
- } else {
- return (status_t)mHwc->blank(mHwc, disp,
- mode == HWC_POWER_MODE_OFF ? 1 : 0);
- }
- }
- return NO_ERROR;
-}
-
-status_t HWComposer::setActiveConfig(int disp, int mode) {
- LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
- DisplayData& dd(mDisplayData[disp]);
- dd.currentConfig = mode;
- if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
- return (status_t)mHwc->setActiveConfig(mHwc, disp, mode);
- } else {
- LOG_FATAL_IF(mode != 0);
- }
- return NO_ERROR;
-}
-
-void HWComposer::disconnectDisplay(int disp) {
- LOG_ALWAYS_FATAL_IF(disp < 0 || disp == HWC_DISPLAY_PRIMARY);
- DisplayData& dd(mDisplayData[disp]);
- free(dd.list);
- dd.list = NULL;
- dd.framebufferTarget = NULL; // points into dd.list
- dd.fbTargetHandle = NULL;
- dd.outbufHandle = NULL;
- dd.lastRetireFence = Fence::NO_FENCE;
- dd.lastDisplayFence = Fence::NO_FENCE;
- dd.outbufAcquireFence = Fence::NO_FENCE;
- // clear all the previous configs and repopulate when a new
- // device is added
- dd.configs.clear();
-}
-
-int HWComposer::getVisualID() const {
- if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
- // FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
- // is supported by the implementation. we can only be in this case
- // if we have HWC 1.1
- return HAL_PIXEL_FORMAT_RGBA_8888;
- //return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
- } else {
- return mFbDev->format;
- }
-}
-
-bool HWComposer::supportsFramebufferTarget() const {
- return (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
-}
-
-int HWComposer::fbPost(int32_t id,
- const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) {
- if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
- return setFramebufferTarget(id, acquireFence, buffer);
- } else {
- acquireFence->waitForever("HWComposer::fbPost");
- return mFbDev->post(mFbDev, buffer->handle);
- }
-}
-
-int HWComposer::fbCompositionComplete() {
- if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
- return NO_ERROR;
-
- if (mFbDev->compositionComplete) {
- return mFbDev->compositionComplete(mFbDev);
- } else {
- return INVALID_OPERATION;
- }
-}
-
-void HWComposer::fbDump(String8& result) {
- if (mFbDev && mFbDev->common.version >= 1 && mFbDev->dump) {
- const size_t SIZE = 4096;
- char buffer[SIZE];
- mFbDev->dump(mFbDev, buffer, SIZE);
- result.append(buffer);
- }
-}
-
-status_t HWComposer::setOutputBuffer(int32_t id, const sp<Fence>& acquireFence,
- const sp<GraphicBuffer>& buf) {
- if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
- return BAD_INDEX;
- if (id < VIRTUAL_DISPLAY_ID_BASE)
- return INVALID_OPERATION;
-
- DisplayData& disp(mDisplayData[id]);
- disp.outbufHandle = buf->handle;
- disp.outbufAcquireFence = acquireFence;
- return NO_ERROR;
-}
-
-sp<Fence> HWComposer::getLastRetireFence(int32_t id) const {
- if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
- return Fence::NO_FENCE;
- return mDisplayData[id].lastRetireFence;
-}
-
-status_t HWComposer::setCursorPositionAsync(int32_t id, const Rect& pos)
-{
- if (mHwc->setCursorPositionAsync) {
- return (status_t)mHwc->setCursorPositionAsync(mHwc, id, pos.left, pos.top);
- }
- else {
- return NO_ERROR;
- }
-}
-
-/*
- * Helper template to implement a concrete HWCLayer
- * This holds the pointer to the concrete hwc layer type
- * and implements the "iterable" side of HWCLayer.
- */
-template<typename CONCRETE, typename HWCTYPE>
-class Iterable : public HWComposer::HWCLayer {
-protected:
- HWCTYPE* const mLayerList;
- HWCTYPE* mCurrentLayer;
- explicit Iterable(HWCTYPE* layer) : mLayerList(layer), mCurrentLayer(layer),
- mIndex(0) { }
- inline HWCTYPE const * getLayer() const { return mCurrentLayer; }
- inline HWCTYPE* getLayer() { return mCurrentLayer; }
- virtual ~Iterable() { }
- size_t mIndex;
-private:
- // returns a copy of ourselves
- virtual HWComposer::HWCLayer* dup() {
- return new CONCRETE( static_cast<const CONCRETE&>(*this) );
- }
- virtual status_t setLayer(size_t index) {
- mIndex = index;
- mCurrentLayer = &mLayerList[index];
- return NO_ERROR;
- }
-};
-
-/*
- * Concrete implementation of HWCLayer for HWC_DEVICE_API_VERSION_1_0.
- * This implements the HWCLayer side of HWCIterableLayer.
- */
-class HWCLayerVersion1 : public Iterable<HWCLayerVersion1, hwc_layer_1_t> {
- struct hwc_composer_device_1* mHwc;
-public:
- HWCLayerVersion1(struct hwc_composer_device_1* hwc, hwc_layer_1_t* layer,
- Vector<Region>* visibleRegions,
- Vector<Region>* surfaceDamageRegions)
- : Iterable<HWCLayerVersion1, hwc_layer_1_t>(layer), mHwc(hwc),
- mVisibleRegions(visibleRegions),
- mSurfaceDamageRegions(surfaceDamageRegions) {}
-
- virtual int32_t getCompositionType() const {
- return getLayer()->compositionType;
- }
- virtual uint32_t getHints() const {
- return getLayer()->hints;
- }
- virtual sp<Fence> getAndResetReleaseFence() {
- int fd = getLayer()->releaseFenceFd;
- getLayer()->releaseFenceFd = -1;
- return fd >= 0 ? new Fence(fd) : Fence::NO_FENCE;
- }
- virtual void setAcquireFenceFd(int fenceFd) {
- getLayer()->acquireFenceFd = fenceFd;
- }
- virtual void setPerFrameDefaultState() {
- //getLayer()->compositionType = HWC_FRAMEBUFFER;
- }
- virtual void setPlaneAlpha(uint8_t alpha) {
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
- getLayer()->planeAlpha = alpha;
- } else {
- if (alpha < 0xFF) {
- getLayer()->flags |= HWC_SKIP_LAYER;
- }
- }
- }
- virtual void setDefaultState() {
- hwc_layer_1_t* const l = getLayer();
- l->compositionType = HWC_FRAMEBUFFER;
- l->hints = 0;
- l->flags = HWC_SKIP_LAYER;
- l->handle = 0;
- l->transform = 0;
- l->blending = HWC_BLENDING_NONE;
- l->visibleRegionScreen.numRects = 0;
- l->visibleRegionScreen.rects = NULL;
- l->acquireFenceFd = -1;
- l->releaseFenceFd = -1;
- l->planeAlpha = 0xFF;
- }
- virtual void setSkip(bool skip) {
- if (skip) {
- getLayer()->flags |= HWC_SKIP_LAYER;
- } else {
- getLayer()->flags &= ~HWC_SKIP_LAYER;
- }
- }
- virtual void setIsCursorLayerHint(bool isCursor) {
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
- if (isCursor) {
- getLayer()->flags |= HWC_IS_CURSOR_LAYER;
- }
- else {
- getLayer()->flags &= ~HWC_IS_CURSOR_LAYER;
- }
- }
- }
- virtual void setBlending(uint32_t blending) {
- getLayer()->blending = blending;
- }
- virtual void setTransform(uint32_t transform) {
- getLayer()->transform = transform;
- }
- virtual void setFrame(const Rect& frame) {
- getLayer()->displayFrame = reinterpret_cast<hwc_rect_t const&>(frame);
- }
- virtual void setCrop(const FloatRect& crop) {
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
- getLayer()->sourceCropf = reinterpret_cast<hwc_frect_t const&>(crop);
- } else {
- /*
- * Since h/w composer didn't support a flot crop rect before version 1.3,
- * using integer coordinates instead produces a different output from the GL code in
- * Layer::drawWithOpenGL(). The difference can be large if the buffer crop to
- * window size ratio is large and a window crop is defined
- * (i.e.: if we scale the buffer a lot and we also crop it with a window crop).
- */
- hwc_rect_t& r = getLayer()->sourceCrop;
- r.left = int(ceilf(crop.left));
- r.top = int(ceilf(crop.top));
- r.right = int(floorf(crop.right));
- r.bottom= int(floorf(crop.bottom));
- }
- }
- virtual void setVisibleRegionScreen(const Region& reg) {
- hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
- mVisibleRegions->editItemAt(mIndex) = reg;
- visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(
- mVisibleRegions->itemAt(mIndex).getArray(
- &visibleRegion.numRects));
- }
- virtual void setSurfaceDamage(const Region& reg) {
- if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_5)) {
- return;
- }
- hwc_region_t& surfaceDamage = getLayer()->surfaceDamage;
- // We encode default full-screen damage as INVALID_RECT upstream, but as
- // 0 rects for HWComposer
- if (reg.isRect() && reg.getBounds() == Rect::INVALID_RECT) {
- surfaceDamage.numRects = 0;
- surfaceDamage.rects = NULL;
- return;
- }
- mSurfaceDamageRegions->editItemAt(mIndex) = reg;
- surfaceDamage.rects = reinterpret_cast<hwc_rect_t const *>(
- mSurfaceDamageRegions->itemAt(mIndex).getArray(
- &surfaceDamage.numRects));
- }
- virtual void setSidebandStream(const sp<NativeHandle>& stream) {
- ALOG_ASSERT(stream->handle() != NULL);
- getLayer()->compositionType = HWC_SIDEBAND;
- getLayer()->sidebandStream = stream->handle();
- }
- virtual void setBuffer(const sp<GraphicBuffer>& buffer) {
- if (buffer == 0 || buffer->handle == 0) {
- getLayer()->compositionType = HWC_FRAMEBUFFER;
- getLayer()->flags |= HWC_SKIP_LAYER;
- getLayer()->handle = 0;
- } else {
- if (getLayer()->compositionType == HWC_SIDEBAND) {
- // If this was a sideband layer but the stream was removed, reset
- // it to FRAMEBUFFER. The HWC can change it to OVERLAY in prepare.
- getLayer()->compositionType = HWC_FRAMEBUFFER;
- }
- getLayer()->handle = buffer->handle;
- }
- }
- virtual void onDisplayed() {
- getLayer()->acquireFenceFd = -1;
- }
-
-protected:
- // Pointers to the vectors of Region backing-memory held in DisplayData.
- // Only the Region at mIndex corresponds to this Layer.
- Vector<Region>* mVisibleRegions;
- Vector<Region>* mSurfaceDamageRegions;
-};
-
-/*
- * returns an iterator initialized at a given index in the layer list
- */
-HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t index) {
- if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
- return LayerListIterator();
- }
- DisplayData& disp(mDisplayData[id]);
- if (!mHwc || !disp.list || index > disp.list->numHwLayers) {
- return LayerListIterator();
- }
- if (disp.visibleRegions.size() < disp.list->numHwLayers) {
- disp.visibleRegions.resize(disp.list->numHwLayers);
- }
- if (disp.surfaceDamageRegions.size() < disp.list->numHwLayers) {
- disp.surfaceDamageRegions.resize(disp.list->numHwLayers);
- }
- return LayerListIterator(new HWCLayerVersion1(mHwc, disp.list->hwLayers,
- &disp.visibleRegions, &disp.surfaceDamageRegions), index);
-}
-
-/*
- * returns an iterator on the beginning of the layer list
- */
-HWComposer::LayerListIterator HWComposer::begin(int32_t id) {
- return getLayerIterator(id, 0);
-}
-
-/*
- * returns an iterator on the end of the layer list
- */
-HWComposer::LayerListIterator HWComposer::end(int32_t id) {
- size_t numLayers = 0;
- if (uint32_t(id) <= 31 && mAllocatedDisplayIDs.hasBit(id)) {
- const DisplayData& disp(mDisplayData[id]);
- if (mHwc && disp.list) {
- numLayers = disp.list->numHwLayers;
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
- // with HWC 1.1, the last layer is always the HWC_FRAMEBUFFER_TARGET,
- // which we ignore when iterating through the layer list.
- ALOGE_IF(!numLayers, "mDisplayData[%d].list->numHwLayers is 0", id);
- if (numLayers) {
- numLayers--;
- }
- }
- }
- }
- return getLayerIterator(id, numLayers);
-}
-
-// Converts a PixelFormat to a human-readable string. Max 11 chars.
-// (Could use a table of prefab String8 objects.)
-static String8 getFormatStr(PixelFormat format) {
- switch (format) {
- case PIXEL_FORMAT_RGBA_8888: return String8("RGBA_8888");
- case PIXEL_FORMAT_RGBX_8888: return String8("RGBx_8888");
- case PIXEL_FORMAT_RGBA_FP16: return String8("RGBA_FP16");
- case PIXEL_FORMAT_RGBA_1010102: return String8("RGBA_1010102");
- case PIXEL_FORMAT_RGB_888: return String8("RGB_888");
- case PIXEL_FORMAT_RGB_565: return String8("RGB_565");
- case PIXEL_FORMAT_BGRA_8888: return String8("BGRA_8888");
- case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
- return String8("ImplDef");
- default:
- String8 result;
- result.appendFormat("? %08x", format);
- return result;
- }
-}
-
-void HWComposer::dump(String8& result) const {
- Mutex::Autolock _l(mDisplayLock);
- if (mHwc) {
- result.appendFormat("Hardware Composer state (version %08x):\n", hwcApiVersion(mHwc));
- result.appendFormat(" mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync);
- for (size_t i=0 ; i<mNumDisplays ; i++) {
- const DisplayData& disp(mDisplayData[i]);
- if (!disp.connected)
- continue;
-
- const Vector< sp<Layer> >& visibleLayersSortedByZ =
- mFlinger->getLayerSortedByZForHwcDisplay(i);
-
-
- result.appendFormat(" Display[%zd] configurations (* current):\n", i);
- for (size_t c = 0; c < disp.configs.size(); ++c) {
- const DisplayConfig& config(disp.configs[c]);
- result.appendFormat(" %s%zd: %ux%u, xdpi=%f, ydpi=%f"
- ", refresh=%" PRId64 ", colorMode=%d\n",
- c == disp.currentConfig ? "* " : "", c,
- config.width, config.height, config.xdpi, config.ydpi,
- config.refresh, config.colorMode);
- }
-
- if (disp.list) {
- result.appendFormat(
- " numHwLayers=%zu, flags=%08x\n",
- disp.list->numHwLayers, disp.list->flags);
-
- result.append(
- " type | handle | hint | flag | tr | blnd | format | source crop (l,t,r,b) | frame | name \n"
- "-----------+----------+------+------+----+------+-------------+--------------------------------+------------------------+------\n");
- // " _________ | ________ | ____ | ____ | __ | ____ | ___________ |_____._,_____._,_____._,_____._ |_____,_____,_____,_____ | ___...
- for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
- const hwc_layer_1_t&l = disp.list->hwLayers[i];
- int32_t format = -1;
- String8 name("unknown");
-
- if (i < visibleLayersSortedByZ.size()) {
- const sp<Layer>& layer(visibleLayersSortedByZ[i]);
- const sp<GraphicBuffer>& buffer(
- layer->getActiveBuffer());
- if (buffer != NULL) {
- format = buffer->getPixelFormat();
- }
- name = layer->getName();
- }
-
- int type = l.compositionType;
- if (type == HWC_FRAMEBUFFER_TARGET) {
- name = "HWC_FRAMEBUFFER_TARGET";
- format = disp.format;
- }
-
- static char const* compositionTypeName[] = {
- "GLES",
- "HWC",
- "BKGND",
- "FB TARGET",
- "SIDEBAND",
- "HWC_CURSOR",
- "UNKNOWN"};
- if (type >= NELEM(compositionTypeName))
- type = NELEM(compositionTypeName) - 1;
-
- String8 formatStr = getFormatStr(format);
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
- result.appendFormat(
- " %9s | %08" PRIxPTR " | %04x | %04x | %02x | %04x | %-11s |%7.1f,%7.1f,%7.1f,%7.1f |%5d,%5d,%5d,%5d | %s\n",
- compositionTypeName[type],
- intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, formatStr.string(),
- l.sourceCropf.left, l.sourceCropf.top, l.sourceCropf.right, l.sourceCropf.bottom,
- l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
- name.string());
- } else {
- result.appendFormat(
- " %9s | %08" PRIxPTR " | %04x | %04x | %02x | %04x | %-11s |%7d,%7d,%7d,%7d |%5d,%5d,%5d,%5d | %s\n",
- compositionTypeName[type],
- intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, formatStr.string(),
- l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom,
- l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
- name.string());
- }
- }
- }
- }
- }
-
- if (mHwc && mHwc->dump) {
- const size_t SIZE = 4096;
- char buffer[SIZE];
- mHwc->dump(mHwc, buffer, SIZE);
- result.append(buffer);
- }
-}
-
-// ---------------------------------------------------------------------------
-
-HWComposer::VSyncThread::VSyncThread(HWComposer& hwc)
- : mHwc(hwc), mEnabled(false),
- mNextFakeVSync(0),
- mRefreshPeriod(hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY))
-{
-}
-
-void HWComposer::VSyncThread::setEnabled(bool enabled) {
- Mutex::Autolock _l(mLock);
- if (mEnabled != enabled) {
- mEnabled = enabled;
- mCondition.signal();
- }
-}
-
-void HWComposer::VSyncThread::onFirstRef() {
- run("VSyncThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
-}
-
-bool HWComposer::VSyncThread::threadLoop() {
- { // scope for lock
- Mutex::Autolock _l(mLock);
- while (!mEnabled) {
- mCondition.wait(mLock);
- }
- }
-
- const nsecs_t period = mRefreshPeriod;
- const nsecs_t now = systemTime(CLOCK_MONOTONIC);
- nsecs_t next_vsync = mNextFakeVSync;
- nsecs_t sleep = next_vsync - now;
- if (sleep < 0) {
- // we missed, find where the next vsync should be
- sleep = (period - ((now - next_vsync) % period));
- next_vsync = now + sleep;
- }
- mNextFakeVSync = next_vsync + period;
-
- struct timespec spec;
- spec.tv_sec = next_vsync / 1000000000;
- spec.tv_nsec = next_vsync % 1000000000;
-
- int err;
- do {
- err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
- } while (err<0 && errno == EINTR);
-
- if (err == 0) {
- mHwc.mEventHandler.onVSyncReceived(&mHwc, 0, next_vsync);
- }
-
- return true;
-}
-
-HWComposer::DisplayData::DisplayData()
-: configs(),
- currentConfig(0),
- format(HAL_PIXEL_FORMAT_RGBA_8888),
- connected(false),
- hasFbComp(false), hasOvComp(false),
- capacity(0), list(NULL),
- framebufferTarget(NULL), fbTargetHandle(0),
- lastRetireFence(Fence::NO_FENCE), lastDisplayFence(Fence::NO_FENCE),
- outbufHandle(NULL), outbufAcquireFence(Fence::NO_FENCE),
- events(0)
-{}
-
-HWComposer::DisplayData::~DisplayData() {
- free(list);
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 1de5e48..cde96e4 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -176,12 +176,6 @@
return NO_ERROR;
}
-#ifndef USE_HWC2
-status_t VirtualDisplaySurface::compositionComplete() {
- return NO_ERROR;
-}
-#endif
-
status_t VirtualDisplaySurface::advanceFrame() {
if (mDisplayId < 0)
return NO_ERROR;
@@ -221,7 +215,6 @@
status_t result = NO_ERROR;
if (fbBuffer != NULL) {
-#ifdef USE_HWC2
uint32_t hwcSlot = 0;
sp<GraphicBuffer> hwcBuffer;
mHwcBufferCache.getHwcBuffer(mFbProducerSlot, fbBuffer,
@@ -230,9 +223,6 @@
// TODO: Correctly propagate the dataspace from GL composition
result = mHwc.setClientTarget(mDisplayId, hwcSlot, mFbFence,
hwcBuffer, HAL_DATASPACE_UNKNOWN);
-#else
- result = mHwc.fbPost(mDisplayId, mFbFence, fbBuffer);
-#endif
}
return result;
@@ -246,32 +236,20 @@
"Unexpected onFrameCommitted() in %s state", dbgStateStr());
mDbgState = DBG_STATE_IDLE;
-#ifdef USE_HWC2
sp<Fence> retireFence = mHwc.getPresentFence(mDisplayId);
-#else
- sp<Fence> fbFence = mHwc.getAndResetReleaseFence(mDisplayId);
-#endif
if (mCompositionType == COMPOSITION_MIXED && mFbProducerSlot >= 0) {
// release the scratch buffer back to the pool
Mutex::Autolock lock(mMutex);
int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, mFbProducerSlot);
VDS_LOGV("onFrameCommitted: release scratch sslot=%d", sslot);
-#ifdef USE_HWC2
addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot],
retireFence);
-#else
- addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot], fbFence);
-#endif
- releaseBufferLocked(sslot, mProducerBuffers[mFbProducerSlot],
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
+ releaseBufferLocked(sslot, mProducerBuffers[mFbProducerSlot]);
}
if (mOutputProducerSlot >= 0) {
int sslot = mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot);
QueueBufferOutput qbo;
-#ifndef USE_HWC2
- sp<Fence> outFence = mHwc.getLastRetireFence(mDisplayId);
-#endif
VDS_LOGV("onFrameCommitted: queue sink sslot=%d", sslot);
if (mMustRecompose) {
status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
@@ -280,11 +258,7 @@
HAL_DATASPACE_UNKNOWN,
Rect(mSinkBufferWidth, mSinkBufferHeight),
NATIVE_WINDOW_SCALING_MODE_FREEZE, 0 /* transform */,
-#ifdef USE_HWC2
retireFence),
-#else
- outFence),
-#endif
&qbo);
if (result == NO_ERROR) {
updateQueueBufferOutput(std::move(qbo));
@@ -294,11 +268,7 @@
// through the motions of updating the display to keep our state
// machine happy. We cancel the buffer to avoid triggering another
// re-composition and causing an infinite loop.
-#ifdef USE_HWC2
mSource[SOURCE_SINK]->cancelBuffer(sslot, retireFence);
-#else
- mSource[SOURCE_SINK]->cancelBuffer(sslot, outFence);
-#endif
}
}
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 1671aba..5c8acea 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -84,9 +84,6 @@
//
virtual status_t beginFrame(bool mustRecompose);
virtual status_t prepareFrame(CompositionType compositionType);
-#ifndef USE_HWC2
- virtual status_t compositionComplete();
-#endif
virtual status_t advanceFrame();
virtual void onFrameCommitted();
virtual void dumpAsString(String8& result) const;
@@ -253,10 +250,7 @@
bool mMustRecompose;
-#ifdef USE_HWC2
HWComposerBufferCache mHwcBufferCache;
-#endif
-
bool mForceHwcCopy;
};
diff --git a/services/surfaceflinger/EventControlThread.cpp b/services/surfaceflinger/EventControlThread.cpp
index 052a959..02eea47 100644
--- a/services/surfaceflinger/EventControlThread.cpp
+++ b/services/surfaceflinger/EventControlThread.cpp
@@ -53,12 +53,7 @@
}
bool enable = requestedVsyncState == VsyncState::On;
-#ifdef USE_HWC2
mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, enable);
-#else
- mFlinger->eventControl(HWC_DISPLAY_PRIMARY,
- SurfaceFlinger::EVENT_VSYNC, enable);
-#endif
currentVsyncState = requestedVsyncState;
}
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 ca9a546..2a4abcb
--- 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,41 @@
#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 {
-// ---------------------------------------------------------------------------
+LayerBE::LayerBE()
+ : mBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),
+ mBuffer(nullptr),
+ mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) {
+}
+
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,69 +85,43 @@
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),
- mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2),
-#ifndef USE_HWC2
- 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;
@@ -153,149 +131,39 @@
// drawing state & current state are identical
mDrawingState = mCurrentState;
-#ifdef USE_HWC2
const auto& hwc = flinger->getHwComposer();
const auto& activeConfig = hwc.getActiveConfig(HWC_DISPLAY_PRIMARY);
nsecs_t displayPeriod = activeConfig->getVsyncPeriod();
-#else
- nsecs_t displayPeriod =
- flinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
-#endif
mFrameTracker.setDisplayRefreshPeriod(displayPeriod);
CompositorTiming compositorTiming;
flinger->getCompositorTiming(&compositorTiming);
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
// ---------------------------------------------------------------------------
-#ifdef USE_HWC2
-void Layer::onLayerDisplayed(const sp<Fence>& releaseFence) {
- mSurfaceFlingerConsumer->setReleaseFence(releaseFence);
-}
-#else
-void Layer::onLayerDisplayed(const sp<const DisplayDevice>& /* hw */,
- HWComposer::HWCLayerInterface* layer) {
- if (layer) {
- layer->onDisplayed();
- mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFence());
- }
-}
-#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();
- }
-}
+/*
+ * 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.
+ */
+void Layer::onLayerDisplayed(const sp<Fence>& /*releaseFence*/) {}
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) {
@@ -312,11 +180,9 @@
void Layer::onRemoved() {
// the layer is removed from SF mLayersPendingRemoval
+ abandon();
- mSurfaceFlingerConsumer->abandon();
-#ifdef USE_HWC2
destroyAllHwcLayers();
-#endif
for (const auto& child : mCurrentChildren) {
child->onRemoved();
@@ -331,94 +197,58 @@
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(getBE().mHwcLayers.count(hwcId) != 0,
+ "Already have a layer for hwcId %d", hwcId);
HWC2::Layer* layer = hwc->createLayer(hwcId);
if (!layer) {
return false;
}
- HWCInfo& hwcInfo = mHwcLayers[hwcId];
+ LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers[hwcId];
hwcInfo.hwc = hwc;
hwcInfo.layer = layer;
layer->setLayerDestroyedListener(
- [this, hwcId] (HWC2::Layer* /*layer*/){mHwcLayers.erase(hwcId);});
+ [this, hwcId](HWC2::Layer* /*layer*/) { getBE().mHwcLayers.erase(hwcId); });
return true;
}
bool Layer::destroyHwcLayer(int32_t hwcId) {
- if (mHwcLayers.count(hwcId) == 0) {
+ if (getBE().mHwcLayers.count(hwcId) == 0) {
return false;
}
- auto& hwcInfo = mHwcLayers[hwcId];
- LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr,
- "Attempt to destroy null layer");
+ auto& hwcInfo = getBE().mHwcLayers[hwcId];
+ 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(getBE().mHwcLayers.count(hwcId) != 0,
+ "Stale layer entry in getBE().mHwcLayers");
return true;
}
void Layer::destroyAllHwcLayers() {
- size_t numLayers = mHwcLayers.size();
+ size_t numLayers = getBE().mHwcLayers.size();
for (size_t i = 0; i < numLayers; ++i) {
- LOG_ALWAYS_FATAL_IF(mHwcLayers.empty(), "destroyAllHwcLayers failed");
- destroyHwcLayer(mHwcLayers.begin()->first);
+ LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.empty(), "destroyAllHwcLayers failed");
+ destroyHwcLayer(getBE().mHwcLayers.begin()->first);
}
- LOG_ALWAYS_FATAL_IF(!mHwcLayers.empty(),
- "All hardware composer layers should have been destroyed");
+ LOG_ALWAYS_FATAL_IF(!getBE().mHwcLayers.empty(),
+ "All hardware composer layers should have been destroyed");
}
-#endif
Rect Layer::getContentCrop() const {
// this is the crop rectangle that applies to the buffer
@@ -427,9 +257,9 @@
if (!mCurrentCrop.isEmpty()) {
// if the buffer crop is defined, we use that
crop = mCurrentCrop;
- } else if (mActiveBuffer != NULL) {
+ } else if (getBE().mBuffer != NULL) {
// otherwise we use the whole buffer
- crop = mActiveBuffer->getBounds();
+ crop = getBE().mBuffer->getBounds();
} else {
// if we don't have a buffer yet, we use an empty/invalid crop
crop.makeInvalid();
@@ -540,10 +370,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;
}
@@ -557,11 +394,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);
@@ -588,16 +420,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;
@@ -611,49 +440,36 @@
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;
}
-#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)
-#endif
{
-#ifdef USE_HWC2
const auto hwcId = displayDevice->getHwcDisplayId();
- auto& hwcInfo = mHwcLayers[hwcId];
-#else
- layer.setDefaultState();
-#endif
+ auto& hwcInfo = getBE().mHwcLayers[hwcId];
// enable this layer
-#ifdef USE_HWC2
hwcInfo.forceClientComposition = false;
if (isSecure() && !displayDevice->isSecure()) {
@@ -661,33 +477,20 @@
}
auto& hwcLayer = hwcInfo.layer;
-#else
- layer.setSkip(false);
-
- if (isSecure() && !hw->isSecure()) {
- layer.setSkip(true);
- }
-#endif
// this gives us only the "orientation" component of the transform
const State& s(getDrawingState());
-#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));
-#else
- if (!isOpaque(s) || getAlpha() != 0xFF) {
- layer.setBlending(mPremultipliedAlpha ?
- HWC_BLENDING_PREMULT :
- HWC_BLENDING_COVERAGE);
- }
-#endif
+ 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));
// apply the layer's transform, followed by the display's global transform
// here we're guaranteed that the layer's transform preserves rects
@@ -696,11 +499,7 @@
if (!s.crop.isEmpty()) {
Rect activeCrop(s.crop);
activeCrop = t.transform(activeCrop);
-#ifdef USE_HWC2
- if(!activeCrop.intersect(displayDevice->getViewport(), &activeCrop)) {
-#else
- if(!activeCrop.intersect(hw->getViewport(), &activeCrop)) {
-#endif
+ if (!activeCrop.intersect(displayDevice->getViewport(), &activeCrop)) {
activeCrop.clear();
}
activeCrop = t.inverse().transform(activeCrop, true);
@@ -710,26 +509,23 @@
// 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();
}
}
-#ifdef USE_HWC2
if (!frame.intersect(displayDevice->getViewport(), &frame)) {
frame.clear();
}
@@ -737,10 +533,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;
}
@@ -749,23 +544,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;
@@ -777,17 +572,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));
-#else
- if (!frame.intersect(hw->getViewport(), &frame)) {
- frame.clear();
- }
- const Transform& tr(hw->getTransform());
- layer.setFrame(tr.transform(frame));
- layer.setCrop(computeCrop(hw));
- layer.setPlaneAlpha(getAlpha());
-#endif
+ ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)", mName.string(),
+ static_cast<int32_t>(error));
/*
* Transformations are applied in this order:
@@ -805,12 +591,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;
}
/*
@@ -824,163 +608,42 @@
// this gives us only the "orientation" component of the transform
const uint32_t orientation = transform.getOrientation();
-#ifdef USE_HWC2
if (orientation & Transform::ROT_INVALID) {
// we can only handle simple transformation
hwcInfo.forceClientComposition = true;
} 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) {
- // we can only handle simple transformation
- layer.setSkip(true);
- } else {
- layer.setTransform(orientation);
- }
-#endif
}
-#ifdef USE_HWC2
void Layer::forceClientComposition(int32_t hwcId) {
- if (mHwcLayers.count(hwcId) == 0) {
+ if (getBE().mHwcLayers.count(hwcId) == 0) {
ALOGE("forceClientComposition: no HWC layer found (%d)", hwcId);
return;
}
- mHwcLayers[hwcId].forceClientComposition = true;
+ getBE().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);
+bool Layer::getForceClientComposition(int32_t hwcId) {
+ if (getBE().mHwcLayers.count(hwcId) == 0) {
+ ALOGE("getForceClientComposition: no HWC layer found (%d)", hwcId);
+ return false;
}
- 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));
- }
+ return getBE().mHwcLayers[hwcId].forceClientComposition;
}
-#else
-void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
- 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.
- // Apply this display's projection's viewport to the visible region
- // before giving it to the HWC HAL.
- const Transform& tr = hw->getTransform();
- Region visible = tr.transform(visibleRegion.intersect(hw->getViewport()));
- layer.setVisibleRegionScreen(visible);
- layer.setSurfaceDamage(surfaceDamageRegion);
- mIsGlesComposition = (layer.getCompositionType() == HWC_FRAMEBUFFER);
-
- if (mSidebandStream.get()) {
- layer.setSidebandStream(mSidebandStream);
- } else {
- // NOTE: buffer can be NULL if the client never drew into this
- // layer yet, or if we ran out of memory
- layer.setBuffer(mActiveBuffer);
- }
-}
-#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 (getBE().mHwcLayers.count(hwcId) == 0 ||
+ getCompositionType(hwcId) != HWC2::Composition::Cursor) {
return;
}
@@ -1003,284 +666,62 @@
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 = getBE().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)
-{
- // this gives us only the "orientation" component of the transform
- const State& s(getCurrentState());
-
- // apply the layer's transform, followed by the display's global transform
- // here we're guaranteed that the layer's transform preserves rects
- Rect win(s.active.w, s.active.h);
- if (!s.crop.isEmpty()) {
- win.intersect(s.crop, &win);
- }
- // subtract the transparent region and snap to the bounds
- Rect bounds = reduce(win, s.activeTransparentRegion);
- Rect frame(getTransform().transform(bounds));
- frame.intersect(hw->getViewport(), &frame);
- if (!s.finalCrop.isEmpty()) {
- frame.intersect(s.finalCrop, &frame);
- }
- const Transform& tr(hw->getTransform());
- return Rect(tr.transform(frame));
-}
-#endif
// ---------------------------------------------------------------------------
// 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, getBE().mMesh, false);
engine.setupFillWithColor(red, green, blue, alpha);
- engine.drawMesh(mMesh);
+ engine.drawMesh(getBE().mMesh);
}
-void Layer::clearWithOpenGL(
- const sp<const DisplayDevice>& hw) const {
- clearWithOpenGL(hw, 0,0,0,0);
+void Layer::clearWithOpenGL(const RenderArea& renderArea) const {
+ clearWithOpenGL(renderArea, 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();
-}
-
-#ifdef USE_HWC2
-void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type,
- bool callIntoHwc) {
- if (mHwcLayers.count(hwcId) == 0) {
+void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc) {
+ if (getBE().mHwcLayers.count(hwcId) == 0) {
ALOGE("setCompositionType called without a valid HWC layer");
return;
}
- auto& hwcInfo = mHwcLayers[hwcId];
+ auto& hwcInfo = getBE().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));
}
}
}
@@ -1291,86 +732,27 @@
// have a HWC counterpart, then it will always be Client
return HWC2::Composition::Client;
}
- if (mHwcLayers.count(hwcId) == 0) {
+ if (getBE().mHwcLayers.count(hwcId) == 0) {
ALOGE("getCompositionType called with an invalid HWC layer");
return HWC2::Composition::Invalid;
}
- return mHwcLayers.at(hwcId).compositionType;
+ return getBE().mHwcLayers.at(hwcId).compositionType;
}
void Layer::setClearClientTarget(int32_t hwcId, bool clear) {
- if (mHwcLayers.count(hwcId) == 0) {
+ if (getBE().mHwcLayers.count(hwcId) == 0) {
ALOGE("setClearClientTarget called without a valid HWC layer");
return;
}
- mHwcLayers[hwcId].clearClientTarget = clear;
+ getBE().mHwcLayers[hwcId].clearClientTarget = clear;
}
bool Layer::getClearClientTarget(int32_t hwcId) const {
- if (mHwcLayers.count(hwcId) == 0) {
+ if (getBE().mHwcLayers.count(hwcId) == 0) {
ALOGE("getClearClientTarget called without a valid HWC layer");
return false;
}
- return mHwcLayers.at(hwcId).clearClientTarget;
-}
-#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
+ return getBE().mHwcLayers.at(hwcId).clearClientTarget;
}
bool Layer::addSyncPoint(const std::shared_ptr<SyncPoint>& point) {
@@ -1393,28 +775,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
// ----------------------------------------------------------------------------
@@ -1434,12 +794,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);
@@ -1463,53 +822,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;
@@ -1520,8 +846,7 @@
this->coveredRegion = coveredRegion;
}
-void Layer::setVisibleNonTransparentRegion(const Region&
- setVisibleNonTransparentRegion) {
+void Layer::setVisibleNonTransparentRegion(const Region& setVisibleNonTransparentRegion) {
// always called from main thread
this->visibleNonTransparentRegion = setVisibleNonTransparentRegion;
}
@@ -1546,8 +871,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 {
@@ -1568,8 +892,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());
@@ -1589,10 +913,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();
@@ -1628,17 +950,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();
@@ -1650,59 +961,50 @@
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)) &&
+ (getBE().mBuffer != 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
-
+ if (resizePending && getBE().mSidebandStream == NULL) {
flags |= eDontUpdateGeometryState;
}
}
@@ -1749,8 +1051,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
@@ -1812,9 +1113,21 @@
return true;
}
-bool Layer::setLayer(int32_t z) {
- if (mCurrentState.z == z)
+bool Layer::setChildRelativeLayer(const sp<Layer>& childLayer,
+ const sp<IBinder>& relativeToHandle, int32_t relativeZ) {
+ ssize_t idx = mCurrentChildren.indexOf(childLayer);
+ if (idx < 0) {
return false;
+ }
+ if (childLayer->setRelativeLayer(relativeToHandle, relativeZ)) {
+ mCurrentChildren.removeAt(idx);
+ mCurrentChildren.add(childLayer);
+ }
+ return true;
+}
+
+bool Layer::setLayer(int32_t z) {
+ if (mCurrentState.z == z) return false;
mCurrentState.sequence++;
mCurrentState.z = z;
mCurrentState.modified = true;
@@ -1859,6 +1172,10 @@
mCurrentState.modified = true;
mCurrentState.z = z;
+ auto oldZOrderRelativeOf = mCurrentState.zOrderRelativeOf.promote();
+ if (oldZOrderRelativeOf != nullptr) {
+ oldZOrderRelativeOf->removeZOrderRelative(this);
+ }
mCurrentState.zOrderRelativeOf = relative;
relative->addZOrderRelative(this);
@@ -1868,31 +1185,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;
@@ -1905,8 +1230,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;
@@ -1916,8 +1240,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) {
@@ -1931,8 +1254,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) {
@@ -1946,30 +1268,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;
@@ -1978,8 +1291,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;
@@ -1999,8 +1311,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
@@ -2012,124 +1323,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();
@@ -2139,256 +1342,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
@@ -2413,7 +1367,7 @@
orientation = 0;
}
}
- mSurfaceFlingerConsumer->setTransformHint(orientation);
+ setTransformHint(orientation);
}
// ----------------------------------------------------------------------------
@@ -2438,7 +1392,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();
@@ -2447,12 +1401,12 @@
info.mMatrix[1][0] = ds.active.transform[1][0];
info.mMatrix[1][1] = ds.active.transform[1][1];
{
- sp<const GraphicBuffer> activeBuffer = getActiveBuffer();
- if (activeBuffer != 0) {
- info.mActiveBufferWidth = activeBuffer->getWidth();
- info.mActiveBufferHeight = activeBuffer->getHeight();
- info.mActiveBufferStride = activeBuffer->getStride();
- info.mActiveBufferFormat = activeBuffer->format;
+ sp<const GraphicBuffer> buffer = getBE().mBuffer;
+ if (buffer != 0) {
+ info.mActiveBufferWidth = buffer->getWidth();
+ info.mActiveBufferHeight = buffer->getHeight();
+ info.mActiveBufferStride = buffer->getStride();
+ info.mActiveBufferFormat = buffer->format;
} else {
info.mActiveBufferWidth = 0;
info.mActiveBufferHeight = 0;
@@ -2467,7 +1421,6 @@
return info;
}
-#ifdef USE_HWC2
void Layer::miniDumpHeader(String8& result) {
result.append("----------------------------------------");
result.append("---------------------------------------\n");
@@ -2481,7 +1434,7 @@
}
void Layer::miniDump(String8& result, int32_t hwcId) const {
- if (mHwcLayers.count(hwcId) == 0) {
+ if (getBE().mHwcLayers.count(hwcId) == 0) {
return;
}
@@ -2499,21 +1452,17 @@
result.appendFormat(" %s\n", name.string());
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());
+ const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(hwcId);
+ 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");
}
-#endif
void Layer::dumpFrameStats(String8& result) const {
mFrameTracker.dumpStats(result);
@@ -2532,8 +1481,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);
@@ -2545,7 +1493,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
@@ -2563,23 +1511,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) {
@@ -2624,17 +1555,43 @@
return true;
}
-bool Layer::detachChildren() {
- traverseInZOrder(LayerVector::StateSet::Drawing, [this](Layer* child) {
- if (child == this) {
- return;
- }
+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() {
+ for (const sp<Layer>& child : mCurrentChildren) {
+ sp<Client> parentClient = mClientRef.promote();
sp<Client> client(child->mClientRef.promote());
- if (client != nullptr) {
- client->detachLayer(child);
+ if (client != nullptr && parentClient != client) {
+ client->detachLayer(child.get());
+ child->detachChildren();
}
- });
+ }
return true;
}
@@ -2659,18 +1616,15 @@
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;
const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
const State& state = useDrawing ? mDrawingState : mCurrentState;
- if (state.zOrderRelatives.size() == 0) {
- return children;
- }
LayerVector traverse;
-
for (const wp<Layer>& weakRelative : state.zOrderRelatives) {
sp<Layer> strongRelative = weakRelative.promote();
if (strongRelative != nullptr) {
@@ -2679,6 +1633,10 @@
}
for (const sp<Layer>& child : children) {
+ const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState;
+ if (childState.zOrderRelativeOf != nullptr) {
+ continue;
+ }
traverse.add(child);
}
@@ -2714,7 +1672,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;
@@ -2722,12 +1680,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();
@@ -2739,20 +1720,18 @@
// for in the transform. We need to mirror this scaling in child surfaces
// or we will break the contract where WM can treat child surfaces as
// pixels in the parent surface.
- if (p->isFixedSize() && p->mActiveBuffer != nullptr) {
+ if (p->isFixedSize() && p->getBE().mBuffer != nullptr) {
int bufferWidth;
int bufferHeight;
if ((p->mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) == 0) {
- bufferWidth = p->mActiveBuffer->getWidth();
- bufferHeight = p->mActiveBuffer->getHeight();
+ bufferWidth = p->getBE().mBuffer->getWidth();
+ bufferHeight = p->getBE().mBuffer->getHeight();
} else {
- bufferHeight = p->mActiveBuffer->getWidth();
- bufferWidth = p->mActiveBuffer->getHeight();
+ bufferHeight = p->getBE().mBuffer->getWidth();
+ bufferWidth = p->getBE().mBuffer->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;
@@ -2761,23 +1740,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++) {
@@ -2788,6 +1761,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 = useDrawing ? mDrawingParent.promote() : mCurrentParent.promote();
+ 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 buffer = getBE().mBuffer;
+ if (buffer != nullptr) {
+ LayerProtoHelper::writeToProto(buffer, 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 f7501a3..8ac5094 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -20,9 +20,6 @@
#include <stdint.h>
#include <sys/types.h>
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
#include <utils/RefBase.h>
#include <utils/String8.h>
#include <utils/Timers.h>
@@ -33,24 +30,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 {
// ---------------------------------------------------------------------------
@@ -61,20 +62,54 @@
class GraphicBuffer;
class SurfaceFlinger;
class LayerDebugInfo;
+class LayerBE;
// ---------------------------------------------------------------------------
-/*
- * 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 LayerBE {
+public:
+ LayerBE();
+
+ // main thread
+ int mBufferSlot;
+ sp<GraphicBuffer> mBuffer;
+ sp<NativeHandle> mSidebandStream;
+
+ // The mesh used to draw the layer in GLES composition mode
+ Mesh mMesh;
+
+ // HWC items, accessed from the main thread
+ struct HWCInfo {
+ HWCInfo()
+ : hwc(nullptr),
+ layer(nullptr),
+ forceClientComposition(false),
+ compositionType(HWC2::Composition::Invalid),
+ clearClientTarget(false) {}
+
+ HWComposer* hwc;
+ HWC2::Layer* layer;
+ bool forceClientComposition;
+ HWC2::Composition compositionType;
+ bool clearClientTarget;
+ Rect displayFrame;
+ FloatRect sourceCrop;
+ HWComposerBufferCache bufferCache;
+ };
+
+ // A layer can be attached to multiple displays when operating in mirror mode
+ // (a.k.a: when several displays are attached with equal layerStack). In this
+ // case we need to keep track. In non-mirror mode, a layer will have only one
+ // HWCInfo. This map key is a display layerStack.
+ std::unordered_map<int32_t, HWCInfo> mHwcLayers;
+};
+
+class Layer : public virtual RefBase {
static int32_t sSequence;
public:
+ LayerBE& getBE() { return mBE; }
+ LayerBE& getBE() const { return mBE; }
mutable bool contentDirty;
// regions below are in window-manager space
Region visibleRegion;
@@ -97,14 +132,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 +151,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 +185,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 +248,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 +261,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 +277,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 +285,7 @@
// -----------------------------------------------------------------------
// Virtuals
-
- virtual const char* getTypeId() const { return "Layer"; }
+ virtual const char* getTypeId() const = 0;
/*
* isOpaque - true if this surface is opaque
@@ -275,24 +294,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,87 +313,75 @@
* 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);
+ bool getForceClientComposition(int32_t hwcId);
+ 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);
-
- Rect getPosition(const sp<const DisplayDevice>& hw);
-#endif
/*
* called after page-flip
*/
-#ifdef USE_HWC2
- void onLayerDisplayed(const sp<Fence>& releaseFence);
-#else
- void onLayerDisplayed(const sp<const DisplayDevice>& hw,
- HWComposer::HWCLayerInterface* layer);
-#endif
+ virtual void onLayerDisplayed(const sp<Fence>& releaseFence);
- 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);
-#endif
+ virtual void releasePendingBuffer(nsecs_t dequeueReadyTime) = 0;
/*
* 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 +406,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 +414,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 +430,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,12 +443,12 @@
/*
* 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; }
-#ifdef USE_HWC2
// -----------------------------------------------------------------------
bool createHwcLayer(HWComposer* hwc, int32_t hwcId);
@@ -458,66 +456,61 @@
void destroyAllHwcLayers();
bool hasHwcLayer(int32_t hwcId) {
- return mHwcLayers.count(hwcId) > 0;
+ return getBE().mHwcLayers.count(hwcId) > 0;
}
HWC2::Layer* getHwcLayer(int32_t hwcId) {
- if (mHwcLayers.count(hwcId) == 0) {
+ if (getBE().mHwcLayers.count(hwcId) == 0) {
return nullptr;
}
- return mHwcLayers[hwcId].layer;
+ return getBE().mHwcLayers[hwcId].layer;
}
-#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;
/* always call base class first */
-#ifdef USE_HWC2
static void miniDumpHeader(String8& result);
void miniDump(String8& result, int32_t hwcId) const;
-#endif
void dumpFrameStats(String8& result) const;
void dumpFrameEvents(String8& result);
void clearFrameStats();
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 +518,16 @@
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);
+ bool setChildRelativeLayer(const sp<Layer>& childLayer,
+ const sp<IBinder>& relativeToHandle, int32_t relativeZ);
// 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 +538,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 +575,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 +606,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 +618,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 +630,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,60 +681,24 @@
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;
// Whether filtering is needed b/c of the drawingstate
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;
-#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) {}
-
- HWComposer* hwc;
- HWC2::Layer* layer;
- bool forceClientComposition;
- HWC2::Composition compositionType;
- bool clearClientTarget;
- Rect displayFrame;
- FloatRect sourceCrop;
- HWComposerBufferCache bufferCache;
- };
-
- // A layer can be attached to multiple displays when operating in mirror mode
- // (a.k.a: when several displays are attached with equal layerStack). In this
- // case we need to keep track. In non-mirror mode, a layer will have only one
- // HWCInfo. This map key is a display layerStack.
- std::unordered_map<int32_t, HWCInfo> mHwcLayers;
-#else
- bool mIsGlesComposition;
-#endif
+ bool mPendingRemoval = false;
// page-flip thread (currently main thread)
bool mProtectedByApp; // application requires protected path to external sink
// 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 +709,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;
@@ -810,6 +719,8 @@
wp<Layer> mCurrentParent;
wp<Layer> mDrawingParent;
+
+ mutable LayerBE mBE;
};
// ---------------------------------------------------------------------------
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..47156c1 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;
+ int32_t lz = l->getCurrentState().z;
+ int32_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..fa4df83
--- /dev/null
+++ b/services/surfaceflinger/RenderArea.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include "Transform.h"
+
+namespace android {
+
+class RenderArea {
+public:
+ RenderArea(uint32_t reqHeight, uint32_t reqWidth,
+ ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone)
+ : 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; };
+ virtual bool getWideColorSupport() const = 0;
+ virtual android_color_mode_t getActiveColorMode() const = 0;
+
+ status_t updateDimensions();
+
+private:
+ uint32_t mReqHeight;
+ uint32_t mReqWidth;
+ Transform::orientation_flags mRotationFlags;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp
index effd319..e014406 100644
--- a/services/surfaceflinger/RenderEngine/Description.cpp
+++ b/services/surfaceflinger/RenderEngine/Description.cpp
@@ -27,21 +27,13 @@
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;
-}
+Description::~Description() {}
void Description::setPremultipliedAlpha(bool premultipliedAlpha) {
mPremultipliedAlpha = premultipliedAlpha;
@@ -60,11 +52,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..3161888 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -33,18 +33,17 @@
#include <gui/ISurfaceComposer.h>
#include <math.h>
+#include "Description.h"
#include "GLES20RenderEngine.h"
+#include "Mesh.h"
#include "Program.h"
#include "ProgramCache.h"
-#include "Description.h"
-#include "Mesh.h"
#include "Texture.h"
-#include <sstream>
#include <fstream>
+#include <sstream>
// ---------------------------------------------------------------------------
-#ifdef USE_HWC2
bool checkGlError(const char* op, int lineNumber) {
bool errorFound = false;
GLint error = glGetError();
@@ -103,41 +102,36 @@
}
file.write(reinterpret_cast<char*>(outBuffer.data()), outBuffer.size());
}
-#endif
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
-GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags) :
- mVpWidth(0),
- mVpHeight(0),
- mPlatformHasWideColor((featureFlags & WIDE_COLOR_SUPPORT) != 0) {
-
+GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags)
+ : mVpWidth(0), mVpHeight(0), mPlatformHasWideColor((featureFlags & WIDE_COLOR_SUPPORT) != 0) {
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glPixelStorei(GL_PACK_ALIGNMENT, 4);
- const uint16_t protTexData[] = { 0 };
+ const uint16_t protTexData[] = {0};
glGenTextures(1, &mProtectedTexName);
glBindTexture(GL_TEXTURE_2D, mProtectedTexName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0,
- GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData);
- //mColorBlindnessCorrection = M;
+ // mColorBlindnessCorrection = M;
-#ifdef USE_HWC2
if (mPlatformHasWideColor) {
// Compute sRGB to DisplayP3 color transform
// NOTE: For now, we are limiting wide-color support to
// Display-P3 only.
- mat3 srgbToP3 = ColorSpaceConnector(ColorSpace::sRGB(), ColorSpace::DisplayP3()).getTransform();
+ mat3 srgbToP3 =
+ ColorSpaceConnector(ColorSpace::sRGB(), ColorSpace::DisplayP3()).getTransform();
// color transform needs to be expanded to 4x4 to be what the shader wants
// mat has an initializer that expands mat3 to mat4, but
@@ -145,27 +139,21 @@
mat4 gamutTransform(srgbToP3);
mSrgbToDisplayP3 = gamutTransform;
}
-#endif
}
-GLES20RenderEngine::~GLES20RenderEngine() {
-}
-
+GLES20RenderEngine::~GLES20RenderEngine() {}
size_t GLES20RenderEngine::getMaxTextureSize() const {
return mMaxTextureSize;
}
size_t GLES20RenderEngine::getMaxViewportDims() const {
- return
- mMaxViewportDims[0] < mMaxViewportDims[1] ?
- mMaxViewportDims[0] : mMaxViewportDims[1];
+ return mMaxViewportDims[0] < mMaxViewportDims[1] ? mMaxViewportDims[0] : mMaxViewportDims[1];
}
-void GLES20RenderEngine::setViewportAndProjection(
- size_t vpw, size_t vph, Rect sourceCrop, size_t hwh, bool yswap,
- Transform::orientation_flags rotation) {
-
+void GLES20RenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
+ size_t hwh, bool yswap,
+ Transform::orientation_flags rotation) {
size_t l = sourceCrop.left;
size_t r = sourceCrop.right;
@@ -186,13 +174,13 @@
case Transform::ROT_0:
break;
case Transform::ROT_90:
- m = mat4::rotate(rot90InRadians, vec3(0,0,1)) * m;
+ m = mat4::rotate(rot90InRadians, vec3(0, 0, 1)) * m;
break;
case Transform::ROT_180:
- m = mat4::rotate(rot90InRadians * 2.0f, vec3(0,0,1)) * m;
+ m = mat4::rotate(rot90InRadians * 2.0f, vec3(0, 0, 1)) * m;
break;
case Transform::ROT_270:
- m = mat4::rotate(rot90InRadians * 3.0f, vec3(0,0,1)) * m;
+ m = mat4::rotate(rot90InRadians * 3.0f, vec3(0, 0, 1)) * m;
break;
default:
break;
@@ -204,25 +192,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
-
+void GLES20RenderEngine::setupLayerBlending(bool premultipliedAlpha, 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 {
@@ -230,34 +210,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);
@@ -291,7 +243,6 @@
bool GLES20RenderEngine::usesWideColor() {
return mUseWideColor;
}
-#endif
void GLES20RenderEngine::setupLayerTexturing(const Texture& texture) {
GLuint target = texture.getTextureTarget();
@@ -329,9 +280,8 @@
glDisable(GL_BLEND);
}
-
-void GLES20RenderEngine::bindImageAsFramebuffer(EGLImageKHR image,
- uint32_t* texName, uint32_t* fbName, uint32_t* status) {
+void GLES20RenderEngine::bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName,
+ uint32_t* fbName, uint32_t* status) {
GLuint tname, name;
// turn our EGLImage into a texture
glGenTextures(1, &tname);
@@ -355,32 +305,23 @@
}
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);
}
void GLES20RenderEngine::drawMesh(const Mesh& mesh) {
-
if (mesh.getTexCoordsSize()) {
glEnableVertexAttribArray(Program::texCoords);
- glVertexAttribPointer(Program::texCoords,
- mesh.getTexCoordsSize(),
- GL_FLOAT, GL_FALSE,
- mesh.getByteStride(),
- mesh.getTexCoords());
+ glVertexAttribPointer(Program::texCoords, mesh.getTexCoordsSize(), GL_FLOAT, GL_FALSE,
+ mesh.getByteStride(), mesh.getTexCoords());
}
- glVertexAttribPointer(Program::position,
- mesh.getVertexSize(),
- GL_FLOAT, GL_FALSE,
- mesh.getByteStride(),
- mesh.getPositions());
+ glVertexAttribPointer(Program::position, mesh.getVertexSize(), GL_FLOAT, GL_FALSE,
+ mesh.getByteStride(), mesh.getPositions());
-#ifdef USE_HWC2
if (usesWideColor()) {
Description wideColorState = mState;
if (mDataSpace != HAL_DATASPACE_DISPLAY_P3) {
@@ -402,11 +343,6 @@
glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
}
-#else
- ProgramCache::getInstance().useProgram(mState);
-
- glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
-#endif
if (mesh.getTexCoordsSize()) {
glDisableVertexAttribArray(Program::texCoords);
@@ -415,13 +351,11 @@
void GLES20RenderEngine::dump(String8& result) {
RenderEngine::dump(result);
-#ifdef USE_HWC2
if (usesWideColor()) {
result.append("Wide-color: On\n");
} else {
result.append("Wide-color: Off\n");
}
-#endif
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index eaf94af..5ee9326 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-
#ifndef SF_GLES20RENDERENGINE_H_
#define SF_GLES20RENDERENGINE_H_
@@ -24,9 +23,9 @@
#include <GLES2/gl2.h>
#include <Transform.h>
-#include "RenderEngine.h"
-#include "ProgramCache.h"
#include "Description.h"
+#include "ProgramCache.h"
+#include "RenderEngine.h"
// ---------------------------------------------------------------------------
namespace android {
@@ -54,24 +53,20 @@
Description mState;
Vector<Group> mGroupStack;
- virtual void bindImageAsFramebuffer(EGLImageKHR image,
- uint32_t* texName, uint32_t* fbName, uint32_t* status);
+ virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName,
+ uint32_t* status);
virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName);
public:
GLES20RenderEngine(uint32_t featureFlags); // See RenderEngine::FeatureFlag
-
-protected:
virtual ~GLES20RenderEngine();
+protected:
virtual void dump(String8& result);
- 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;
+ virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh,
+ bool yswap, Transform::orientation_flags rotation);
+ virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
+ const half4& color) override;
// Color management related functions and state
void setColorMode(android_color_mode mode);
@@ -92,11 +87,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;
virtual void setupLayerTexturing(const Texture& texture);
diff --git a/services/surfaceflinger/RenderEngine/GLExtensions.cpp b/services/surfaceflinger/RenderEngine/GLExtensions.cpp
index 76bbcc1..7ffcc96 100644
--- a/services/surfaceflinger/RenderEngine/GLExtensions.cpp
+++ b/services/surfaceflinger/RenderEngine/GLExtensions.cpp
@@ -14,42 +14,35 @@
* limitations under the License.
*/
-#include <stdlib.h>
-#include <stdio.h>
#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
#include "GLExtensions.h"
namespace android {
// ---------------------------------------------------------------------------
-ANDROID_SINGLETON_STATIC_INSTANCE( GLExtensions )
+ANDROID_SINGLETON_STATIC_INSTANCE(GLExtensions)
-GLExtensions::GLExtensions()
- : mHaveFramebufferObject(false)
-{
-}
+GLExtensions::GLExtensions() : mHaveFramebufferObject(false) {}
-void GLExtensions::initWithGLStrings(
- GLubyte const* vendor,
- GLubyte const* renderer,
- GLubyte const* version,
- GLubyte const* extensions)
-{
- mVendor = (char const*)vendor;
- mRenderer = (char const*)renderer;
- mVersion = (char const*)version;
+void GLExtensions::initWithGLStrings(GLubyte const* vendor, GLubyte const* renderer,
+ GLubyte const* version, GLubyte const* extensions) {
+ mVendor = (char const*)vendor;
+ mRenderer = (char const*)renderer;
+ mVersion = (char const*)version;
mExtensions = (char const*)extensions;
char const* curr = (char const*)extensions;
char const* head = curr;
do {
head = strchr(curr, ' ');
- String8 s(curr, head ? head-curr : strlen(curr));
+ String8 s(curr, head ? head - curr : strlen(curr));
if (s.length()) {
mExtensionList.add(s);
}
- curr = head+1;
+ curr = head + 1;
} while (head);
if (hasExtension("GL_OES_framebuffer_object")) {
@@ -57,8 +50,7 @@
}
}
-bool GLExtensions::hasExtension(char const* extension) const
-{
+bool GLExtensions::hasExtension(char const* extension) const {
const String8 s(extension);
return mExtensionList.indexOf(s) >= 0;
}
diff --git a/services/surfaceflinger/RenderEngine/GLExtensions.h b/services/surfaceflinger/RenderEngine/GLExtensions.h
index d81ed2a..ee7b446 100644
--- a/services/surfaceflinger/RenderEngine/GLExtensions.h
+++ b/services/surfaceflinger/RenderEngine/GLExtensions.h
@@ -20,9 +20,9 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/String8.h>
-#include <utils/SortedVector.h>
#include <utils/Singleton.h>
+#include <utils/SortedVector.h>
+#include <utils/String8.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
@@ -32,8 +32,7 @@
namespace android {
// ---------------------------------------------------------------------------
-class GLExtensions : public Singleton<GLExtensions>
-{
+class GLExtensions : public Singleton<GLExtensions> {
friend class Singleton<GLExtensions>;
bool mHaveFramebufferObject : 1;
@@ -45,22 +44,16 @@
SortedVector<String8> mExtensionList;
GLExtensions(const GLExtensions&);
- GLExtensions& operator = (const GLExtensions&);
+ GLExtensions& operator=(const GLExtensions&);
protected:
GLExtensions();
public:
+ inline bool haveFramebufferObject() const { return mHaveFramebufferObject; }
- inline bool haveFramebufferObject() const {
- return mHaveFramebufferObject;
- }
-
- void initWithGLStrings(
- GLubyte const* vendor,
- GLubyte const* renderer,
- GLubyte const* version,
- GLubyte const* extensions);
+ void initWithGLStrings(GLubyte const* vendor, GLubyte const* renderer, GLubyte const* version,
+ GLubyte const* extensions);
char const* getVendor() const;
char const* getRenderer() const;
@@ -70,7 +63,6 @@
bool hasExtension(char const* extension) const;
};
-
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/RenderEngine/Mesh.cpp b/services/surfaceflinger/RenderEngine/Mesh.cpp
index ffd9be2..6a62b1d 100644
--- a/services/surfaceflinger/RenderEngine/Mesh.cpp
+++ b/services/surfaceflinger/RenderEngine/Mesh.cpp
@@ -21,9 +21,10 @@
namespace android {
Mesh::Mesh(Primitive primitive, size_t vertexCount, size_t vertexSize, size_t texCoordSize)
- : mVertexCount(vertexCount), mVertexSize(vertexSize), mTexCoordsSize(texCoordSize),
- mPrimitive(primitive)
-{
+ : mVertexCount(vertexCount),
+ mVertexSize(vertexSize),
+ mTexCoordsSize(texCoordSize),
+ mPrimitive(primitive) {
if (vertexCount == 0) {
mVertices = new float[1];
mVertices[0] = 0.0f;
@@ -37,8 +38,7 @@
// either vertexSize or texCoordSize, it must have overflowed. remainder
// will be equal to stride as long as stride * vertexCount doesn't overflow.
if ((stride < vertexSize) || (remainder != stride)) {
- ALOGE("Overflow in Mesh(..., %zu, %zu, %zu)", vertexCount, vertexSize,
- texCoordSize);
+ ALOGE("Overflow in Mesh(..., %zu, %zu, %zu)", vertexCount, vertexSize, texCoordSize);
mVertices = new float[1];
mVertices[0] = 0.0f;
mVertexCount = 0;
@@ -53,14 +53,13 @@
}
Mesh::~Mesh() {
- delete [] mVertices;
+ delete[] mVertices;
}
Mesh::Primitive Mesh::getPrimitive() const {
return mPrimitive;
}
-
float const* Mesh::getPositions() const {
return mVertices;
}
@@ -75,7 +74,6 @@
return mVertices + mVertexSize;
}
-
size_t Mesh::getVertexCount() const {
return mVertexCount;
}
@@ -89,7 +87,7 @@
}
size_t Mesh::getByteStride() const {
- return mStride*sizeof(float);
+ return mStride * sizeof(float);
}
size_t Mesh::getStride() const {
diff --git a/services/surfaceflinger/RenderEngine/Mesh.h b/services/surfaceflinger/RenderEngine/Mesh.h
index b6d42b0..d0a9ac0 100644
--- a/services/surfaceflinger/RenderEngine/Mesh.h
+++ b/services/surfaceflinger/RenderEngine/Mesh.h
@@ -24,9 +24,9 @@
class Mesh {
public:
enum Primitive {
- TRIANGLES = 0x0004, // GL_TRIANGLES
- TRIANGLE_STRIP = 0x0005, // GL_TRIANGLE_STRIP
- TRIANGLE_FAN = 0x0006 // GL_TRIANGLE_FAN
+ TRIANGLES = 0x0004, // GL_TRIANGLES
+ TRIANGLE_STRIP = 0x0005, // GL_TRIANGLE_STRIP
+ TRIANGLE_FAN = 0x0006 // GL_TRIANGLE_FAN
};
Mesh(Primitive primitive, size_t vertexCount, size_t vertexSize, size_t texCoordsSize = 0);
@@ -40,21 +40,24 @@
friend class Mesh;
float* mData;
size_t mStride;
- VertexArray(float* data, size_t stride) : mData(data), mStride(stride) { }
+ VertexArray(float* data, size_t stride) : mData(data), mStride(stride) {}
+
public:
- TYPE& operator[](size_t index) {
- return *reinterpret_cast<TYPE*>(&mData[index*mStride]);
- }
+ TYPE& operator[](size_t index) { return *reinterpret_cast<TYPE*>(&mData[index * mStride]); }
TYPE const& operator[](size_t index) const {
- return *reinterpret_cast<TYPE const*>(&mData[index*mStride]);
+ return *reinterpret_cast<TYPE const*>(&mData[index * mStride]);
}
};
template <typename TYPE>
- VertexArray<TYPE> getPositionArray() { return VertexArray<TYPE>(getPositions(), mStride); }
+ VertexArray<TYPE> getPositionArray() {
+ return VertexArray<TYPE>(getPositions(), mStride);
+ }
template <typename TYPE>
- VertexArray<TYPE> getTexCoordArray() { return VertexArray<TYPE>(getTexCoords(), mStride); }
+ VertexArray<TYPE> getTexCoordArray() {
+ return VertexArray<TYPE>(getTexCoords(), mStride);
+ }
Primitive getPrimitive() const;
@@ -81,8 +84,8 @@
private:
Mesh(const Mesh&);
- Mesh& operator = (const Mesh&);
- Mesh const& operator = (const Mesh&) const;
+ Mesh& operator=(const Mesh&);
+ Mesh const& operator=(const Mesh&) const;
float* getPositions();
float* getTexCoords();
@@ -94,6 +97,5 @@
Primitive mPrimitive;
};
-
} /* namespace android */
#endif /* SF_RENDER_ENGINE_MESH_H */
diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/Program.cpp
index 48a8da5..baf92eb 100644
--- a/services/surfaceflinger/RenderEngine/Program.cpp
+++ b/services/surfaceflinger/RenderEngine/Program.cpp
@@ -19,14 +19,15 @@
#include <log/log.h>
#include <utils/String8.h>
+#include <math/mat4.h>
+#include "Description.h"
#include "Program.h"
#include "ProgramCache.h"
-#include "Description.h"
namespace android {
Program::Program(const ProgramCache::Key& /*needs*/, const char* vertex, const char* fragment)
- : mInitialized(false) {
+ : mInitialized(false) {
GLuint vertexId = buildShader(vertex, GL_VERTEX_SHADER);
GLuint fragmentId = buildShader(fragment, GL_FRAGMENT_SHADER);
GLuint programId = glCreateProgram();
@@ -63,18 +64,15 @@
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);
- const GLfloat m[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 };
- glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, m);
+ glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, mat4().asArray());
glEnableVertexAttribArray(0);
}
}
-Program::~Program() {
-}
+Program::~Program() {}
bool Program::isValid() const {
return mInitialized;
@@ -119,12 +117,11 @@
char* src = new char[l];
glGetShaderSource(shader, l, NULL, src);
result.append(src);
- delete [] src;
+ delete[] src;
return result;
}
void Program::setUniforms(const Description& desc) {
-
// TODO: we should have a mechanism here to not always reset uniforms that
// didn't change for this program.
@@ -132,11 +129,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..6e57fdd 100644
--- a/services/surfaceflinger/RenderEngine/Program.h
+++ b/services/surfaceflinger/RenderEngine/Program.h
@@ -34,7 +34,7 @@
class Program {
public:
// known locations for position and texture coordinates
- enum { position=0, texCoords=1 };
+ enum { position = 0, texCoords = 1 };
Program(const ProgramCache::Key& needs, const char* vertex, const char* fragment);
~Program();
@@ -54,7 +54,6 @@
/* set-up uniforms from the description */
void setUniforms(const Description& desc);
-
private:
GLuint buildShader(const char* source, GLenum type);
String8& dumpShader(String8& result, GLenum type);
@@ -79,14 +78,10 @@
/* location of the sampler uniform */
GLint mSamplerLoc;
- /* location of the alpha plane uniform */
- GLint mAlphaPlaneLoc;
-
/* location of the color uniform */
GLint mColorLoc;
};
-
} /* namespace android */
#endif /* SF_RENDER_ENGINE_PROGRAM_H */
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index 06b2252..4f138dc 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -19,14 +19,13 @@
#include <utils/String8.h>
-#include "ProgramCache.h"
-#include "Program.h"
#include "Description.h"
+#include "Program.h"
+#include "ProgramCache.h"
namespace android {
// -----------------------------------------------------------------------------------------------
-
/*
* A simple formatter class to automatically add the endl and
* manage the indentation.
@@ -42,23 +41,22 @@
typedef Formatter& (*FormaterManipFunc)(Formatter&);
friend Formatter& indent(Formatter& f);
friend Formatter& dedent(Formatter& f);
+
public:
Formatter() : mIndent(0) {}
- String8 getString() const {
- return mString;
- }
+ String8 getString() const { return mString; }
- friend Formatter& operator << (Formatter& out, const char* in) {
- for (int i=0 ; i<out.mIndent ; i++) {
+ friend Formatter& operator<<(Formatter& out, const char* in) {
+ for (int i = 0; i < out.mIndent; i++) {
out.mString.append(" ");
}
out.mString.append(in);
out.mString.append("\n");
return out;
}
- friend inline Formatter& operator << (Formatter& out, const String8& in) {
- return operator << (out, in.string());
+ friend inline Formatter& operator<<(Formatter& out, const String8& in) {
+ return operator<<(out, in.string());
}
friend inline Formatter& operator<<(Formatter& to, FormaterManipFunc func) {
return (*func)(to);
@@ -83,13 +81,11 @@
primeCache();
}
-ProgramCache::~ProgramCache() {
-}
+ProgramCache::~ProgramCache() {}
void ProgramCache::primeCache() {
uint32_t shaderCount = 0;
- uint32_t keyMask = Key::BLEND_MASK | Key::OPACITY_MASK |
- Key::PLANE_ALPHA_MASK | Key::TEXTURE_MASK;
+ uint32_t keyMask = Key::BLEND_MASK | Key::OPACITY_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.
@@ -98,9 +94,7 @@
Key shaderKey;
shaderKey.set(keyMask, keyVal);
uint32_t tex = shaderKey.getTextureTarget();
- if (tex != Key::TEXTURE_OFF &&
- tex != Key::TEXTURE_EXT &&
- tex != Key::TEXTURE_2D) {
+ if (tex != Key::TEXTURE_OFF && tex != Key::TEXTURE_EXT && tex != Key::TEXTURE_2D) {
continue;
}
Program* program = mCache.valueFor(shaderKey);
@@ -118,34 +112,36 @@
ProgramCache::Key ProgramCache::computeKey(const Description& description) {
Key needs;
needs.set(Key::TEXTURE_MASK,
- !description.mTextureEnabled ? Key::TEXTURE_OFF :
- 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::BLEND_MASK,
- description.mPremultipliedAlpha ? Key::BLEND_PREMULT : Key::BLEND_NORMAL)
- .set(Key::OPACITY_MASK,
- description.mOpaque ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT)
- .set(Key::COLOR_MATRIX_MASK,
- description.mColorMatrixEnabled ? Key::COLOR_MATRIX_ON : Key::COLOR_MATRIX_OFF)
- .set(Key::WIDE_GAMUT_MASK,
- description.mIsWideGamut ? Key::WIDE_GAMUT_ON : Key::WIDE_GAMUT_OFF);
+ !description.mTextureEnabled
+ ? Key::TEXTURE_OFF
+ : description.mTexture.getTextureTarget() == GL_TEXTURE_EXTERNAL_OES
+ ? Key::TEXTURE_EXT
+ : description.mTexture.getTextureTarget() == GL_TEXTURE_2D
+ ? Key::TEXTURE_2D
+ : Key::TEXTURE_OFF)
+ .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,
+ description.mOpaque ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT)
+ .set(Key::COLOR_MATRIX_MASK,
+ description.mColorMatrixEnabled ? Key::COLOR_MATRIX_ON : Key::COLOR_MATRIX_OFF)
+ .set(Key::WIDE_GAMUT_MASK,
+ description.mIsWideGamut ? Key::WIDE_GAMUT_ON : Key::WIDE_GAMUT_OFF);
return needs;
}
String8 ProgramCache::generateVertexShader(const Key& needs) {
Formatter vs;
if (needs.isTexturing()) {
- vs << "attribute vec4 texCoords;"
- << "varying vec2 outTexCoords;";
+ vs << "attribute vec4 texCoords;"
+ << "varying vec2 outTexCoords;";
}
vs << "attribute vec4 position;"
<< "uniform mat4 projection;"
<< "uniform mat4 texture;"
- << "void main(void) {" << indent
- << "gl_Position = projection * position;";
+ << "void main(void) {" << indent << "gl_Position = projection * position;";
if (needs.isTexturing()) {
vs << "outTexCoords = (texture * texCoords).st;";
}
@@ -168,12 +164,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 +221,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;";
}
}
@@ -271,11 +268,10 @@
}
void ProgramCache::useProgram(const Description& description) {
-
// generate the key for the shader based on the description
Key needs(computeKey(description));
- // look-up the program in the cache
+ // look-up the program in the cache
Program* program = mCache.valueFor(needs);
if (program == NULL) {
// we didn't find our program, so generate one...
@@ -284,7 +280,7 @@
mCache.add(needs, program);
time += systemTime();
- //ALOGD(">>> generated new program: needs=%08X, time=%u ms (%d programs)",
+ // ALOGD(">>> generated new program: needs=%08X, time=%u ms (%d programs)",
// needs.mNeeds, uint32_t(ns2ms(time)), mCache.size());
}
@@ -295,5 +291,4 @@
}
}
-
} /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.h b/services/surfaceflinger/RenderEngine/ProgramCache.h
index 5b0fbcd..54d3722 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.h
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.h
@@ -19,8 +19,8 @@
#include <GLES2/gl2.h>
-#include <utils/Singleton.h>
#include <utils/KeyedVector.h>
+#include <utils/Singleton.h>
#include <utils/TypeHelpers.h>
#include "Description.h"
@@ -47,63 +47,50 @@
friend class ProgramCache;
typedef uint32_t key_t;
key_t mKey;
+
public:
enum {
- BLEND_PREMULT = 0x00000001,
- BLEND_NORMAL = 0x00000000,
- BLEND_MASK = 0x00000001,
+ BLEND_PREMULT = 0x00000001,
+ BLEND_NORMAL = 0x00000000,
+ BLEND_MASK = 0x00000001,
- OPACITY_OPAQUE = 0x00000002,
- OPACITY_TRANSLUCENT = 0x00000000,
- OPACITY_MASK = 0x00000002,
+ OPACITY_OPAQUE = 0x00000002,
+ 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,
- TEXTURE_2D = 0x00000010,
- TEXTURE_MASK = 0x00000018,
+ TEXTURE_OFF = 0x00000000,
+ TEXTURE_EXT = 0x00000008,
+ TEXTURE_2D = 0x00000010,
+ TEXTURE_MASK = 0x00000018,
- COLOR_MATRIX_OFF = 0x00000000,
- COLOR_MATRIX_ON = 0x00000020,
- COLOR_MATRIX_MASK = 0x00000020,
+ COLOR_MATRIX_OFF = 0x00000000,
+ COLOR_MATRIX_ON = 0x00000020,
+ COLOR_MATRIX_MASK = 0x00000020,
- WIDE_GAMUT_OFF = 0x00000000,
- WIDE_GAMUT_ON = 0x00000040,
- WIDE_GAMUT_MASK = 0x00000040,
+ WIDE_GAMUT_OFF = 0x00000000,
+ WIDE_GAMUT_ON = 0x00000040,
+ WIDE_GAMUT_MASK = 0x00000040,
};
- inline Key() : mKey(0) { }
- inline Key(const Key& rhs) : mKey(rhs.mKey) { }
+ inline Key() : mKey(0) {}
+ inline Key(const Key& rhs) : mKey(rhs.mKey) {}
inline Key& set(key_t mask, key_t value) {
mKey = (mKey & ~mask) | value;
return *this;
}
- inline bool isTexturing() const {
- return (mKey & TEXTURE_MASK) != TEXTURE_OFF;
- }
- inline int getTextureTarget() const {
- return (mKey & TEXTURE_MASK);
- }
- inline bool isPremultiplied() const {
- return (mKey & BLEND_MASK) == BLEND_PREMULT;
- }
- 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 hasColorMatrix() const {
- return (mKey & COLOR_MATRIX_MASK) == COLOR_MATRIX_ON;
- }
- inline bool isWideGamut() const {
- return (mKey & WIDE_GAMUT_MASK) == WIDE_GAMUT_ON;
- }
+ inline bool isTexturing() const { return (mKey & TEXTURE_MASK) != TEXTURE_OFF; }
+ inline int getTextureTarget() const { return (mKey & TEXTURE_MASK); }
+ inline bool isPremultiplied() const { return (mKey & BLEND_MASK) == BLEND_PREMULT; }
+ inline bool isOpaque() const { return (mKey & OPACITY_MASK) == OPACITY_OPAQUE; }
+ inline bool hasAlpha() const { return (mKey & ALPHA_MASK) == ALPHA_LT_ONE; }
+ inline bool hasColorMatrix() const { return (mKey & COLOR_MATRIX_MASK) == COLOR_MATRIX_ON; }
+ inline bool isWideGamut() const { return (mKey & WIDE_GAMUT_MASK) == WIDE_GAMUT_ON; }
// this is the definition of a friend function -- not a method of class Needs
friend inline int strictly_order_type(const Key& lhs, const Key& rhs) {
@@ -135,7 +122,6 @@
DefaultKeyedVector<Key, Program*> mCache;
};
-
ANDROID_BASIC_TYPES_TRAITS(ProgramCache::Key)
} /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 56e9ac0..883ae26 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -18,13 +18,13 @@
#include <ui/Rect.h>
#include <ui/Region.h>
-#include "RenderEngine.h"
#include "GLES20RenderEngine.h"
#include "GLExtensions.h"
#include "Mesh.h"
+#include "RenderEngine.h"
-#include <vector>
#include <SurfaceFlinger.h>
+#include <vector>
extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
@@ -33,21 +33,25 @@
// ---------------------------------------------------------------------------
static bool findExtension(const char* exts, const char* name) {
- if (!exts)
- return false;
+ if (!exts) return false;
size_t len = strlen(name);
const char* pos = exts;
while ((pos = strstr(pos, name)) != NULL) {
- if (pos[len] == '\0' || pos[len] == ' ')
- return true;
+ if (pos[len] == '\0' || pos[len] == ' ') return true;
pos += len;
}
return false;
}
-RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat, uint32_t featureFlags) {
+std::unique_ptr<RenderEngine> RenderEngine::create(int hwcFormat, uint32_t featureFlags) {
+ // initialize EGL for the default display
+ EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (!eglInitialize(display, NULL, NULL)) {
+ LOG_ALWAYS_FATAL("failed to initialize EGL");
+ }
+
// EGL_ANDROIDX_no_config_context is an experimental extension with no
// written specification. It will be replaced by something more formal.
// SurfaceFlinger is using it to allow a single EGLContext to render to
@@ -70,8 +74,7 @@
EGLint renderableType = 0;
if (config == EGL_NO_CONFIG) {
renderableType = EGL_OPENGL_ES2_BIT;
- } else if (!eglGetConfigAttrib(display, config,
- EGL_RENDERABLE_TYPE, &renderableType)) {
+ } else if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) {
LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE");
}
EGLint contextClientVersion = 0;
@@ -96,12 +99,10 @@
contextAttributes.push_back(EGL_NONE);
contextAttributes.push_back(EGL_NONE);
- EGLContext ctxt = eglCreateContext(display, config, NULL,
- contextAttributes.data());
+ EGLContext ctxt = eglCreateContext(display, config, NULL, contextAttributes.data());
// if can't create a GL context, we can only abort.
- LOG_ALWAYS_FATAL_IF(ctxt==EGL_NO_CONTEXT, "EGLContext creation failed");
-
+ LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed");
// now figure out what version of GL did we actually get
// NOTE: a dummy surface is not needed if KHR_create_context is supported
@@ -110,35 +111,32 @@
if (dummyConfig == EGL_NO_CONFIG) {
dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
}
- EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE };
+ EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE};
EGLSurface dummy = eglCreatePbufferSurface(display, dummyConfig, attribs);
- LOG_ALWAYS_FATAL_IF(dummy==EGL_NO_SURFACE, "can't create dummy pbuffer");
+ LOG_ALWAYS_FATAL_IF(dummy == EGL_NO_SURFACE, "can't create dummy pbuffer");
EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt);
LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current");
GLExtensions& extensions(GLExtensions::getInstance());
- extensions.initWithGLStrings(
- glGetString(GL_VENDOR),
- glGetString(GL_RENDERER),
- glGetString(GL_VERSION),
- glGetString(GL_EXTENSIONS));
+ extensions.initWithGLStrings(glGetString(GL_VENDOR), glGetString(GL_RENDERER),
+ glGetString(GL_VERSION), glGetString(GL_EXTENSIONS));
- GlesVersion version = parseGlesVersion( extensions.getVersion() );
+ GlesVersion version = parseGlesVersion(extensions.getVersion());
// initialize the renderer while GL is current
- RenderEngine* engine = NULL;
+ std::unique_ptr<RenderEngine> engine;
switch (version) {
- case GLES_VERSION_1_0:
- case GLES_VERSION_1_1:
- LOG_ALWAYS_FATAL("SurfaceFlinger requires OpenGL ES 2.0 minimum to run.");
- break;
- case GLES_VERSION_2_0:
- case GLES_VERSION_3_0:
- engine = new GLES20RenderEngine(featureFlags);
- break;
+ case GLES_VERSION_1_0:
+ case GLES_VERSION_1_1:
+ LOG_ALWAYS_FATAL("SurfaceFlinger requires OpenGL ES 2.0 minimum to run.");
+ break;
+ case GLES_VERSION_2_0:
+ case GLES_VERSION_3_0:
+ engine = std::make_unique<GLES20RenderEngine>(featureFlags);
+ break;
}
- engine->setEGLHandles(config, ctxt);
+ engine->setEGLHandles(display, config, ctxt);
ALOGI("OpenGL ES informations:");
ALOGI("vendor : %s", extensions.getVendor());
@@ -154,31 +152,50 @@
return engine;
}
-RenderEngine::RenderEngine() : mEGLConfig(NULL), mEGLContext(EGL_NO_CONTEXT) {
-}
+RenderEngine::RenderEngine()
+ : mEGLDisplay(EGL_NO_DISPLAY), mEGLConfig(NULL), mEGLContext(EGL_NO_CONTEXT) {}
RenderEngine::~RenderEngine() {
+ eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglTerminate(mEGLDisplay);
}
-void RenderEngine::setEGLHandles(EGLConfig config, EGLContext ctxt) {
+void RenderEngine::setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt) {
+ mEGLDisplay = display;
mEGLConfig = config;
mEGLContext = ctxt;
}
-EGLContext RenderEngine::getEGLConfig() const {
+EGLDisplay RenderEngine::getEGLDisplay() const {
+ return mEGLDisplay;
+}
+
+EGLConfig RenderEngine::getEGLConfig() const {
return mEGLConfig;
}
-EGLContext RenderEngine::getEGLContext() const {
- return mEGLContext;
+bool RenderEngine::setCurrentSurface(const RE::Surface& surface) {
+ bool success = true;
+ EGLSurface eglSurface = surface.getEGLSurface();
+ if (eglSurface != eglGetCurrentSurface(EGL_DRAW)) {
+ success = eglMakeCurrent(mEGLDisplay, eglSurface, eglSurface, mEGLContext) == EGL_TRUE;
+ if (success && surface.getAsync()) {
+ eglSwapInterval(mEGLDisplay, 0);
+ }
+ }
+
+ return success;
+}
+
+void RenderEngine::resetCurrentSurface() {
+ eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
void RenderEngine::checkErrors() const {
do {
// there could be more than one error flag
GLenum error = glGetError();
- if (error == GL_NO_ERROR)
- break;
+ if (error == GL_NO_ERROR) break;
ALOGE("GL error 0x%04x", int(error));
} while (true);
}
@@ -201,32 +218,74 @@
return GLES_VERSION_1_0;
}
-void RenderEngine::fillRegionWithColor(const Region& region, uint32_t height,
- float red, float green, float blue, float alpha) {
+void RenderEngine::fillRegionWithColor(const Region& region, uint32_t height, float red,
+ float green, float blue, float alpha) {
size_t c;
Rect const* r = region.getArray(&c);
- Mesh mesh(Mesh::TRIANGLES, c*6, 2);
+ Mesh mesh(Mesh::TRIANGLES, c * 6, 2);
Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
- for (size_t i=0 ; i<c ; i++, r++) {
- position[i*6 + 0].x = r->left;
- position[i*6 + 0].y = height - r->top;
- position[i*6 + 1].x = r->left;
- position[i*6 + 1].y = height - r->bottom;
- position[i*6 + 2].x = r->right;
- position[i*6 + 2].y = height - r->bottom;
- position[i*6 + 3].x = r->left;
- position[i*6 + 3].y = height - r->top;
- position[i*6 + 4].x = r->right;
- position[i*6 + 4].y = height - r->bottom;
- position[i*6 + 5].x = r->right;
- position[i*6 + 5].y = height - r->top;
+ for (size_t i = 0; i < c; i++, r++) {
+ position[i * 6 + 0].x = r->left;
+ position[i * 6 + 0].y = height - r->top;
+ position[i * 6 + 1].x = r->left;
+ position[i * 6 + 1].y = height - r->bottom;
+ position[i * 6 + 2].x = r->right;
+ position[i * 6 + 2].y = height - r->bottom;
+ position[i * 6 + 3].x = r->left;
+ position[i * 6 + 3].y = height - r->top;
+ position[i * 6 + 4].x = r->right;
+ position[i * 6 + 4].y = height - r->bottom;
+ position[i * 6 + 5].x = r->right;
+ position[i * 6 + 5].y = height - r->top;
}
setupFillWithColor(red, green, blue, alpha);
drawMesh(mesh);
}
-void RenderEngine::flush() {
- glFlush();
+int RenderEngine::flush(bool wait) {
+ // 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
+ // wait on it directly.
+ EGLSyncKHR sync;
+ if (!wait) {
+ EGLint syncFd = EGL_NO_NATIVE_FENCE_FD_ANDROID;
+
+ sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
+ if (sync != EGL_NO_SYNC_KHR) {
+ // native fence fd will not be populated until flush() is done.
+ glFlush();
+
+ // get the sync fd
+ syncFd = eglDupNativeFenceFDANDROID(mEGLDisplay, sync);
+ if (syncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+ ALOGW("failed to dup sync khr object");
+ }
+
+ eglDestroySyncKHR(mEGLDisplay, sync);
+ }
+
+ if (syncFd != EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+ return syncFd;
+ }
+ }
+
+ // fallback or explicit wait
+ sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL);
+ if (sync != EGL_NO_SYNC_KHR) {
+ EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
+ 2000000000 /*2 sec*/);
+ EGLint eglErr = eglGetError();
+ if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+ ALOGW("fence wait timed out");
+ } else {
+ ALOGW_IF(eglErr != EGL_SUCCESS, "error waiting on EGL fence: %#x", eglErr);
+ }
+ eglDestroySyncKHR(mEGLDisplay, sync);
+ } else {
+ ALOGW("error creating EGL fence: %#x", eglGetError());
+ }
+
+ return -1;
}
void RenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
@@ -234,8 +293,7 @@
glClear(GL_COLOR_BUFFER_BIT);
}
-void RenderEngine::setScissor(
- uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) {
+void RenderEngine::setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) {
glScissor(left, bottom, right, top);
glEnable(GL_SCISSOR_TEST);
}
@@ -257,38 +315,52 @@
}
void RenderEngine::dump(String8& result) {
+ result.appendFormat("EGL implementation : %s\n",
+ eglQueryStringImplementationANDROID(mEGLDisplay, EGL_VERSION));
+ result.appendFormat("%s\n", eglQueryStringImplementationANDROID(mEGLDisplay, EGL_EXTENSIONS));
+
const GLExtensions& extensions(GLExtensions::getInstance());
- result.appendFormat("GLES: %s, %s, %s\n",
- extensions.getVendor(),
- extensions.getRenderer(),
- extensions.getVersion());
+ result.appendFormat("GLES: %s, %s, %s\n", extensions.getVendor(), extensions.getRenderer(),
+ extensions.getVersion());
result.appendFormat("%s\n", extensions.getExtension());
}
// ---------------------------------------------------------------------------
-RenderEngine::BindImageAsFramebuffer::BindImageAsFramebuffer(
- RenderEngine& engine, EGLImageKHR image) : mEngine(engine)
-{
- mEngine.bindImageAsFramebuffer(image, &mTexName, &mFbName, &mStatus);
+RenderEngine::BindNativeBufferAsFramebuffer::BindNativeBufferAsFramebuffer(
+ RenderEngine& engine, ANativeWindowBuffer* buffer)
+ : mEngine(engine) {
+ mImage = eglCreateImageKHR(mEngine.mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+ buffer, NULL);
+ if (mImage == EGL_NO_IMAGE_KHR) {
+ mStatus = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ return;
+ }
- ALOGE_IF(mStatus != GL_FRAMEBUFFER_COMPLETE_OES,
- "glCheckFramebufferStatusOES error %d", mStatus);
+ mEngine.bindImageAsFramebuffer(mImage, &mTexName, &mFbName, &mStatus);
+
+ ALOGE_IF(mStatus != GL_FRAMEBUFFER_COMPLETE_OES, "glCheckFramebufferStatusOES error %d",
+ mStatus);
}
-RenderEngine::BindImageAsFramebuffer::~BindImageAsFramebuffer() {
+RenderEngine::BindNativeBufferAsFramebuffer::~BindNativeBufferAsFramebuffer() {
+ if (mImage == EGL_NO_IMAGE_KHR) {
+ return;
+ }
+
// back to main framebuffer
mEngine.unbindFramebuffer(mTexName, mFbName);
+ eglDestroyImageKHR(mEngine.mEGLDisplay, mImage);
}
-status_t RenderEngine::BindImageAsFramebuffer::getStatus() const {
+status_t RenderEngine::BindNativeBufferAsFramebuffer::getStatus() const {
return mStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
}
// ---------------------------------------------------------------------------
-static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs,
- EGLint attribute, EGLint wanted, EGLConfig* outConfig) {
+static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute,
+ EGLint wanted, EGLConfig* outConfig) {
EGLint numConfigs = -1, n = 0;
eglGetConfigs(dpy, NULL, 0, &numConfigs);
EGLConfig* const configs = new EGLConfig[numConfigs];
@@ -296,23 +368,23 @@
if (n) {
if (attribute != EGL_NONE) {
- for (int i=0 ; i<n ; i++) {
+ for (int i = 0; i < n; i++) {
EGLint value = 0;
eglGetConfigAttrib(dpy, configs[i], attribute, &value);
if (wanted == value) {
*outConfig = configs[i];
- delete [] configs;
+ delete[] configs;
return NO_ERROR;
}
}
} else {
// just pick the first one
*outConfig = configs[0];
- delete [] configs;
+ delete[] configs;
return NO_ERROR;
}
}
- delete [] configs;
+ delete[] configs;
return NAME_NOT_FOUND;
}
@@ -322,10 +394,10 @@
friend class Adder;
KeyedVector<Attribute, EGLint> mList;
struct Attribute {
- Attribute() : v(0) {};
- explicit Attribute(EGLint v) : v(v) { }
+ Attribute() : v(0){};
+ explicit Attribute(EGLint v) : v(v) {}
EGLint v;
- bool operator < (const Attribute& other) const {
+ bool operator<(const Attribute& other) const {
// this places EGL_NONE at the end
EGLint lhs(v);
EGLint rhs(other.v);
@@ -338,39 +410,32 @@
friend class EGLAttributeVector;
EGLAttributeVector& v;
EGLint attribute;
- Adder(EGLAttributeVector& v, EGLint attribute)
- : v(v), attribute(attribute) {
- }
+ Adder(EGLAttributeVector& v, EGLint attribute) : v(v), attribute(attribute) {}
+
public:
- void operator = (EGLint value) {
+ void operator=(EGLint value) {
if (attribute != EGL_NONE) {
v.mList.add(Attribute(attribute), value);
}
}
- operator EGLint () const { return v.mList[attribute]; }
+ operator EGLint() const { return v.mList[attribute]; }
};
+
public:
- EGLAttributeVector() {
- mList.add(Attribute(EGL_NONE), EGL_NONE);
- }
+ EGLAttributeVector() { mList.add(Attribute(EGL_NONE), EGL_NONE); }
void remove(EGLint attribute) {
if (attribute != EGL_NONE) {
mList.removeItem(Attribute(attribute));
}
}
- Adder operator [] (EGLint attribute) {
- return Adder(*this, attribute);
- }
- EGLint operator [] (EGLint attribute) const {
- return mList[attribute];
- }
+ Adder operator[](EGLint attribute) { return Adder(*this, attribute); }
+ EGLint operator[](EGLint attribute) const { return mList[attribute]; }
// cast-operator to (EGLint const*)
- operator EGLint const* () const { return &mList.keyAt(0).v; }
+ operator EGLint const*() const { return &mList.keyAt(0).v; }
};
-
-static status_t selectEGLConfig(EGLDisplay display, EGLint format,
- EGLint renderableType, EGLConfig* config) {
+static status_t selectEGLConfig(EGLDisplay display, EGLint format, EGLint renderableType,
+ EGLConfig* config) {
// select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
// it is to be used with WIFI displays
status_t err;
@@ -379,24 +444,23 @@
EGLAttributeVector attribs;
if (renderableType) {
- attribs[EGL_RENDERABLE_TYPE] = renderableType;
- attribs[EGL_RECORDABLE_ANDROID] = EGL_TRUE;
- attribs[EGL_SURFACE_TYPE] = EGL_WINDOW_BIT|EGL_PBUFFER_BIT;
+ attribs[EGL_RENDERABLE_TYPE] = renderableType;
+ attribs[EGL_RECORDABLE_ANDROID] = EGL_TRUE;
+ attribs[EGL_SURFACE_TYPE] = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
attribs[EGL_FRAMEBUFFER_TARGET_ANDROID] = EGL_TRUE;
- attribs[EGL_RED_SIZE] = 8;
- attribs[EGL_GREEN_SIZE] = 8;
- attribs[EGL_BLUE_SIZE] = 8;
- attribs[EGL_ALPHA_SIZE] = 8;
- wantedAttribute = EGL_NONE;
- wantedAttributeValue = EGL_NONE;
+ attribs[EGL_RED_SIZE] = 8;
+ attribs[EGL_GREEN_SIZE] = 8;
+ attribs[EGL_BLUE_SIZE] = 8;
+ attribs[EGL_ALPHA_SIZE] = 8;
+ wantedAttribute = EGL_NONE;
+ wantedAttributeValue = EGL_NONE;
} else {
// if no renderable type specified, fallback to a simplified query
- wantedAttribute = EGL_NATIVE_VISUAL_ID;
- wantedAttributeValue = format;
+ wantedAttribute = EGL_NATIVE_VISUAL_ID;
+ wantedAttributeValue = format;
}
- err = selectConfigForAttribute(display, attribs,
- wantedAttribute, wantedAttributeValue, config);
+ err = selectConfigForAttribute(display, attribs, wantedAttribute, wantedAttributeValue, config);
if (err == NO_ERROR) {
EGLint caveat;
if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat))
@@ -406,8 +470,7 @@
return err;
}
-EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format,
- bool logConfig) {
+EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format, bool logConfig) {
status_t err;
EGLConfig config;
@@ -430,23 +493,22 @@
if (logConfig) {
// print some debugging info
- EGLint r,g,b,a;
- eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r);
+ EGLint r, g, b, a;
+ eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r);
eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
- eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b);
+ eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b);
eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
ALOGI("EGL information:");
ALOGI("vendor : %s", eglQueryString(display, EGL_VENDOR));
ALOGI("version : %s", eglQueryString(display, EGL_VERSION));
ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
- ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
+ ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS) ?: "Not Supported");
ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
}
return config;
}
-
void RenderEngine::primeCache() const {
// Getting the ProgramCache instance causes it to prime its shader cache,
// which is performed in its constructor
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 9544579..3847347 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -14,20 +14,24 @@
* limitations under the License.
*/
-
#ifndef SF_RENDERENGINE_H_
#define SF_RENDERENGINE_H_
+#include <memory>
+
#include <stdint.h>
#include <sys/types.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include <math/mat4.h>
#include <Transform.h>
+#include <gui/SurfaceControl.h>
+#include <math/mat4.h>
#define EGL_NO_CONFIG ((EGLConfig)0)
+struct ANativeWindowBuffer;
+
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
@@ -38,31 +42,38 @@
class Mesh;
class Texture;
+namespace RE {
+class Surface;
+}
+
class RenderEngine {
enum GlesVersion {
- GLES_VERSION_1_0 = 0x10000,
- GLES_VERSION_1_1 = 0x10001,
- GLES_VERSION_2_0 = 0x20000,
- GLES_VERSION_3_0 = 0x30000,
+ GLES_VERSION_1_0 = 0x10000,
+ GLES_VERSION_1_1 = 0x10001,
+ GLES_VERSION_2_0 = 0x20000,
+ GLES_VERSION_3_0 = 0x30000,
};
static GlesVersion parseGlesVersion(const char* str);
+ EGLDisplay mEGLDisplay;
EGLConfig mEGLConfig;
EGLContext mEGLContext;
- void setEGLHandles(EGLConfig config, EGLContext ctxt);
+ void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt);
- virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, uint32_t* status) = 0;
+ virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName,
+ uint32_t* status) = 0;
virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0;
protected:
RenderEngine();
- virtual ~RenderEngine() = 0;
public:
+ virtual ~RenderEngine() = 0;
+
enum FeatureFlag {
WIDE_COLOR_SUPPORT = 1 << 0 // Platform has a wide color display
};
- static RenderEngine* create(EGLDisplay display, int hwcFormat, uint32_t featureFlags);
+ static std::unique_ptr<RenderEngine> create(int hwcFormat, uint32_t featureFlags);
static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
@@ -72,10 +83,11 @@
virtual void dump(String8& result);
// helpers
- void flush();
+ // flush returns -1 or a valid native fence fd owned by the caller
+ int flush(bool wait);
void clearWithColor(float red, float green, float blue, float alpha);
- void fillRegionWithColor(const Region& region, uint32_t height,
- float red, float green, float blue, float alpha);
+ void fillRegionWithColor(const Region& region, uint32_t height, float red, float green,
+ float blue, float alpha);
// common to all GL versions
void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top);
@@ -84,38 +96,36 @@
void deleteTextures(size_t count, uint32_t const* names);
void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels);
- class BindImageAsFramebuffer {
+ class BindNativeBufferAsFramebuffer {
RenderEngine& mEngine;
+ EGLImageKHR mImage;
uint32_t mTexName, mFbName;
uint32_t mStatus;
+
public:
- BindImageAsFramebuffer(RenderEngine& engine, EGLImageKHR image);
- ~BindImageAsFramebuffer();
+ BindNativeBufferAsFramebuffer(RenderEngine& engine, ANativeWindowBuffer* buffer);
+ ~BindNativeBufferAsFramebuffer();
int getStatus() const;
};
+ bool setCurrentSurface(const RE::Surface& surface);
+ void resetCurrentSurface();
+
// set-up
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;
-#ifdef USE_HWC2
- virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, float alpha) = 0;
- virtual void setupDimLayerBlending(float alpha) = 0;
+ 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;
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;
virtual void setupFillWithColor(float r, float g, float b, float a) = 0;
- virtual mat4 setupColorTransform(const mat4& /* colorTransform */) {
- return mat4();
- }
+ virtual mat4 setupColorTransform(const mat4& /* colorTransform */) { return mat4(); }
virtual void disableTexturing() = 0;
virtual void disableBlending() = 0;
@@ -127,8 +137,9 @@
virtual size_t getMaxTextureSize() const = 0;
virtual size_t getMaxViewportDims() const = 0;
+ // internal to RenderEngine
+ EGLDisplay getEGLDisplay() const;
EGLConfig getEGLConfig() const;
- EGLContext getEGLContext() const;
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/Surface.cpp b/services/surfaceflinger/RenderEngine/Surface.cpp
new file mode 100644
index 0000000..a23d9fb
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/Surface.cpp
@@ -0,0 +1,106 @@
+/*
+ * 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 "Surface.h"
+
+#include "RenderEngine.h"
+
+#include <log/log.h>
+
+namespace android {
+namespace RE {
+
+Surface::Surface(const RenderEngine& engine)
+ : mEGLDisplay(engine.getEGLDisplay()), mEGLConfig(engine.getEGLConfig()) {
+ // RE does not assume any config when EGL_KHR_no_config_context is supported
+ if (mEGLConfig == EGL_NO_CONFIG_KHR) {
+ mEGLConfig = RenderEngine::chooseEglConfig(mEGLDisplay, PIXEL_FORMAT_RGBA_8888, false);
+ }
+}
+
+Surface::~Surface() {
+ setNativeWindow(nullptr);
+}
+
+void Surface::setNativeWindow(ANativeWindow* window) {
+ if (mEGLSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(mEGLDisplay, mEGLSurface);
+ mEGLSurface = EGL_NO_SURFACE;
+ }
+
+ mWindow = window;
+ if (mWindow) {
+ mEGLSurface = eglCreateWindowSurface(mEGLDisplay, mEGLConfig, mWindow, nullptr);
+ }
+}
+
+void Surface::swapBuffers() const {
+ if (!eglSwapBuffers(mEGLDisplay, mEGLSurface)) {
+ EGLint error = eglGetError();
+
+ const char format[] = "eglSwapBuffers(%p, %p) failed with 0x%08x";
+ if (mCritical || error == EGL_CONTEXT_LOST) {
+ LOG_ALWAYS_FATAL(format, mEGLDisplay, mEGLSurface, error);
+ } else {
+ ALOGE(format, mEGLDisplay, mEGLSurface, error);
+ }
+ }
+}
+
+EGLint Surface::queryConfig(EGLint attrib) const {
+ EGLint value;
+ if (!eglGetConfigAttrib(mEGLConfig, mEGLConfig, attrib, &value)) {
+ value = 0;
+ }
+
+ return value;
+}
+
+EGLint Surface::querySurface(EGLint attrib) const {
+ EGLint value;
+ if (!eglQuerySurface(mEGLDisplay, mEGLSurface, attrib, &value)) {
+ value = 0;
+ }
+
+ return value;
+}
+
+int32_t Surface::queryRedSize() const {
+ return queryConfig(EGL_RED_SIZE);
+}
+
+int32_t Surface::queryGreenSize() const {
+ return queryConfig(EGL_GREEN_SIZE);
+}
+
+int32_t Surface::queryBlueSize() const {
+ return queryConfig(EGL_BLUE_SIZE);
+}
+
+int32_t Surface::queryAlphaSize() const {
+ return queryConfig(EGL_ALPHA_SIZE);
+}
+
+int32_t Surface::queryWidth() const {
+ return querySurface(EGL_WIDTH);
+}
+
+int32_t Surface::queryHeight() const {
+ return querySurface(EGL_HEIGHT);
+}
+
+} // namespace RE
+} // namespace android
diff --git a/services/surfaceflinger/RenderEngine/Surface.h b/services/surfaceflinger/RenderEngine/Surface.h
new file mode 100644
index 0000000..8b10be9
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/Surface.h
@@ -0,0 +1,73 @@
+/*
+ * 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 <cstdint>
+
+#include <EGL/egl.h>
+
+struct ANativeWindow;
+
+namespace android {
+
+class RenderEngine;
+
+namespace RE {
+
+class Surface {
+public:
+ Surface(const RenderEngine& engine);
+ ~Surface();
+
+ Surface(const Surface&) = delete;
+ Surface& operator=(const Surface&) = delete;
+
+ void setCritical(bool enable) { mCritical = enable; }
+ void setAsync(bool enable) { mAsync = enable; }
+
+ void setNativeWindow(ANativeWindow* window);
+ void swapBuffers() const;
+
+ int32_t queryRedSize() const;
+ int32_t queryGreenSize() const;
+ int32_t queryBlueSize() const;
+ int32_t queryAlphaSize() const;
+
+ int32_t queryWidth() const;
+ int32_t queryHeight() const;
+
+private:
+ EGLint queryConfig(EGLint attrib) const;
+ EGLint querySurface(EGLint attrib) const;
+
+ // methods internal to RenderEngine
+ friend class android::RenderEngine;
+ bool getAsync() const { return mAsync; }
+ EGLSurface getEGLSurface() const { return mEGLSurface; }
+
+ EGLDisplay mEGLDisplay;
+ EGLConfig mEGLConfig;
+
+ bool mCritical = false;
+ bool mAsync = false;
+
+ ANativeWindow* mWindow = nullptr;
+ EGLSurface mEGLSurface = EGL_NO_SURFACE;
+};
+
+} // namespace RE
+} // namespace android
diff --git a/services/surfaceflinger/RenderEngine/Texture.cpp b/services/surfaceflinger/RenderEngine/Texture.cpp
index 8875b6d..351430f 100644
--- a/services/surfaceflinger/RenderEngine/Texture.cpp
+++ b/services/surfaceflinger/RenderEngine/Texture.cpp
@@ -20,24 +20,22 @@
namespace android {
-Texture::Texture() :
- mTextureName(0), mTextureTarget(TEXTURE_2D),
- mWidth(0), mHeight(0), mFiltering(false) {
-}
+Texture::Texture()
+ : mTextureName(0), mTextureTarget(TEXTURE_2D), mWidth(0), mHeight(0), mFiltering(false) {}
-Texture::Texture(Target textureTarget, uint32_t textureName) :
- mTextureName(textureName), mTextureTarget(textureTarget),
- mWidth(0), mHeight(0), mFiltering(false) {
-}
+Texture::Texture(Target textureTarget, uint32_t textureName)
+ : mTextureName(textureName),
+ mTextureTarget(textureTarget),
+ mWidth(0),
+ mHeight(0),
+ mFiltering(false) {}
void Texture::init(Target textureTarget, uint32_t textureName) {
mTextureName = textureName;
mTextureTarget = textureTarget;
}
-Texture::~Texture() {
-}
-
+Texture::~Texture() {}
void Texture::setMatrix(float const* matrix) {
mTextureMatrix = mat4(matrix);
diff --git a/services/surfaceflinger/RenderEngine/Texture.h b/services/surfaceflinger/RenderEngine/Texture.h
index a07e0c3..56b6b31 100644
--- a/services/surfaceflinger/RenderEngine/Texture.h
+++ b/services/surfaceflinger/RenderEngine/Texture.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include <stdint.h>
#include <math/mat4.h>
+#include <stdint.h>
#ifndef SF_RENDER_ENGINE_TEXTURE_H
#define SF_RENDER_ENGINE_TEXTURE_H
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7a8737f..142892e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -28,8 +28,6 @@
#include <stdatomic.h>
#include <optional>
-#include <EGL/egl.h>
-
#include <cutils/properties.h>
#include <log/log.h>
@@ -72,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"
@@ -90,6 +89,8 @@
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <configstore/Utils.h>
+#include <layerproto/LayerProtoParser.h>
+
#define DISPLAY_COUNT 1
/*
@@ -98,8 +99,6 @@
*/
#define DEBUG_SCREENSHOTS false
-extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
-
namespace android {
using namespace android::hardware::configstore;
@@ -282,9 +281,6 @@
SurfaceFlinger::~SurfaceFlinger()
{
- EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglTerminate(display);
}
void SurfaceFlinger::binderDied(const wp<IBinder>& /* who */)
@@ -568,7 +564,7 @@
virtual void onInjectSyncEvent(nsecs_t when) {
std::lock_guard<std::mutex> lock(mCallbackMutex);
- if (mCallback != nullptr) {
+ if (mCallback) {
mCallback->onVSyncEvent(when);
}
}
@@ -591,10 +587,6 @@
Mutex::Autolock _l(mStateLock);
- // initialize EGL for the default display
- mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- eglInitialize(mEGLDisplay, NULL, NULL);
-
// start the EventThread
sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseOffsetNs, true, "app");
@@ -615,15 +607,9 @@
}
// Get a RenderEngine for the given display / config (can't fail)
- mRenderEngine = RenderEngine::create(mEGLDisplay,
- HAL_PIXEL_FORMAT_RGBA_8888,
+ mRenderEngine = RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888,
hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0);
-
- // retrieve the EGL context that was selected/created
- mEGLContext = mRenderEngine->getEGLContext();
-
- LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
- "couldn't create EGLContext");
+ LOG_ALWAYS_FATAL_IF(mRenderEngine == nullptr, "couldn't create RenderEngine");
LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
"Starting with vr flinger active is not currently supported.");
@@ -646,7 +632,8 @@
postMessageAsync(message);
};
mVrFlinger = dvr::VrFlinger::Create(mHwc->getComposer(),
- vrFlingerRequestDisplayCallback);
+ mHwc->getHwcDisplayId(HWC_DISPLAY_PRIMARY).value_or(0),
+ vrFlingerRequestDisplayCallback);
if (!mVrFlinger) {
ALOGE("Failed to start vrflinger");
}
@@ -1065,42 +1052,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;
}
@@ -1317,8 +1291,7 @@
}
bool useWideColorMode = hasWideColorModes && hasWideColorDisplay && !mForceNativeColorMode;
sp<DisplayDevice> hw = new DisplayDevice(this, DisplayDevice::DISPLAY_PRIMARY, type, isSecure,
- token, fbs, producer, mRenderEngine->getEGLConfig(),
- useWideColorMode);
+ token, fbs, producer, useWideColorMode);
mDisplays.add(token, hw);
android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE;
if (useWideColorMode) {
@@ -1333,7 +1306,7 @@
// make the GLContext current so that we can create textures when creating
// Layers (which may happens before we render something)
- hw->makeCurrent(mEGLDisplay, mEGLContext);
+ hw->makeCurrent();
}
void SurfaceFlinger::onHotplugReceived(int32_t sequenceId,
@@ -1404,7 +1377,7 @@
// mCurrentState and mDrawingState and re-apply all changes when we make the
// transition.
mDrawingState.displays.clear();
- eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ getRenderEngine().resetCurrentSurface();
mDisplays.clear();
}
@@ -1531,6 +1504,7 @@
rebuildLayerStacks();
setUpHWComposer();
doDebugFlashRegions();
+ doTracing("handleRefresh");
doComposition();
postComposition(refreshStartTime);
@@ -1560,7 +1534,7 @@
const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
if (!dirtyRegion.isEmpty()) {
// redraw the whole screen
- doComposeSurfaces(hw, Region(hw->bounds()));
+ doComposeSurfaces(hw);
// and draw the dirty region
const int32_t height = hw->getHeight();
@@ -1590,6 +1564,14 @@
}
}
+void SurfaceFlinger::doTracing(const char* where) {
+ ATRACE_CALL();
+ ATRACE_NAME(where);
+ if (CC_UNLIKELY(mTracing.isEnabled())) {
+ mTracing.traceLayers(where, dumpProtoInfo(LayerVector::StateSet::Drawing));
+ }
+}
+
void SurfaceFlinger::preComposition(nsecs_t refreshStartTime)
{
ATRACE_CALL();
@@ -1774,7 +1756,7 @@
// rebuild the visible layer list per screen
if (CC_UNLIKELY(mVisibleRegionsDirty)) {
- ATRACE_CALL();
+ ATRACE_NAME("rebuildLayerStacks VR Dirty");
mVisibleRegionsDirty = false;
invalidateHwcGeometry();
@@ -1973,6 +1955,12 @@
"display %zd: %d", displayId, result);
}
for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+ if (layer->getForceClientComposition(hwcId)) {
+ ALOGV("[%s] Requesting Client composition", layer->getName().string());
+ layer->setCompositionType(hwcId, HWC2::Composition::Client);
+ continue;
+ }
+
layer->setPerFrameData(displayDevice);
}
@@ -2021,8 +2009,7 @@
doDisplayComposition(hw, dirtyRegion);
hw->dirtyRegion.clear();
- hw->flip(hw->swapRegion);
- hw->swapRegion.clear();
+ hw->flip();
}
}
postFramebuffer();
@@ -2046,7 +2033,7 @@
mHwc->presentAndGetReleaseFences(hwcId);
}
displayDevice->onSwapBuffersCompleted();
- displayDevice->makeCurrent(mEGLDisplay, mEGLContext);
+ displayDevice->makeCurrent();
for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
// The layer buffer from the previous frame (if any) is released
// by HWC only when the release fence from this frame (if any) is
@@ -2172,7 +2159,7 @@
// be sure that nothing associated with this display
// is current.
const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDeviceLocked());
- defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext);
+ defaultDisplay->makeCurrent();
sp<DisplayDevice> hw(getDisplayDeviceLocked(draw.keyAt(i)));
if (hw != NULL)
hw->disconnect(getHwComposer());
@@ -2290,9 +2277,7 @@
if (dispSurface != NULL) {
sp<DisplayDevice> hw =
new DisplayDevice(this, state.type, hwcId, state.isSecure, display,
- dispSurface, producer,
- mRenderEngine->getEGLConfig(),
- hasWideColorDisplay);
+ dispSurface, producer, hasWideColorDisplay);
hw->setLayerStack(state.layerStack);
hw->setProjection(state.orientation,
state.viewport, state.frame);
@@ -2512,7 +2497,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;
@@ -2657,46 +2642,18 @@
}
ALOGV("doDisplayComposition");
-
- Region dirtyRegion(inDirtyRegion);
-
- // compute the invalid region
- displayDevice->swapRegion.orSelf(dirtyRegion);
-
- uint32_t flags = displayDevice->getFlags();
- if (flags & DisplayDevice::SWAP_RECTANGLE) {
- // we can redraw only what's dirty, but since SWAP_RECTANGLE only
- // takes a rectangle, we must make sure to update that whole
- // rectangle in that case
- dirtyRegion.set(displayDevice->swapRegion.bounds());
- } else {
- if (flags & DisplayDevice::PARTIAL_UPDATES) {
- // We need to redraw the rectangle that will be updated
- // (pushed to the framebuffer).
- // This is needed because PARTIAL_UPDATES only takes one
- // rectangle instead of a region (see DisplayDevice::flip())
- dirtyRegion.set(displayDevice->swapRegion.bounds());
- } else {
- // we need to redraw everything (the whole screen)
- dirtyRegion.set(displayDevice->bounds());
- displayDevice->swapRegion = dirtyRegion;
- }
- }
-
- if (!doComposeSurfaces(displayDevice, dirtyRegion)) return;
-
- // update the swap region and clear the dirty region
- displayDevice->swapRegion.orSelf(dirtyRegion);
+ if (!doComposeSurfaces(displayDevice)) return;
// swap buffers (presentation)
displayDevice->swapBuffers(getHwComposer());
}
-bool SurfaceFlinger::doComposeSurfaces(
- const sp<const DisplayDevice>& displayDevice, const Region& dirty)
+bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& displayDevice)
{
ALOGV("doComposeSurfaces");
+ const Region bounds(displayDevice->bounds());
+ const DisplayRenderArea renderArea(displayDevice);
const auto hwcId = displayDevice->getHwcDisplayId();
mat4 oldColorMatrix;
@@ -2711,19 +2668,17 @@
if (hasClientComposition) {
ALOGV("hasClientComposition");
-#ifdef USE_HWC2
mRenderEngine->setWideColor(
displayDevice->getWideColorSupport() && !mForceNativeColorMode);
mRenderEngine->setColorMode(mForceNativeColorMode ?
HAL_COLOR_MODE_NATIVE : displayDevice->getActiveColorMode());
-#endif
- if (!displayDevice->makeCurrent(mEGLDisplay, mEGLContext)) {
+ if (!displayDevice->makeCurrent()) {
ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
displayDevice->getDisplayName().string());
- eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ getRenderEngine().resetCurrentSurface();
// |mStateLock| not needed as we are on the main thread
- if(!getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext)) {
+ if(!getDefaultDisplayDeviceLocked()->makeCurrent()) {
ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");
}
return false;
@@ -2739,10 +2694,7 @@
// We'll revisit later if needed.
mRenderEngine->clearWithColor(0, 0, 0, 0);
} else {
- // we start with the whole screen area
- const Region bounds(displayDevice->getBounds());
-
- // we remove the scissor part
+ // we start with the whole screen area and remove the scissor part
// we're left with the letterbox region
// (common case is that letterbox ends-up being empty)
const Region letterbox(bounds.subtract(displayDevice->getScissor()));
@@ -2750,9 +2702,6 @@
// compute the area to clear
Region region(displayDevice->undefinedRegion.merge(letterbox));
- // but limit it to the dirty region
- region.andSelf(dirty);
-
// screen is already cleared here
if (!region.isEmpty()) {
// can happen with SurfaceView
@@ -2789,7 +2738,7 @@
// we're using h/w composer
bool firstLayer = true;
for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
- const Region clip(dirty.intersect(
+ const Region clip(bounds.intersect(
displayTransform.transform(layer->visibleRegion)));
ALOGV("Layer: %s", layer->getName().string());
ALOGV(" Composition type: %s",
@@ -2802,16 +2751,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:
@@ -2825,10 +2774,10 @@
} else {
// we're not using h/w composer
for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
- const Region clip(dirty.intersect(
+ const Region clip(bounds.intersect(
displayTransform.transform(layer->visibleRegion)));
if (!clip.isEmpty()) {
- layer->draw(displayDevice, clip);
+ layer->draw(renderArea, clip);
}
}
}
@@ -2865,7 +2814,7 @@
if (parent == nullptr) {
mCurrentState.layersSortedByZ.add(lbc);
} else {
- if (mCurrentState.layersSortedByZ.indexOf(parent) < 0) {
+ if (parent->isPendingRemoval()) {
ALOGE("addClientLayer called with a removed parent");
return NAME_NOT_FOUND;
}
@@ -2886,6 +2835,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) {
@@ -3089,122 +3042,153 @@
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) {
+ // 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) && 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->setChildRelativeLayer(layer, s.relativeLayerHandle, s.z)) {
+ 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) {
+ bool hadParent = layer->hasParent();
+ if (layer->reparent(s.parentHandleForChild)) {
+ if (!hadParent) {
+ mCurrentState.layersSortedByZ.remove(layer);
+ }
+ 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;
}
@@ -3229,14 +3213,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;
@@ -3290,7 +3275,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)
{
@@ -3305,24 +3290,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;
}
@@ -3450,7 +3435,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
@@ -3464,7 +3450,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);
@@ -3513,13 +3500,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: "
@@ -3539,6 +3526,13 @@
bool dumpAll = true;
size_t index = 0;
size_t numArgs = args.size();
+
+ if (asProto) {
+ LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current);
+ result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize());
+ dumpAll = false;
+ }
+
if (numArgs) {
if ((index < numArgs) &&
(args[index] == String16("--list"))) {
@@ -3783,6 +3777,18 @@
result.append("\n");
}
+LayersProto SurfaceFlinger::dumpProtoInfo(LayerVector::StateSet stateSet) const {
+ LayersProto layersProto;
+ const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
+ const State& state = useDrawing ? mDrawingState : mCurrentState;
+ state.traverseInZOrder([&](Layer* layer) {
+ LayerProto* layerProto = layersProto.add_layers();
+ layer->writeToProto(layerProto, stateSet);
+ });
+
+ return layersProto;
+}
+
void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
String8& result) const
{
@@ -3847,9 +3853,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(LayerVector::StateSet::Current);
+ auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
+ result.append(LayerProtoParser::layersToString(layerTree).c_str());
/*
* Dump Display state
@@ -3874,13 +3881,6 @@
HWComposer& hwc(getHwComposer());
sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
- colorizer.bold(result);
- result.appendFormat("EGL implementation : %s\n",
- eglQueryStringImplementationANDROID(mEGLDisplay, EGL_VERSION));
- colorizer.reset(result);
- result.appendFormat("%s\n",
- eglQueryStringImplementationANDROID(mEGLDisplay, EGL_EXTENSIONS));
-
mRenderEngine->dump(result);
hw->undefinedRegion.dump(result, "undefinedRegion");
@@ -4043,6 +4043,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;
}
@@ -4226,6 +4237,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;
@@ -4242,35 +4267,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:
@@ -4284,111 +4280,109 @@
const int mApi;
};
-static status_t getWindowBuffer(ANativeWindow* window, uint32_t requestedWidth,
- uint32_t requestedHeight, bool hasWideColorDisplay,
- bool renderEngineUsesWideColor, ANativeWindowBuffer** outBuffer) {
- const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
- GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
-
- int err = 0;
- err = native_window_set_buffers_dimensions(window, requestedWidth, requestedHeight);
- 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);
-
- if (hasWideColorDisplay) {
- err |= native_window_set_buffers_data_space(window,
- renderEngineUsesWideColor
- ? HAL_DATASPACE_DISPLAY_P3
- : HAL_DATASPACE_V0_SRGB);
- }
-
- if (err != NO_ERROR) {
- return BAD_VALUE;
- }
-
- /* TODO: Once we have the sync framework everywhere this can use
- * server-side waits on the fence that dequeueBuffer returns.
- */
- err = native_window_dequeue_buffer_and_wait(window, outBuffer);
- if (err != NO_ERROR) {
- return err;
- }
-
- return NO_ERROR;
-}
-
-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) {
+status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
+ 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;
- if (CC_UNLIKELY(producer == 0))
- return BAD_VALUE;
+ const sp<const DisplayDevice> device(getDisplayDeviceLocked(display));
+ DisplayRenderArea renderArea(device, sourceCrop, reqHeight, reqWidth, rotation);
- // 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();
+ auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this,
+ device, minLayerZ, maxLayerZ, std::placeholders::_1);
+ return captureScreenCommon(renderArea, traverseLayers, outBuffer, useIdentityTransform);
+}
- // 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;
+status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder,
+ sp<GraphicBuffer>* outBuffer, const Rect& sourceCrop,
+ float frameScale) {
+ ATRACE_CALL();
+
+ class LayerRenderArea : public RenderArea {
+ public:
+ LayerRenderArea(const sp<Layer>& layer, const Rect crop, int32_t reqWidth,
+ int32_t reqHeight)
+ : RenderArea(reqHeight, reqWidth), mLayer(layer), mCrop(crop) {}
+ 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 {
+ if (mCrop.isEmpty()) {
+ return getBounds();
+ } else {
+ return mCrop;
+ }
+ }
+ bool getWideColorSupport() const override { return false; }
+ android_color_mode_t getActiveColorMode() const override { return HAL_COLOR_MODE_NATIVE; }
+
+ private:
+ const sp<Layer> mLayer;
+ const Rect mCrop;
+ };
+
+ auto layerHandle = reinterpret_cast<Layer::Handle*>(layerHandleBinder.get());
+ auto parent = layerHandle->owner.promote();
+
+ if (parent == nullptr || parent->isPendingRemoval()) {
+ ALOGE("captureLayers called with a removed parent");
+ return NAME_NOT_FOUND;
}
- { // Autolock scope
- Mutex::Autolock lock(mStateLock);
- sp<const DisplayDevice> displayDevice(getDisplayDeviceLocked(display));
- updateDimensionsLocked(displayDevice, rotationFlags, &reqWidth, &reqHeight);
+ Rect crop(sourceCrop);
+ if (sourceCrop.width() <= 0) {
+ crop.left = 0;
+ crop.right = parent->getCurrentState().active.w;
}
- // create a surface (because we're a producer, and we need to
- // dequeue/queue a buffer)
- sp<Surface> surface = new Surface(producer, false);
-
- // Put the screenshot Surface into async mode so that
- // Layer::headFenceHasSignaled will always return true and we'll latch the
- // first buffer regardless of whether or not its acquire fence has
- // signaled. This is needed to avoid a race condition in the rotation
- // animation. See b/30209608
- surface->setAsyncMode(true);
-
- ANativeWindow* window = surface.get();
-
- status_t result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
- if (result != NO_ERROR) {
- return result;
+ if (sourceCrop.height() <= 0) {
+ crop.top = 0;
+ crop.bottom = parent->getCurrentState().active.h;
}
- WindowDisconnector disconnector(window, NATIVE_WINDOW_API_EGL);
- ANativeWindowBuffer* buffer = nullptr;
- result = getWindowBuffer(window, reqWidth, reqHeight,
- hasWideColorDisplay && !mForceNativeColorMode,
- getRenderEngine().usesWideColor(), &buffer);
- if (result != NO_ERROR) {
- return result;
- }
+ int32_t reqWidth = crop.width() * frameScale;
+ int32_t reqHeight = crop.height() * frameScale;
+
+ LayerRenderArea renderArea(parent, crop, reqWidth, reqHeight);
+
+ auto traverseLayers = [parent](const LayerVector::Visitor& visitor) {
+ parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
+ if (!layer->isVisible()) {
+ return;
+ }
+ visitor(layer);
+ });
+ };
+ return captureScreenCommon(renderArea, traverseLayers, outBuffer, false);
+}
+
+status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea,
+ TraverseLayersFunction traverseLayers,
+ sp<GraphicBuffer>* outBuffer,
+ bool useIdentityTransform) {
+ ATRACE_CALL();
+
+ renderArea.updateDimensions();
+
+ const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
+ GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
+ *outBuffer = new GraphicBuffer(renderArea.getReqWidth(), renderArea.getReqHeight(),
+ HAL_PIXEL_FORMAT_RGBA_8888, 1, usage, "screenshot");
// This mutex protects syncFd and captureResult for communication of the return values from the
// main thread back to this Binder thread
@@ -4413,10 +4407,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, (*outBuffer).get(),
+ useIdentityTransform, &fd);
}
{
@@ -4427,7 +4419,7 @@
}
});
- result = postMessageAsync(message);
+ status_t result = postMessageAsync(message);
if (result == NO_ERROR) {
captureCondition.wait(captureLock, [&]() { return captureResult; });
while (*captureResult == EAGAIN) {
@@ -4442,153 +4434,96 @@
}
if (result == NO_ERROR) {
- // queueBuffer takes ownership of syncFd
- result = window->queueBuffer(window, buffer, syncFd);
+ sync_wait(syncFd, -1);
+ close(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:
-// a) When the destroy() method is called
-// b) When the object goes out of scope
-class ImageHolder {
-public:
- ImageHolder(EGLDisplay display, EGLImageKHR image) : mDisplay(display), mImage(image) {}
- ~ImageHolder() { destroy(); }
-
- void destroy() {
- if (mImage != EGL_NO_IMAGE_KHR) {
- eglDestroyImageKHR(mDisplay, mImage);
- mImage = EGL_NO_IMAGE_KHR;
- }
- }
-
-private:
- const EGLDisplay mDisplay;
- 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,
+status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea,
+ TraverseLayersFunction traverseLayers,
+ ANativeWindowBuffer* buffer,
bool useIdentityTransform,
- Transform::orientation_flags rotation,
- bool isLocalScreenshot, int* outSyncFd) {
+ 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());
- });
- }
- if (!isLocalScreenshot && secureLayerIsVisible) {
+ traverseLayers([&](Layer* layer) {
+ secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && layer->isSecure());
+ });
+
+ if (secureLayerIsVisible) {
ALOGW("FB is protected: PERMISSION_DENIED");
return PERMISSION_DENIED;
}
- int syncFd = -1;
- // create an EGLImage from the buffer so we can later
- // turn it into a texture
- EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT,
- EGL_NATIVE_BUFFER_ANDROID, buffer, NULL);
- if (image == EGL_NO_IMAGE_KHR) {
- return BAD_VALUE;
- }
-
- // This will automatically destroy the image if we return before calling its destroy method
- ImageHolder imageHolder(mEGLDisplay, image);
-
// this binds the given EGLImage as a framebuffer for the
// duration of this scope.
- RenderEngine::BindImageAsFramebuffer imageBond(getRenderEngine(), image);
- if (imageBond.getStatus() != NO_ERROR) {
- ALOGE("got GL_FRAMEBUFFER_COMPLETE_OES error while taking screenshot");
+ RenderEngine::BindNativeBufferAsFramebuffer bufferBond(getRenderEngine(), buffer);
+ if (bufferBond.getStatus() != NO_ERROR) {
+ ALOGE("got ANWB binding error while taking screenshot");
return INVALID_OPERATION;
}
@@ -4596,89 +4531,43 @@
// 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
- // wait on it directly.
- EGLSyncKHR sync = EGL_NO_SYNC_KHR;
- if (!DEBUG_SCREENSHOTS) {
- sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
- // native fence fd will not be populated until flush() is done.
- getRenderEngine().flush();
- }
-
- if (sync != EGL_NO_SYNC_KHR) {
- // get the sync fd
- syncFd = eglDupNativeFenceFDANDROID(mEGLDisplay, sync);
- if (syncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
- ALOGW("captureScreen: failed to dup sync khr object");
- syncFd = -1;
- }
- eglDestroySyncKHR(mEGLDisplay, sync);
- } else {
- // fallback path
- sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL);
- if (sync != EGL_NO_SYNC_KHR) {
- EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync,
- EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 2000000000 /*2 sec*/);
- EGLint eglErr = eglGetError();
- if (result == EGL_TIMEOUT_EXPIRED_KHR) {
- ALOGW("captureScreen: fence wait timed out");
- } else {
- ALOGW_IF(eglErr != EGL_SUCCESS,
- "captureScreen: error waiting on EGL fence: %#x", eglErr);
- }
- eglDestroySyncKHR(mEGLDisplay, sync);
- } else {
- ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError());
- }
- }
- *outSyncFd = syncFd;
+ *outSyncFd = getRenderEngine().flush(DEBUG_SCREENSHOTS);
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++;
+ });
}
}
@@ -4692,6 +4581,29 @@
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());
+ // relative layers are traversed in Layer::traverseInZOrder
+ if (state.zOrderRelativeOf != nullptr || state.z < minLayerZ || state.z > maxLayerZ) {
+ continue;
+ }
+ layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
+ if (!layer->isVisible()) {
+ return;
+ }
+ visitor(layer);
+ });
+ }
+}
+
}; // namespace android
@@ -4701,4 +4613,4 @@
#if defined(__gl2_h_)
#error "don't include gl2/gl2.h in this file"
-#endif
+#endif
\ No newline at end of file
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 231709d..974de94 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -21,8 +21,6 @@
#include <stdint.h>
#include <sys/types.h>
-#include <EGL/egl.h>
-
/*
* NOTE: Make sure this file doesn't include anything from <gl/ > or <gl2/ >
*/
@@ -43,13 +41,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,14 +58,11 @@
#include "LayerVector.h"
#include "MessageQueue.h"
#include "SurfaceInterceptor.h"
+#include "SurfaceTracing.h"
#include "StartPropertySetThread.h"
-#ifdef USE_HWC2
#include "DisplayHardware/HWC2.h"
#include "DisplayHardware/HWComposer.h"
-#else
-#include "DisplayHardware/HWComposer_hwc1.h"
-#endif
#include "Effects/Daltonizer.h"
@@ -75,6 +72,11 @@
#include <string>
#include <thread>
#include <utility>
+#include "RenderArea.h"
+
+#include <layerproto/LayerProtoHeader.h>
+
+using namespace android::surfaceflinger;
namespace android {
@@ -84,13 +86,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,12 +109,9 @@
};
class SurfaceFlinger : public BnSurfaceComposer,
+ public PriorityDumper,
private IBinder::DeathRecipient,
-#ifdef USE_HWC2
private HWC2::ComposerCallback
-#else
- private HWComposer::EventHandler
-#endif
{
public:
@@ -206,11 +207,7 @@
// enable/disable h/w composer event
// TODO: this should be made accessible only to EventThread
-#ifdef USE_HWC2
void setVsyncEnabled(int disp, int enabled);
-#else
- void eventControl(int disp, int event, int enabled);
-#endif
// called on the main thread by MessageQueue when an internal message
// is received
@@ -233,6 +230,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 +270,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
@@ -291,11 +289,12 @@
std::vector<FrameEvent>* outSupported) const;
virtual sp<IDisplayEventConnection> createDisplayEventConnection(
ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp);
- virtual status_t 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);
+ virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
+ 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, sp<GraphicBuffer>* outBuffer,
+ const Rect& sourceCrop, float frameScale);
virtual status_t getDisplayStats(const sp<IBinder>& display,
DisplayStatInfo* stats);
virtual status_t getDisplayConfigs(const sp<IBinder>& display,
@@ -329,18 +328,12 @@
/* ------------------------------------------------------------------------
* HWC2::ComposerCallback / HWComposer::EventHandler interface
*/
-#ifdef USE_HWC2
void onVsyncReceived(int32_t sequenceId, hwc2_display_t display,
int64_t timestamp) override;
void onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
HWC2::Connection connection,
bool primaryDisplay) override;
void onRefreshReceived(int32_t sequenceId, hwc2_display_t display) override;
-#else
- void onVSyncReceived(HWComposer* composer, int type, nsecs_t timestamp) override;
- void onHotplugReceived(HWComposer* composer, int disp, bool connected) override;
- void onInvalidateReceived(HWComposer* composer) override;
-#endif
/* ------------------------------------------------------------------------
* Message handling
@@ -357,19 +350,12 @@
// called on the main thread in response to setActiveConfig()
void setActiveConfigInternal(const sp<DisplayDevice>& hw, int mode);
// called on the main thread in response to setPowerMode()
-#ifdef USE_HWC2
void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode,
bool stateLockHeld);
-#else
- void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode);
-#endif
// 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 +394,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 +430,17 @@
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);
-
-#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,
+ void renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers,
+ bool yswap, bool useIdentityTransform);
+ status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers,
+ sp<GraphicBuffer>* outBuffer,
+ bool useIdentityTransform);
+ status_t captureScreenImplLocked(const RenderArea& renderArea,
+ TraverseLayersFunction traverseLayers,
+ ANativeWindowBuffer* buffer, bool useIdentityTransform,
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);
-#endif
+ void traverseLayersInDisplay(const sp<const DisplayDevice>& display, int32_t minLayerZ,
+ int32_t maxLayerZ, const LayerVector::Visitor& visitor);
sp<StartPropertySetThread> mStartPropertySetThread = nullptr;
@@ -530,10 +505,6 @@
// region of all screens presenting this layer stack.
void invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty);
-#ifndef USE_HWC2
- int32_t allocateHwcDisplayId(DisplayDevice::DisplayType type);
-#endif
-
/* ------------------------------------------------------------------------
* H/W composer
*/
@@ -567,11 +538,12 @@
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
// has been destroyed and is no longer valid.
- bool doComposeSurfaces(const sp<const DisplayDevice>& displayDevice, const Region& dirty);
+ bool doComposeSurfaces(const sp<const DisplayDevice>& displayDevice);
void postFramebuffer();
void drawWormhole(const sp<const DisplayDevice>& displayDevice, const Region& region) const;
@@ -595,6 +567,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 +584,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,12 +596,13 @@
std::vector<OccupancyTracker::Segment>&& history);
void dumpBufferingStats(String8& result) const;
void dumpWideColorInfo(String8& result) const;
+ LayersProto dumpProtoInfo(LayerVector::StateSet stateSet) const;
bool isLayerTripleBufferingDisabled() const {
return this->mLayerTripleBufferingDisabled;
}
+ status_t doDump(int fd, const Vector<String16>& args, bool asProto);
-#ifdef USE_HWC2
/* ------------------------------------------------------------------------
* VrFlinger
*/
@@ -628,7 +610,6 @@
// Check to see if we should handoff to vr flinger.
void updateVrFlinger();
-#endif
/* ------------------------------------------------------------------------
* Attributes
@@ -673,12 +654,10 @@
// acquiring mStateLock.
std::unique_ptr<HWComposer> mHwc;
-#ifdef USE_HWC2
const std::string mHwcServiceName; // "default" for real use, something else for testing.
-#endif
// constant members (no synchronization needed for access)
- RenderEngine* mRenderEngine;
+ std::unique_ptr<RenderEngine> mRenderEngine;
nsecs_t mBootTime;
bool mGpuToCpuSupported;
sp<EventThread> mEventThread;
@@ -686,25 +665,17 @@
sp<EventThread> mInjectorEventThread;
sp<InjectVSyncSource> mVSyncInjector;
sp<EventControlThread> mEventControlThread;
- EGLContext mEGLContext;
- EGLDisplay mEGLDisplay;
sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES];
// Can only accessed from the main thread, these members
// don't need synchronization
State mDrawingState{LayerVector::StateSet::Drawing};
bool mVisibleRegionsDirty;
-#ifndef USE_HWC2
- bool mHwWorkListDirty;
-#else
bool mGeometryInvalid;
-#endif
bool mAnimCompositionPending;
-#ifdef USE_HWC2
std::vector<sp<Layer>> mLayersWithQueuedFrames;
sp<Fence> mPreviousPresentFence = Fence::NO_FENCE;
bool mHadClientComposition = false;
-#endif
FenceTimeline mGlCompositionDoneTimeline;
FenceTimeline mDisplayTimeline;
@@ -723,10 +694,9 @@
nsecs_t mLastTransactionTime;
bool mBootFinished;
bool mForceFullDamage;
-#ifdef USE_HWC2
bool mPropagateBackpressure = true;
-#endif
SurfaceInterceptor mInterceptor;
+ SurfaceTracing mTracing;
bool mUseHwcVirtualDisplays = false;
// Restrict layers to use two buffers in their bufferqueues.
@@ -766,9 +736,6 @@
bool mInjectVSyncs;
Daltonizer mDaltonizer;
-#ifndef USE_HWC2
- bool mDaltonize;
-#endif
mat4 mPreviousColorMatrix;
mat4 mColorMatrix;
@@ -810,7 +777,6 @@
// either AID_GRAPHICS or AID_SYSTEM.
status_t CheckTransactCodeCredentials(uint32_t code);
-#ifdef USE_HWC2
std::unique_ptr<dvr::VrFlinger> mVrFlinger;
std::atomic<bool> mVrFlingerRequestsDisplay;
static bool useVrFlinger;
@@ -819,7 +785,6 @@
// use to differentiate callbacks from different hardware composer
// instances. Each hardware composer instance gets a different sequence id.
int32_t mComposerSequenceId;
-#endif
float mSaturation = 1.0f;
bool mForceNativeColorMode = false;
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index abc8fde..e17bb58 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -89,11 +89,7 @@
}
// Release the previous buffer.
-#ifdef USE_HWC2
err = updateAndReleaseLocked(item, &mPendingRelease);
-#else
- err = updateAndReleaseLocked(item);
-#endif
if (err != NO_ERROR) {
return err;
}
@@ -197,7 +193,6 @@
return ConsumerBase::mPrevFinalReleaseFence;
}
-#ifdef USE_HWC2
void SurfaceFlingerConsumer::setReleaseFence(const sp<Fence>& fence)
{
if (!mPendingRelease.isPending) {
@@ -230,7 +225,6 @@
mPendingRelease = PendingRelease();
return true;
}
-#endif
void SurfaceFlingerConsumer::setContentsChangedListener(
const wp<ContentsChangedListener>& listener) {
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h
index 1126233..53b4915 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.h
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -81,10 +81,8 @@
nsecs_t computeExpectedPresent(const DispSync& dispSync);
sp<Fence> getPrevFinalReleaseFence() const;
-#ifdef USE_HWC2
virtual void setReleaseFence(const sp<Fence>& fence) override;
bool releasePendingBuffer();
-#endif
void onDisconnect() override;
void addAndGetFrameTimestamps(
@@ -104,11 +102,9 @@
// The portion of this surface that has changed since the previous frame
Region mSurfaceDamage;
-#ifdef USE_HWC2
// A release that is pending on the receipt of a new release fence from
// presentDisplay
PendingRelease mPendingRelease;
-#endif
// The layer for this SurfaceFlingerConsumer
const wp<Layer> mLayer;
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
deleted file mode 100644
index 1d6fbaf..0000000
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ /dev/null
@@ -1,4117 +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 ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include <dlfcn.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <math.h>
-#include <stdatomic.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <mutex>
-
-#include <EGL/egl.h>
-
-#include <cutils/properties.h>
-#include <log/log.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/PermissionCache.h>
-
-#include <ui/DisplayInfo.h>
-#include <ui/DisplayStatInfo.h>
-
-#include <gui/BufferQueue.h>
-#include <gui/GuiConfig.h>
-#include <gui/IDisplayEventConnection.h>
-#include <gui/LayerDebugInfo.h>
-#include <gui/Surface.h>
-
-#include <ui/GraphicBufferAllocator.h>
-#include <ui/HdrCapabilities.h>
-#include <ui/PixelFormat.h>
-#include <ui/UiConfig.h>
-
-#include <utils/misc.h>
-#include <utils/String8.h>
-#include <utils/String16.h>
-#include <utils/StopWatch.h>
-#include <utils/Timers.h>
-#include <utils/Trace.h>
-
-#include <private/android_filesystem_config.h>
-#include <private/gui/SyncFeatures.h>
-
-#include <set>
-
-#include "Client.h"
-#include "clz.h"
-#include "Colorizer.h"
-#include "DdmConnection.h"
-#include "DisplayDevice.h"
-#include "DispSync.h"
-#include "EventControlThread.h"
-#include "EventThread.h"
-#include "Layer.h"
-#include "LayerVector.h"
-#include "LayerDim.h"
-#include "MonitoredProducer.h"
-#include "SurfaceFlinger.h"
-
-#include "DisplayHardware/FramebufferSurface.h"
-#include "DisplayHardware/HWComposer.h"
-#include "DisplayHardware/VirtualDisplaySurface.h"
-
-#include "Effects/Daltonizer.h"
-
-#include "RenderEngine/RenderEngine.h"
-#include <cutils/compiler.h>
-
-#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
-#include <configstore/Utils.h>
-
-#define DISPLAY_COUNT 1
-
-/*
- * DEBUG_SCREENSHOTS: set to true to check that screenshots are not all
- * black pixels.
- */
-#define DEBUG_SCREENSHOTS false
-
-extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-using namespace android::hardware::configstore;
-using namespace android::hardware::configstore::V1_0;
-
-const String16 sHardwareTest("android.permission.HARDWARE_TEST");
-const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER");
-const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
-const String16 sDump("android.permission.DUMP");
-
-// ---------------------------------------------------------------------------
-int64_t SurfaceFlinger::vsyncPhaseOffsetNs;
-int64_t SurfaceFlinger::sfVsyncPhaseOffsetNs;
-bool SurfaceFlinger::useContextPriority;
-int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
-bool SurfaceFlinger::useHwcForRgbToYuv;
-uint64_t SurfaceFlinger::maxVirtualDisplaySize;
-bool SurfaceFlinger::hasSyncFramework;
-int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers;
-
-SurfaceFlinger::SurfaceFlinger()
- : BnSurfaceComposer(),
- mTransactionFlags(0),
- mTransactionPending(false),
- mAnimTransactionPending(false),
- mLayersRemoved(false),
- mLayersAdded(false),
- mRepaintEverything(0),
- mRenderEngine(NULL),
- mBootTime(systemTime()),
- mVisibleRegionsDirty(false),
- mHwWorkListDirty(false),
- mAnimCompositionPending(false),
- mDebugRegion(0),
- mDebugDDMS(0),
- mDebugDisableHWC(0),
- mDebugDisableTransformHint(0),
- mDebugInSwapBuffers(0),
- mLastSwapBufferTime(0),
- mDebugInTransaction(0),
- mLastTransactionTime(0),
- mBootFinished(false),
- mForceFullDamage(false),
- mInterceptor(this),
- mPrimaryDispSync("PrimaryDispSync"),
- mPrimaryHWVsyncEnabled(false),
- mHWVsyncAvailable(false),
- mDaltonize(false),
- mHasColorMatrix(false),
- mHasPoweredOff(false),
- mFrameBuckets(),
- mTotalTime(0),
- mLastSwapTime(0),
- mNumLayers(0)
-{
- ALOGI("SurfaceFlinger is starting");
-
- vsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
- &ISurfaceFlingerConfigs::vsyncEventPhaseOffsetNs>(1000000);
-
- sfVsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
- &ISurfaceFlingerConfigs::vsyncSfEventPhaseOffsetNs>(1000000);
-
- maxVirtualDisplaySize = getUInt64<ISurfaceFlingerConfigs,
- &ISurfaceFlingerConfigs::maxVirtualDisplaySize>(0);
-
- hasSyncFramework = getBool< ISurfaceFlingerConfigs,
- &ISurfaceFlingerConfigs::hasSyncFramework>(true);
-
- useContextPriority = getBool< ISurfaceFlingerConfigs,
- &ISurfaceFlingerConfigs::useContextPriority>(false);
-
- dispSyncPresentTimeOffset = getInt64< ISurfaceFlingerConfigs,
- &ISurfaceFlingerConfigs::presentTimeOffsetFromVSyncNs>(0);
-
- useHwcForRgbToYuv = getBool< ISurfaceFlingerConfigs,
- &ISurfaceFlingerConfigs::useHwcForRGBtoYUV>(false);
-
- maxFrameBufferAcquiredBuffers = getInt64< ISurfaceFlingerConfigs,
- &ISurfaceFlingerConfigs::maxFrameBufferAcquiredBuffers>(2);
-
- mPrimaryDispSync.init(hasSyncFramework, dispSyncPresentTimeOffset);
-
- char value[PROPERTY_VALUE_MAX];
-
- property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");
- mGpuToCpuSupported = !atoi(value);
-
- property_get("debug.sf.showupdates", value, "0");
- mDebugRegion = atoi(value);
-
- property_get("debug.sf.ddms", value, "0");
- mDebugDDMS = atoi(value);
- if (mDebugDDMS) {
- if (!startDdmConnection()) {
- // start failed, and DDMS debugging not enabled
- mDebugDDMS = 0;
- }
- }
- ALOGI_IF(mDebugRegion, "showupdates enabled");
- ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
-
- property_get("debug.sf.enable_hwc_vds", value, "0");
- mUseHwcVirtualDisplays = atoi(value);
- ALOGI_IF(!mUseHwcVirtualDisplays, "Enabling HWC virtual displays");
-
- property_get("ro.sf.disable_triple_buffer", value, "1");
- mLayerTripleBufferingDisabled = atoi(value);
- ALOGI_IF(mLayerTripleBufferingDisabled, "Disabling Triple Buffering");
-}
-
-void SurfaceFlinger::onFirstRef()
-{
- mEventQueue.init(this);
-}
-
-SurfaceFlinger::~SurfaceFlinger()
-{
- EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglTerminate(display);
-}
-
-void SurfaceFlinger::binderDied(const wp<IBinder>& /* who */)
-{
- // the window manager died on us. prepare its eulogy.
-
- // restore initial conditions (default device unblank, etc)
- initializeDisplays();
-
- // restart the boot-animation
- startBootAnim();
-}
-
-static sp<ISurfaceComposerClient> initClient(const sp<Client>& client) {
- status_t err = client->initCheck();
- if (err == NO_ERROR) {
- return client;
- }
- return nullptr;
-}
-
-sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
- return initClient(new Client(this));
-}
-
-sp<ISurfaceComposerClient> SurfaceFlinger::createScopedConnection(
- const sp<IGraphicBufferProducer>& gbp) {
- if (authenticateSurfaceTexture(gbp) == false) {
- return nullptr;
- }
- const auto& layer = (static_cast<MonitoredProducer*>(gbp.get()))->getLayer();
- if (layer == nullptr) {
- return nullptr;
- }
-
- return initClient(new Client(this, layer));
-}
-
-sp<IBinder> SurfaceFlinger::createDisplay(const String8& displayName,
- bool secure)
-{
- class DisplayToken : public BBinder {
- sp<SurfaceFlinger> flinger;
- virtual ~DisplayToken() {
- // no more references, this display must be terminated
- Mutex::Autolock _l(flinger->mStateLock);
- flinger->mCurrentState.displays.removeItem(this);
- flinger->setTransactionFlags(eDisplayTransactionNeeded);
- }
- public:
- explicit DisplayToken(const sp<SurfaceFlinger>& flinger)
- : flinger(flinger) {
- }
- };
-
- sp<BBinder> token = new DisplayToken(this);
-
- Mutex::Autolock _l(mStateLock);
- DisplayDeviceState info(DisplayDevice::DISPLAY_VIRTUAL, secure);
- info.displayName = displayName;
- mCurrentState.displays.add(token, info);
- mInterceptor.saveDisplayCreation(info);
- return token;
-}
-
-void SurfaceFlinger::destroyDisplay(const sp<IBinder>& display) {
- Mutex::Autolock _l(mStateLock);
-
- ssize_t idx = mCurrentState.displays.indexOfKey(display);
- if (idx < 0) {
- ALOGW("destroyDisplay: invalid display token");
- return;
- }
-
- const DisplayDeviceState& info(mCurrentState.displays.valueAt(idx));
- if (!info.isVirtualDisplay()) {
- ALOGE("destroyDisplay called for non-virtual display");
- return;
- }
- mInterceptor.saveDisplayDeletion(info.displayId);
- mCurrentState.displays.removeItemsAt(idx);
- setTransactionFlags(eDisplayTransactionNeeded);
-}
-
-void SurfaceFlinger::createBuiltinDisplayLocked(DisplayDevice::DisplayType type) {
- ALOGW_IF(mBuiltinDisplays[type],
- "Overwriting display token for display type %d", type);
- mBuiltinDisplays[type] = new BBinder();
- // All non-virtual displays are currently considered secure.
- DisplayDeviceState info(type, true);
- mCurrentState.displays.add(mBuiltinDisplays[type], info);
- mInterceptor.saveDisplayCreation(info);
-}
-
-sp<IBinder> SurfaceFlinger::getBuiltInDisplay(int32_t id) {
- if (uint32_t(id) >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
- ALOGE("getDefaultDisplay: id=%d is not a valid default display id", id);
- return NULL;
- }
- return mBuiltinDisplays[id];
-}
-
-void SurfaceFlinger::bootFinished()
-{
- if (mStartPropertySetThread->join() != NO_ERROR) {
- ALOGE("Join StartPropertySetThread failed!");
- }
- const nsecs_t now = systemTime();
- const nsecs_t duration = now - mBootTime;
- ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
- mBootFinished = true;
-
- // wait patiently for the window manager death
- const String16 name("window");
- sp<IBinder> window(defaultServiceManager()->getService(name));
- if (window != 0) {
- window->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
- }
-
- // stop boot animation
- // formerly we would just kill the process, but we now ask it to exit so it
- // can choose where to stop the animation.
- property_set("service.bootanim.exit", "1");
-
- const int LOGTAG_SF_STOP_BOOTANIM = 60110;
- LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
- ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
-}
-
-void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
- class MessageDestroyGLTexture : public MessageBase {
- RenderEngine& engine;
- uint32_t texture;
- public:
- MessageDestroyGLTexture(RenderEngine& engine, uint32_t texture)
- : engine(engine), texture(texture) {
- }
- virtual bool handler() {
- engine.deleteTextures(1, &texture);
- return true;
- }
- };
- postMessageAsync(new MessageDestroyGLTexture(getRenderEngine(), texture));
-}
-
-class DispSyncSource : public VSyncSource, private DispSync::Callback {
-public:
- DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
- const char* name) :
- mName(name),
- mValue(0),
- mTraceVsync(traceVsync),
- mVsyncOnLabel(String8::format("VsyncOn-%s", name)),
- mVsyncEventLabel(String8::format("VSYNC-%s", name)),
- mDispSync(dispSync),
- mCallbackMutex(),
- mCallback(),
- mVsyncMutex(),
- mPhaseOffset(phaseOffset),
- mEnabled(false) {}
-
- virtual ~DispSyncSource() {}
-
- virtual void setVSyncEnabled(bool enable) {
- Mutex::Autolock lock(mVsyncMutex);
- if (enable) {
- status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
- static_cast<DispSync::Callback*>(this));
- if (err != NO_ERROR) {
- ALOGE("error registering vsync callback: %s (%d)",
- strerror(-err), err);
- }
- //ATRACE_INT(mVsyncOnLabel.string(), 1);
- } else {
- status_t err = mDispSync->removeEventListener(
- static_cast<DispSync::Callback*>(this));
- if (err != NO_ERROR) {
- ALOGE("error unregistering vsync callback: %s (%d)",
- strerror(-err), err);
- }
- //ATRACE_INT(mVsyncOnLabel.string(), 0);
- }
- mEnabled = enable;
- }
-
- virtual void setCallback(const sp<VSyncSource::Callback>& callback) {
- Mutex::Autolock lock(mCallbackMutex);
- mCallback = callback;
- }
-
- virtual void setPhaseOffset(nsecs_t phaseOffset) {
- Mutex::Autolock lock(mVsyncMutex);
-
- // Normalize phaseOffset to [0, period)
- auto period = mDispSync->getPeriod();
- phaseOffset %= period;
- if (phaseOffset < 0) {
- // If we're here, then phaseOffset is in (-period, 0). After this
- // operation, it will be in (0, period)
- phaseOffset += period;
- }
- mPhaseOffset = phaseOffset;
-
- // If we're not enabled, we don't need to mess with the listeners
- if (!mEnabled) {
- return;
- }
-
- // Remove the listener with the old offset
- status_t err = mDispSync->removeEventListener(
- static_cast<DispSync::Callback*>(this));
- if (err != NO_ERROR) {
- ALOGE("error unregistering vsync callback: %s (%d)",
- strerror(-err), err);
- }
-
- // Add a listener with the new offset
- err = mDispSync->addEventListener(mName, mPhaseOffset,
- static_cast<DispSync::Callback*>(this));
- if (err != NO_ERROR) {
- ALOGE("error registering vsync callback: %s (%d)",
- strerror(-err), err);
- }
- }
-
-private:
- virtual void onDispSyncEvent(nsecs_t when) {
- sp<VSyncSource::Callback> callback;
- {
- Mutex::Autolock lock(mCallbackMutex);
- callback = mCallback;
-
- if (mTraceVsync) {
- mValue = (mValue + 1) % 2;
- ATRACE_INT(mVsyncEventLabel.string(), mValue);
- }
- }
-
- if (callback != NULL) {
- callback->onVSyncEvent(when);
- }
- }
-
- const char* const mName;
-
- int mValue;
-
- const bool mTraceVsync;
- const String8 mVsyncOnLabel;
- const String8 mVsyncEventLabel;
-
- DispSync* mDispSync;
-
- Mutex mCallbackMutex; // Protects the following
- sp<VSyncSource::Callback> mCallback;
-
- Mutex mVsyncMutex; // Protects the following
- nsecs_t mPhaseOffset;
- bool mEnabled;
-};
-
-class InjectVSyncSource : public VSyncSource {
-public:
- InjectVSyncSource() {}
-
- virtual ~InjectVSyncSource() {}
-
- virtual void setCallback(const sp<VSyncSource::Callback>& callback) {
- std::lock_guard<std::mutex> lock(mCallbackMutex);
- mCallback = callback;
- }
-
- virtual void onInjectSyncEvent(nsecs_t when) {
- std::lock_guard<std::mutex> lock(mCallbackMutex);
- mCallback->onVSyncEvent(when);
- }
-
- virtual void setVSyncEnabled(bool) {}
- virtual void setPhaseOffset(nsecs_t) {}
-
-private:
- std::mutex mCallbackMutex; // Protects the following
- sp<VSyncSource::Callback> mCallback;
-};
-
-// Do not call property_set on main thread which will be blocked by init
-// Use StartPropertySetThread instead.
-void SurfaceFlinger::init() {
- ALOGI( "SurfaceFlinger's main thread ready to run. "
- "Initializing graphics H/W...");
-
- Mutex::Autolock _l(mStateLock);
-
- // initialize EGL for the default display
- mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- eglInitialize(mEGLDisplay, NULL, NULL);
-
- // start the EventThread
- sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
- vsyncPhaseOffsetNs, true, "app");
- mEventThread = new EventThread(vsyncSrc, *this, false);
- sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
- sfVsyncPhaseOffsetNs, true, "sf");
- mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
- mEventQueue.setEventThread(mSFEventThread);
-
- // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter
- struct sched_param param = {0};
- param.sched_priority = 2;
- if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, ¶m) != 0) {
- ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
- }
- if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, ¶m) != 0) {
- ALOGE("Couldn't set SCHED_FIFO for EventThread");
- }
-
- // Initialize the H/W composer object. There may or may not be an
- // actual hardware composer underneath.
- mHwc.reset(new HWComposer(this,
- *static_cast<HWComposer::EventHandler *>(this)));
-
- // get a RenderEngine for the given display / config (can't fail)
- mRenderEngine = RenderEngine::create(mEGLDisplay,
- mHwc->getVisualID(), 0);
-
- // retrieve the EGL context that was selected/created
- mEGLContext = mRenderEngine->getEGLContext();
-
- LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
- "couldn't create EGLContext");
-
- // initialize our non-virtual displays
- for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
- DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
- // set-up the displays that are already connected
- if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
- // All non-virtual displays are currently considered secure.
- bool isSecure = true;
- createBuiltinDisplayLocked(type);
- wp<IBinder> token = mBuiltinDisplays[i];
-
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer);
-
- sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
- consumer);
- int32_t hwcId = allocateHwcDisplayId(type);
- sp<DisplayDevice> hw = new DisplayDevice(this,
- type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
- fbs, producer,
- mRenderEngine->getEGLConfig(), false);
- if (i > DisplayDevice::DISPLAY_PRIMARY) {
- // FIXME: currently we don't get blank/unblank requests
- // for displays other than the main display, so we always
- // assume a connected display is unblanked.
- ALOGD("marking display %zu as acquired/unblanked", i);
- hw->setPowerMode(HWC_POWER_MODE_NORMAL);
- }
- mDisplays.add(token, hw);
- }
- }
-
- // make the GLContext current so that we can create textures when creating Layers
- // (which may happens before we render something)
- getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext);
-
- mEventControlThread = new EventControlThread(this);
- mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
-
- // set a fake vsync period if there is no HWComposer
- if (mHwc->initCheck() != NO_ERROR) {
- mPrimaryDispSync.setPeriod(16666667);
- }
-
- // initialize our drawing state
- mDrawingState = mCurrentState;
-
- // set initial conditions (e.g. unblank default device)
- initializeDisplays();
-
- mRenderEngine->primeCache();
-
- // Inform native graphics APIs that the present timestamp is NOT supported:
- mStartPropertySetThread = new StartPropertySetThread(false);
- if (mStartPropertySetThread->Start() != NO_ERROR) {
- ALOGE("Run StartPropertySetThread failed!");
- }
-
- ALOGV("Done initializing");
-}
-
-int32_t SurfaceFlinger::allocateHwcDisplayId(DisplayDevice::DisplayType type) {
- return (uint32_t(type) < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) ?
- type : mHwc->allocateDisplayId();
-}
-
-void SurfaceFlinger::startBootAnim() {
- // Start boot animation service by setting a property mailbox
- // if property setting thread is already running, Start() will be just a NOP
- mStartPropertySetThread->Start();
- // Wait until property was set
- if (mStartPropertySetThread->join() != NO_ERROR) {
- ALOGE("Join StartPropertySetThread failed!");
- }
-}
-
-size_t SurfaceFlinger::getMaxTextureSize() const {
- return mRenderEngine->getMaxTextureSize();
-}
-
-size_t SurfaceFlinger::getMaxViewportDims() const {
- return mRenderEngine->getMaxViewportDims();
-}
-
-// ----------------------------------------------------------------------------
-
-bool SurfaceFlinger::authenticateSurfaceTexture(
- const sp<IGraphicBufferProducer>& bufferProducer) const {
- Mutex::Autolock _l(mStateLock);
- return authenticateSurfaceTextureLocked(bufferProducer);
-}
-
-bool SurfaceFlinger::authenticateSurfaceTextureLocked(
- const sp<IGraphicBufferProducer>& bufferProducer) const {
- sp<IBinder> surfaceTextureBinder(IInterface::asBinder(bufferProducer));
- return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0;
-}
-
-status_t SurfaceFlinger::getSupportedFrameTimestamps(
- std::vector<FrameEvent>* outSupported) const {
- *outSupported = {
- FrameEvent::REQUESTED_PRESENT,
- FrameEvent::ACQUIRE,
- FrameEvent::LATCH,
- FrameEvent::FIRST_REFRESH_START,
- FrameEvent::LAST_REFRESH_START,
- FrameEvent::GPU_COMPOSITION_DONE,
- FrameEvent::DEQUEUE_READY,
- FrameEvent::RELEASE,
- };
- return NO_ERROR;
-}
-
-status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
- Vector<DisplayInfo>* configs) {
- if ((configs == NULL) || (display.get() == NULL)) {
- return BAD_VALUE;
- }
-
- int32_t type = getDisplayType(display);
- if (type < 0) return type;
-
- // TODO: Not sure if display density should handled by SF any longer
- class Density {
- static int getDensityFromProperty(char const* propName) {
- char property[PROPERTY_VALUE_MAX];
- int density = 0;
- if (property_get(propName, property, NULL) > 0) {
- density = atoi(property);
- }
- return density;
- }
- public:
- static int getEmuDensity() {
- return getDensityFromProperty("qemu.sf.lcd_density"); }
- static int getBuildDensity() {
- return getDensityFromProperty("ro.sf.lcd_density"); }
- };
-
- configs->clear();
-
- const Vector<HWComposer::DisplayConfig>& hwConfigs =
- getHwComposer().getConfigs(type);
- for (size_t c = 0; c < hwConfigs.size(); ++c) {
- const HWComposer::DisplayConfig& hwConfig = hwConfigs[c];
- DisplayInfo info = DisplayInfo();
-
- float xdpi = hwConfig.xdpi;
- float ydpi = hwConfig.ydpi;
-
- if (type == DisplayDevice::DISPLAY_PRIMARY) {
- // The density of the device is provided by a build property
- float density = Density::getBuildDensity() / 160.0f;
- if (density == 0) {
- // the build doesn't provide a density -- this is wrong!
- // use xdpi instead
- ALOGE("ro.sf.lcd_density must be defined as a build property");
- density = xdpi / 160.0f;
- }
- if (Density::getEmuDensity()) {
- // if "qemu.sf.lcd_density" is specified, it overrides everything
- xdpi = ydpi = density = Density::getEmuDensity();
- density /= 160.0f;
- }
- info.density = density;
-
- // TODO: this needs to go away (currently needed only by webkit)
- sp<const DisplayDevice> hw(getDefaultDisplayDevice());
- info.orientation = hw->getOrientation();
- } else {
- // TODO: where should this value come from?
- static const int TV_DENSITY = 213;
- info.density = TV_DENSITY / 160.0f;
- info.orientation = 0;
- }
-
- info.w = hwConfig.width;
- info.h = hwConfig.height;
- info.xdpi = xdpi;
- info.ydpi = ydpi;
- info.fps = float(1e9 / hwConfig.refresh);
- info.appVsyncOffset = vsyncPhaseOffsetNs;
-
- // This is how far in advance a buffer must be queued for
- // presentation at a given time. If you want a buffer to appear
- // on the screen at time N, you must submit the buffer before
- // (N - presentationDeadline).
- //
- // Normally it's one full refresh period (to give SF a chance to
- // latch the buffer), but this can be reduced by configuring a
- // DispSync offset. Any additional delays introduced by the hardware
- // composer or panel must be accounted for here.
- //
- // We add an additional 1ms to allow for processing time and
- // differences between the ideal and actual refresh rate.
- info.presentationDeadline =
- hwConfig.refresh - sfVsyncPhaseOffsetNs + 1000000;
-
- // All non-virtual displays are currently considered secure.
- info.secure = true;
-
- configs->push_back(info);
- }
-
- return NO_ERROR;
-}
-
-status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>& /* display */,
- DisplayStatInfo* stats) {
- if (stats == NULL) {
- return BAD_VALUE;
- }
-
- // FIXME for now we always return stats for the primary display
- memset(stats, 0, sizeof(*stats));
- stats->vsyncTime = mPrimaryDispSync.computeNextRefresh(0);
- stats->vsyncPeriod = mPrimaryDispSync.getPeriod();
- return NO_ERROR;
-}
-
-int SurfaceFlinger::getActiveConfig(const sp<IBinder>& display) {
- sp<const DisplayDevice> device(getDisplayDevice(display));
- if (device != NULL) {
- return device->getActiveConfig();
- }
- return BAD_VALUE;
-}
-
-void SurfaceFlinger::setActiveConfigInternal(const sp<DisplayDevice>& hw, int mode) {
- ALOGD("Set active config mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
- this);
- int32_t type = hw->getDisplayType();
- int currentMode = hw->getActiveConfig();
-
- if (mode == currentMode) {
- ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode);
- return;
- }
-
- if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
- ALOGW("Trying to set config for virtual display");
- return;
- }
-
- hw->setActiveConfig(mode);
- getHwComposer().setActiveConfig(type, mode);
-}
-
-status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& display, int mode) {
- class MessageSetActiveConfig: public MessageBase {
- SurfaceFlinger& mFlinger;
- sp<IBinder> mDisplay;
- int mMode;
- public:
- MessageSetActiveConfig(SurfaceFlinger& flinger, const sp<IBinder>& disp,
- int mode) :
- mFlinger(flinger), mDisplay(disp) { mMode = mode; }
- virtual bool handler() {
- Vector<DisplayInfo> configs;
- mFlinger.getDisplayConfigs(mDisplay, &configs);
- if (mMode < 0 || mMode >= static_cast<int>(configs.size())) {
- ALOGE("Attempt to set active config = %d for display with %zu configs",
- mMode, configs.size());
- }
- sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
- if (hw == NULL) {
- ALOGE("Attempt to set active config = %d for null display %p",
- mMode, mDisplay.get());
- } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
- ALOGW("Attempt to set active config = %d for virtual display",
- mMode);
- } else {
- mFlinger.setActiveConfigInternal(hw, mMode);
- }
- return true;
- }
- };
- sp<MessageBase> msg = new MessageSetActiveConfig(*this, display, mode);
- postMessageSync(msg);
- return NO_ERROR;
-}
-
-status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& display,
- Vector<android_color_mode_t>* outColorModes) {
- if (outColorModes == nullptr || display.get() == nullptr) {
- return BAD_VALUE;
- }
-
- int32_t type = getDisplayType(display);
- if (type < 0) return type;
-
- std::set<android_color_mode_t> colorModes;
- for (const HWComposer::DisplayConfig& hwConfig : getHwComposer().getConfigs(type)) {
- colorModes.insert(hwConfig.colorMode);
- }
-
- outColorModes->clear();
- std::copy(colorModes.cbegin(), colorModes.cend(), std::back_inserter(*outColorModes));
-
- return NO_ERROR;
-}
-
-android_color_mode_t SurfaceFlinger::getActiveColorMode(const sp<IBinder>& display) {
- if (display.get() == nullptr) return static_cast<android_color_mode_t>(BAD_VALUE);
-
- int32_t type = getDisplayType(display);
- if (type < 0) return static_cast<android_color_mode_t>(type);
-
- return getHwComposer().getColorMode(type);
-}
-
-status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& display,
- android_color_mode_t colorMode) {
- if (display.get() == nullptr || colorMode < 0) {
- return BAD_VALUE;
- }
-
- int32_t type = getDisplayType(display);
- if (type < 0) return type;
- const Vector<HWComposer::DisplayConfig>& hwConfigs = getHwComposer().getConfigs(type);
- HWComposer::DisplayConfig desiredConfig = hwConfigs[getHwComposer().getCurrentConfig(type)];
- desiredConfig.colorMode = colorMode;
- for (size_t c = 0; c < hwConfigs.size(); ++c) {
- const HWComposer::DisplayConfig config = hwConfigs[c];
- if (config == desiredConfig) {
- return setActiveConfig(display, c);
- }
- }
- return BAD_VALUE;
-}
-
-status_t SurfaceFlinger::clearAnimationFrameStats() {
- Mutex::Autolock _l(mStateLock);
- mAnimFrameTracker.clearStats();
- return NO_ERROR;
-}
-
-status_t SurfaceFlinger::getAnimationFrameStats(FrameStats* outStats) const {
- Mutex::Autolock _l(mStateLock);
- mAnimFrameTracker.getStats(outStats);
- return NO_ERROR;
-}
-
-status_t SurfaceFlinger::getHdrCapabilities(const sp<IBinder>& /*display*/,
- HdrCapabilities* outCapabilities) const {
- // HWC1 does not provide HDR capabilities
- *outCapabilities = HdrCapabilities();
- return NO_ERROR;
-}
-
-status_t SurfaceFlinger::enableVSyncInjections(bool enable) {
- if (enable == mInjectVSyncs) {
- return NO_ERROR;
- }
-
- if (enable) {
- mInjectVSyncs = enable;
- ALOGV("VSync Injections enabled");
- if (mVSyncInjector.get() == nullptr) {
- mVSyncInjector = new InjectVSyncSource();
- mInjectorEventThread = new EventThread(mVSyncInjector, *this, false);
- }
- mEventQueue.setEventThread(mInjectorEventThread);
- } else {
- mInjectVSyncs = enable;
- ALOGV("VSync Injections disabled");
- mEventQueue.setEventThread(mSFEventThread);
- mVSyncInjector.clear();
- }
- return NO_ERROR;
-}
-
-status_t SurfaceFlinger::injectVSync(nsecs_t when) {
- if (!mInjectVSyncs) {
- ALOGE("VSync Injections not enabled");
- return BAD_VALUE;
- }
- if (mInjectVSyncs && mInjectorEventThread.get() != nullptr) {
- ALOGV("Injecting VSync inside SurfaceFlinger");
- mVSyncInjector->onInjectSyncEvent(when);
- }
- return NO_ERROR;
-}
-
-status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const {
- IPCThreadState* ipc = IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
- if ((uid != AID_SHELL) &&
- !PermissionCache::checkPermission(sDump, pid, uid)) {
- ALOGE("Layer debug info permission denied for pid=%d, uid=%d", pid, uid);
- return PERMISSION_DENIED;
- }
-
- // Try to acquire a lock for 1s, fail gracefully
- status_t err = mStateLock.timedLock(s2ns(1));
- bool locked = (err == NO_ERROR);
- if (!locked) {
- ALOGE("LayerDebugInfo: SurfaceFlinger unresponsive (%s [%d]) - exit", strerror(-err), err);
- return TIMED_OUT;
- }
-
- outLayers->clear();
- mCurrentState.traverseInZOrder([&](Layer* layer) {
- outLayers->push_back(layer->getLayerDebugInfo());
- });
-
- mStateLock.unlock();
-
- return NO_ERROR;
-}
-
-// ----------------------------------------------------------------------------
-
-sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
- ISurfaceComposer::VsyncSource vsyncSource) {
- if (vsyncSource == eVsyncSourceSurfaceFlinger) {
- return mSFEventThread->createEventConnection();
- } else {
- return mEventThread->createEventConnection();
- }
-}
-
-// ----------------------------------------------------------------------------
-
-void SurfaceFlinger::waitForEvent() {
- mEventQueue.waitMessage();
-}
-
-void SurfaceFlinger::signalTransaction() {
- mEventQueue.invalidate();
-}
-
-void SurfaceFlinger::signalLayerUpdate() {
- mEventQueue.invalidate();
-}
-
-void SurfaceFlinger::signalRefresh() {
- mEventQueue.refresh();
-}
-
-status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
- nsecs_t reltime, uint32_t /* flags */) {
- return mEventQueue.postMessage(msg, reltime);
-}
-
-status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
- nsecs_t reltime, uint32_t /* flags */) {
- status_t res = mEventQueue.postMessage(msg, reltime);
- if (res == NO_ERROR) {
- msg->wait();
- }
- return res;
-}
-
-void SurfaceFlinger::run() {
- do {
- waitForEvent();
- } while (true);
-}
-
-void SurfaceFlinger::enableHardwareVsync() {
- Mutex::Autolock _l(mHWVsyncLock);
- if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
- mPrimaryDispSync.beginResync();
- //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
- mEventControlThread->setVsyncEnabled(true);
- mPrimaryHWVsyncEnabled = true;
- }
-}
-
-void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) {
- Mutex::Autolock _l(mHWVsyncLock);
-
- if (makeAvailable) {
- mHWVsyncAvailable = true;
- } else if (!mHWVsyncAvailable) {
- // Hardware vsync is not currently available, so abort the resync
- // attempt for now
- return;
- }
-
- const nsecs_t period =
- getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
-
- mPrimaryDispSync.reset();
- mPrimaryDispSync.setPeriod(period);
-
- if (!mPrimaryHWVsyncEnabled) {
- mPrimaryDispSync.beginResync();
- //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
- mEventControlThread->setVsyncEnabled(true);
- mPrimaryHWVsyncEnabled = true;
- }
-}
-
-void SurfaceFlinger::disableHardwareVsync(bool makeUnavailable) {
- Mutex::Autolock _l(mHWVsyncLock);
- if (mPrimaryHWVsyncEnabled) {
- //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, false);
- mEventControlThread->setVsyncEnabled(false);
- mPrimaryDispSync.endResync();
- mPrimaryHWVsyncEnabled = false;
- }
- if (makeUnavailable) {
- mHWVsyncAvailable = false;
- }
-}
-
-void SurfaceFlinger::resyncWithRateLimit() {
- static constexpr nsecs_t kIgnoreDelay = ms2ns(500);
- if (systemTime() - mLastSwapTime > kIgnoreDelay) {
- resyncToHardwareVsync(false);
- }
-}
-
-void SurfaceFlinger::onVSyncReceived(HWComposer* /*composer*/, int type,
- nsecs_t timestamp) {
- bool needsHwVsync = false;
-
- { // Scope for the lock
- Mutex::Autolock _l(mHWVsyncLock);
- if (type == 0 && mPrimaryHWVsyncEnabled) {
- needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
- }
- }
-
- if (needsHwVsync) {
- enableHardwareVsync();
- } else {
- disableHardwareVsync(false);
- }
-}
-
-void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) {
- std::lock_guard<std::mutex> lock(mCompositorTimingLock);
- *compositorTiming = mCompositorTiming;
-}
-
-void SurfaceFlinger::onHotplugReceived(HWComposer* /*composer*/, int type, bool connected) {
- if (mEventThread == NULL) {
- // This is a temporary workaround for b/7145521. A non-null pointer
- // does not mean EventThread has finished initializing, so this
- // is not a correct fix.
- ALOGW("WARNING: EventThread not started, ignoring hotplug");
- return;
- }
-
- if (uint32_t(type) < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
- Mutex::Autolock _l(mStateLock);
- if (connected) {
- createBuiltinDisplayLocked((DisplayDevice::DisplayType)type);
- } else {
- mCurrentState.displays.removeItem(mBuiltinDisplays[type]);
- mBuiltinDisplays[type].clear();
- }
- setTransactionFlags(eDisplayTransactionNeeded);
-
- // Defer EventThread notification until SF has updated mDisplays.
- }
-}
-
-void SurfaceFlinger::onInvalidateReceived(HWComposer* /*composer*/) {
- repaintEverything();
-}
-
-void SurfaceFlinger::eventControl(int disp, int event, int enabled) {
- ATRACE_CALL();
- getHwComposer().eventControl(disp, event, enabled);
-}
-
-void SurfaceFlinger::onMessageReceived(int32_t what) {
- ATRACE_CALL();
- switch (what) {
- case MessageQueue::INVALIDATE: {
- bool refreshNeeded = handleMessageTransaction();
- refreshNeeded |= handleMessageInvalidate();
- refreshNeeded |= mRepaintEverything;
- if (refreshNeeded) {
- // Signal a refresh if a transaction modified the window state,
- // a new buffer was latched, or if HWC has requested a full
- // repaint
- signalRefresh();
- }
- break;
- }
- case MessageQueue::REFRESH: {
- handleMessageRefresh();
- break;
- }
- }
-}
-
-bool SurfaceFlinger::handleMessageTransaction() {
- uint32_t transactionFlags = peekTransactionFlags();
- if (transactionFlags) {
- handleTransaction(transactionFlags);
- return true;
- }
- return false;
-}
-
-bool SurfaceFlinger::handleMessageInvalidate() {
- ATRACE_CALL();
- return handlePageFlip();
-}
-
-void SurfaceFlinger::handleMessageRefresh() {
- ATRACE_CALL();
-
- nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
- preComposition(refreshStartTime);
- rebuildLayerStacks();
- setUpHWComposer();
- doDebugFlashRegions();
- doComposition();
- postComposition(refreshStartTime);
-}
-
-void SurfaceFlinger::doDebugFlashRegions()
-{
- // is debugging enabled
- if (CC_LIKELY(!mDebugRegion))
- return;
-
- const bool repaintEverything = mRepaintEverything;
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- const sp<DisplayDevice>& hw(mDisplays[dpy]);
- if (hw->isDisplayOn()) {
- // transform the dirty region into this screen's coordinate space
- const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
- if (!dirtyRegion.isEmpty()) {
- // redraw the whole screen
- doComposeSurfaces(hw, Region(hw->bounds()));
-
- // and draw the dirty region
- const int32_t height = hw->getHeight();
- RenderEngine& engine(getRenderEngine());
- engine.fillRegionWithColor(dirtyRegion, height, 1, 0, 1, 1);
-
- hw->compositionComplete();
- hw->swapBuffers(getHwComposer());
- }
- }
- }
-
- postFramebuffer();
-
- if (mDebugRegion > 1) {
- usleep(mDebugRegion * 1000);
- }
-
- HWComposer& hwc(getHwComposer());
- if (hwc.initCheck() == NO_ERROR) {
- status_t err = hwc.prepare();
- ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
- }
-}
-
-void SurfaceFlinger::preComposition(nsecs_t refreshStartTime)
-{
- bool needExtraInvalidate = false;
- mDrawingState.traverseInZOrder([&](Layer* layer) {
- if (layer->onPreComposition(refreshStartTime)) {
- needExtraInvalidate = true;
- }
- });
-
- if (needExtraInvalidate) {
- signalLayerUpdate();
- }
-}
-
-void SurfaceFlinger::updateCompositorTiming(
- nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime,
- std::shared_ptr<FenceTime>& presentFenceTime) {
- // Update queue of past composite+present times and determine the
- // most recently known composite to present latency.
- mCompositePresentTimes.push({compositeTime, presentFenceTime});
- nsecs_t compositeToPresentLatency = -1;
- while (!mCompositePresentTimes.empty()) {
- CompositePresentTime& cpt = mCompositePresentTimes.front();
- // Cached values should have been updated before calling this method,
- // which helps avoid duplicate syscalls.
- nsecs_t displayTime = cpt.display->getCachedSignalTime();
- if (displayTime == Fence::SIGNAL_TIME_PENDING) {
- break;
- }
- compositeToPresentLatency = displayTime - cpt.composite;
- mCompositePresentTimes.pop();
- }
-
- // Don't let mCompositePresentTimes grow unbounded, just in case.
- while (mCompositePresentTimes.size() > 16) {
- mCompositePresentTimes.pop();
- }
-
- setCompositorTimingSnapped(
- vsyncPhase, vsyncInterval, compositeToPresentLatency);
-}
-
-void SurfaceFlinger::setCompositorTimingSnapped(nsecs_t vsyncPhase,
- nsecs_t vsyncInterval, nsecs_t compositeToPresentLatency) {
- // Integer division and modulo round toward 0 not -inf, so we need to
- // treat negative and positive offsets differently.
- nsecs_t idealLatency = (sfVsyncPhaseOffsetNs > 0) ?
- (vsyncInterval - (sfVsyncPhaseOffsetNs % vsyncInterval)) :
- ((-sfVsyncPhaseOffsetNs) % vsyncInterval);
-
- // Just in case sfVsyncPhaseOffsetNs == -vsyncInterval.
- if (idealLatency <= 0) {
- idealLatency = vsyncInterval;
- }
-
- // Snap the latency to a value that removes scheduling jitter from the
- // composition and present times, which often have >1ms of jitter.
- // Reducing jitter is important if an app attempts to extrapolate
- // something (such as user input) to an accurate diasplay time.
- // Snapping also allows an app to precisely calculate sfVsyncPhaseOffsetNs
- // with (presentLatency % interval).
- nsecs_t bias = vsyncInterval / 2;
- int64_t extraVsyncs =
- (compositeToPresentLatency - idealLatency + bias) / vsyncInterval;
- nsecs_t snappedCompositeToPresentLatency = (extraVsyncs > 0) ?
- idealLatency + (extraVsyncs * vsyncInterval) : idealLatency;
-
- std::lock_guard<std::mutex> lock(mCompositorTimingLock);
- mCompositorTiming.deadline = vsyncPhase - idealLatency;
- mCompositorTiming.interval = vsyncInterval;
- mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
-}
-
-void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
-{
- const HWComposer& hwc = getHwComposer();
- const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
-
- mGlCompositionDoneTimeline.updateSignalTimes();
- std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
- if (getHwComposer().hasGlesComposition(hw->getHwcDisplayId())) {
- glCompositionDoneFenceTime =
- std::make_shared<FenceTime>(hw->getClientTargetAcquireFence());
- mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime);
- } else {
- glCompositionDoneFenceTime = FenceTime::NO_FENCE;
- }
-
- mDisplayTimeline.updateSignalTimes();
- sp<Fence> retireFence = mHwc->getDisplayFence(HWC_DISPLAY_PRIMARY);
- auto retireFenceTime = std::make_shared<FenceTime>(retireFence);
- mDisplayTimeline.push(retireFenceTime);
-
- nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0);
- nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod();
-
- // We use the refreshStartTime which might be sampled a little later than
- // when we started doing work for this frame, but that should be okay
- // since updateCompositorTiming has snapping logic.
- updateCompositorTiming(
- vsyncPhase, vsyncInterval, refreshStartTime, retireFenceTime);
- CompositorTiming compositorTiming;
- {
- std::lock_guard<std::mutex> lock(mCompositorTimingLock);
- compositorTiming = mCompositorTiming;
- }
-
- mDrawingState.traverseInZOrder([&](Layer* layer) {
- // TODO(brianderson): The retire fence is incorrectly passed in as the
- // present fence. Fix this if this file lives on.
- bool frameLatched = layer->onPostComposition(glCompositionDoneFenceTime,
- retireFenceTime, compositorTiming);
- if (frameLatched) {
- recordBufferingStats(layer->getName().string(),
- layer->getOccupancyHistory(false));
- }
- });
-
- if (retireFence->isValid()) {
- if (mPrimaryDispSync.addPresentFence(retireFenceTime)) {
- enableHardwareVsync();
- } else {
- disableHardwareVsync(false);
- }
- }
-
- if (!hasSyncFramework) {
- if (hw->isDisplayOn()) {
- enableHardwareVsync();
- }
- }
-
- if (mAnimCompositionPending) {
- mAnimCompositionPending = false;
-
- if (retireFenceTime->isValid()) {
- mAnimFrameTracker.setActualPresentFence(std::move(retireFenceTime));
- } else {
- // The HWC doesn't support present fences, so use the refresh
- // timestamp instead.
- nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
- mAnimFrameTracker.setActualPresentTime(presentTime);
- }
- mAnimFrameTracker.advanceFrame();
- }
-
- if (hw->getPowerMode() == HWC_POWER_MODE_OFF) {
- return;
- }
-
- nsecs_t currentTime = systemTime();
- if (mHasPoweredOff) {
- mHasPoweredOff = false;
- } else {
- nsecs_t period = mPrimaryDispSync.getPeriod();
- nsecs_t elapsedTime = currentTime - mLastSwapTime;
- size_t numPeriods = static_cast<size_t>(elapsedTime / period);
- if (numPeriods < NUM_BUCKETS - 1) {
- mFrameBuckets[numPeriods] += elapsedTime;
- } else {
- mFrameBuckets[NUM_BUCKETS - 1] += elapsedTime;
- }
- mTotalTime += elapsedTime;
- }
- mLastSwapTime = currentTime;
-}
-
-void SurfaceFlinger::rebuildLayerStacks() {
- // rebuild the visible layer list per screen
- if (CC_UNLIKELY(mVisibleRegionsDirty)) {
- ATRACE_CALL();
- mVisibleRegionsDirty = false;
- invalidateHwcGeometry();
-
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- Region opaqueRegion;
- Region dirtyRegion;
- Vector< sp<Layer> > layersSortedByZ;
- const sp<DisplayDevice>& hw(mDisplays[dpy]);
- const Transform& tr(hw->getTransform());
- const Rect bounds(hw->getBounds());
- if (hw->isDisplayOn()) {
- computeVisibleRegions(hw, dirtyRegion, opaqueRegion);
-
- mDrawingState.traverseInZOrder([&](Layer* layer) {
- if (layer->getLayerStack() == hw->getLayerStack()) {
- Region drawRegion(tr.transform(
- layer->visibleNonTransparentRegion));
- drawRegion.andSelf(bounds);
- if (!drawRegion.isEmpty()) {
- layersSortedByZ.add(layer);
- }
- }
- });
- }
- hw->setVisibleLayersSortedByZ(layersSortedByZ);
- hw->undefinedRegion.set(bounds);
- hw->undefinedRegion.subtractSelf(tr.transform(opaqueRegion));
- hw->dirtyRegion.orSelf(dirtyRegion);
- }
- }
-}
-
-void SurfaceFlinger::setUpHWComposer() {
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- bool dirty = !mDisplays[dpy]->getDirtyRegion(false).isEmpty();
- bool empty = mDisplays[dpy]->getVisibleLayersSortedByZ().size() == 0;
- bool wasEmpty = !mDisplays[dpy]->lastCompositionHadVisibleLayers;
-
- // If nothing has changed (!dirty), don't recompose.
- // If something changed, but we don't currently have any visible layers,
- // and didn't when we last did a composition, then skip it this time.
- // The second rule does two things:
- // - When all layers are removed from a display, we'll emit one black
- // frame, then nothing more until we get new layers.
- // - When a display is created with a private layer stack, we won't
- // emit any black frames until a layer is added to the layer stack.
- bool mustRecompose = dirty && !(empty && wasEmpty);
-
- ALOGV_IF(mDisplays[dpy]->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL,
- "dpy[%zu]: %s composition (%sdirty %sempty %swasEmpty)", dpy,
- mustRecompose ? "doing" : "skipping",
- dirty ? "+" : "-",
- empty ? "+" : "-",
- wasEmpty ? "+" : "-");
-
- mDisplays[dpy]->beginFrame(mustRecompose);
-
- if (mustRecompose) {
- mDisplays[dpy]->lastCompositionHadVisibleLayers = !empty;
- }
- }
-
- HWComposer& hwc(getHwComposer());
- if (hwc.initCheck() == NO_ERROR) {
- // build the h/w work list
- if (CC_UNLIKELY(mHwWorkListDirty)) {
- mHwWorkListDirty = false;
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- sp<const DisplayDevice> hw(mDisplays[dpy]);
- const int32_t id = hw->getHwcDisplayId();
- if (id >= 0) {
- const Vector< sp<Layer> >& currentLayers(
- hw->getVisibleLayersSortedByZ());
- const size_t count = currentLayers.size();
- if (hwc.createWorkList(id, count) == NO_ERROR) {
- HWComposer::LayerListIterator cur = hwc.begin(id);
- const HWComposer::LayerListIterator end = hwc.end(id);
- for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
- const sp<Layer>& layer(currentLayers[i]);
- layer->setGeometry(hw, *cur);
- if (mDebugDisableHWC || mDebugRegion || mDaltonize || mHasColorMatrix) {
- cur->setSkip(true);
- }
- }
- }
- }
- }
- }
-
- // set the per-frame data
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- sp<const DisplayDevice> hw(mDisplays[dpy]);
- const int32_t id = hw->getHwcDisplayId();
- if (id >= 0) {
- const Vector< sp<Layer> >& currentLayers(
- hw->getVisibleLayersSortedByZ());
- const size_t count = currentLayers.size();
- HWComposer::LayerListIterator cur = hwc.begin(id);
- const HWComposer::LayerListIterator end = hwc.end(id);
- for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
- /*
- * update the per-frame h/w composer data for each layer
- * and build the transparent region of the FB
- */
- const sp<Layer>& layer(currentLayers[i]);
- layer->setPerFrameData(hw, *cur);
- }
- }
- }
-
- // If possible, attempt to use the cursor overlay on each display.
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- sp<const DisplayDevice> hw(mDisplays[dpy]);
- const int32_t id = hw->getHwcDisplayId();
- if (id >= 0) {
- const Vector< sp<Layer> >& currentLayers(
- hw->getVisibleLayersSortedByZ());
- const size_t count = currentLayers.size();
- HWComposer::LayerListIterator cur = hwc.begin(id);
- const HWComposer::LayerListIterator end = hwc.end(id);
- for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
- const sp<Layer>& layer(currentLayers[i]);
- if (layer->isPotentialCursor()) {
- cur->setIsCursorLayerHint();
- break;
- }
- }
- }
- }
-
- status_t err = hwc.prepare();
- ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
-
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- sp<const DisplayDevice> hw(mDisplays[dpy]);
- hw->prepareFrame(hwc);
- }
- }
-}
-
-void SurfaceFlinger::doComposition() {
- ATRACE_CALL();
- const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- const sp<DisplayDevice>& hw(mDisplays[dpy]);
- if (hw->isDisplayOn()) {
- // transform the dirty region into this screen's coordinate space
- const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
-
- // repaint the framebuffer (if needed)
- doDisplayComposition(hw, dirtyRegion);
-
- hw->dirtyRegion.clear();
- hw->flip(hw->swapRegion);
- hw->swapRegion.clear();
- }
- // inform the h/w that we're done compositing
- hw->compositionComplete();
- }
- postFramebuffer();
-}
-
-void SurfaceFlinger::postFramebuffer()
-{
- ATRACE_CALL();
-
- const nsecs_t now = systemTime();
- mDebugInSwapBuffers = now;
-
- HWComposer& hwc(getHwComposer());
- if (hwc.initCheck() == NO_ERROR) {
- if (!hwc.supportsFramebufferTarget()) {
- // EGL spec says:
- // "surface must be bound to the calling thread's current context,
- // for the current rendering API."
- getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
- }
- hwc.commit();
- }
-
- // make the default display current because the VirtualDisplayDevice code cannot
- // deal with dequeueBuffer() being called outside of the composition loop; however
- // the code below can call glFlush() which is allowed (and does in some case) call
- // dequeueBuffer().
- getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
-
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- sp<const DisplayDevice> hw(mDisplays[dpy]);
- const Vector< sp<Layer> >& currentLayers(hw->getVisibleLayersSortedByZ());
- hw->onSwapBuffersCompleted(hwc);
- const size_t count = currentLayers.size();
- int32_t id = hw->getHwcDisplayId();
- if (id >=0 && hwc.initCheck() == NO_ERROR) {
- HWComposer::LayerListIterator cur = hwc.begin(id);
- const HWComposer::LayerListIterator end = hwc.end(id);
- for (size_t i = 0; cur != end && i < count; ++i, ++cur) {
- currentLayers[i]->onLayerDisplayed(hw, &*cur);
- }
- } else {
- for (size_t i = 0; i < count; i++) {
- currentLayers[i]->onLayerDisplayed(hw, NULL);
- }
- }
- }
-
- mLastSwapBufferTime = systemTime() - now;
- mDebugInSwapBuffers = 0;
-
- uint32_t flipCount = getDefaultDisplayDevice()->getPageFlipCount();
- if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
- logFrameStats();
- }
-}
-
-void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
-{
- ATRACE_CALL();
-
- // here we keep a copy of the drawing state (that is the state that's
- // going to be overwritten by handleTransactionLocked()) outside of
- // mStateLock so that the side-effects of the State assignment
- // don't happen with mStateLock held (which can cause deadlocks).
- State drawingState(mDrawingState);
-
- Mutex::Autolock _l(mStateLock);
- const nsecs_t now = systemTime();
- mDebugInTransaction = now;
-
- // Here we're guaranteed that some transaction flags are set
- // so we can call handleTransactionLocked() unconditionally.
- // We call getTransactionFlags(), which will also clear the flags,
- // with mStateLock held to guarantee that mCurrentState won't change
- // until the transaction is committed.
-
- transactionFlags = getTransactionFlags(eTransactionMask);
- handleTransactionLocked(transactionFlags);
-
- mLastTransactionTime = systemTime() - now;
- mDebugInTransaction = 0;
- invalidateHwcGeometry();
- // here the transaction has been committed
-}
-
-void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
-{
- // Notify all layers of available frames
- mCurrentState.traverseInZOrder([](Layer* layer) {
- layer->notifyAvailableFrames();
- });
-
- /*
- * Traversal of the children
- * (perform the transaction for each of them if needed)
- */
-
- if (transactionFlags & eTraversalNeeded) {
- mCurrentState.traverseInZOrder([&](Layer* layer) {
- uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
- if (!trFlags) return;
-
- const uint32_t flags = layer->doTransaction(0);
- if (flags & Layer::eVisibleRegion)
- mVisibleRegionsDirty = true;
- });
- }
-
- /*
- * Perform display own transactions if needed
- */
-
- if (transactionFlags & eDisplayTransactionNeeded) {
- // here we take advantage of Vector's copy-on-write semantics to
- // improve performance by skipping the transaction entirely when
- // know that the lists are identical
- const KeyedVector< wp<IBinder>, DisplayDeviceState>& curr(mCurrentState.displays);
- const KeyedVector< wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays);
- if (!curr.isIdenticalTo(draw)) {
- mVisibleRegionsDirty = true;
- const size_t cc = curr.size();
- size_t dc = draw.size();
-
- // find the displays that were removed
- // (ie: in drawing state but not in current state)
- // also handle displays that changed
- // (ie: displays that are in both lists)
- for (size_t i=0 ; i<dc ; i++) {
- const ssize_t j = curr.indexOfKey(draw.keyAt(i));
- if (j < 0) {
- // in drawing state but not in current state
- if (!draw[i].isMainDisplay()) {
- // Call makeCurrent() on the primary display so we can
- // be sure that nothing associated with this display
- // is current.
- const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDeviceLocked());
- defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext);
- sp<DisplayDevice> hw(getDisplayDeviceLocked(draw.keyAt(i)));
- if (hw != NULL)
- hw->disconnect(getHwComposer());
- if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES)
- mEventThread->onHotplugReceived(draw[i].type, false);
- mDisplays.removeItem(draw.keyAt(i));
- } else {
- ALOGW("trying to remove the main display");
- }
- } else {
- // this display is in both lists. see if something changed.
- const DisplayDeviceState& state(curr[j]);
- const wp<IBinder>& display(curr.keyAt(j));
- const sp<IBinder> state_binder = IInterface::asBinder(state.surface);
- const sp<IBinder> draw_binder = IInterface::asBinder(draw[i].surface);
- if (state_binder != draw_binder) {
- // changing the surface is like destroying and
- // recreating the DisplayDevice, so we just remove it
- // from the drawing state, so that it get re-added
- // below.
- sp<DisplayDevice> hw(getDisplayDeviceLocked(display));
- if (hw != NULL)
- hw->disconnect(getHwComposer());
- mDisplays.removeItem(display);
- mDrawingState.displays.removeItemsAt(i);
- dc--; i--;
- // at this point we must loop to the next item
- continue;
- }
-
- const sp<DisplayDevice> disp(getDisplayDeviceLocked(display));
- if (disp != NULL) {
- if (state.layerStack != draw[i].layerStack) {
- disp->setLayerStack(state.layerStack);
- }
- if ((state.orientation != draw[i].orientation)
- || (state.viewport != draw[i].viewport)
- || (state.frame != draw[i].frame))
- {
- disp->setProjection(state.orientation,
- state.viewport, state.frame);
- }
- if (state.width != draw[i].width || state.height != draw[i].height) {
- disp->setDisplaySize(state.width, state.height);
- }
- }
- }
- }
-
- // find displays that were added
- // (ie: in current state but not in drawing state)
- for (size_t i=0 ; i<cc ; i++) {
- if (draw.indexOfKey(curr.keyAt(i)) < 0) {
- const DisplayDeviceState& state(curr[i]);
-
- sp<DisplaySurface> dispSurface;
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferProducer> bqProducer;
- sp<IGraphicBufferConsumer> bqConsumer;
- BufferQueue::createBufferQueue(&bqProducer, &bqConsumer);
-
- int32_t hwcDisplayId = -1;
- if (state.isVirtualDisplay()) {
- // Virtual displays without a surface are dormant:
- // they have external state (layer stack, projection,
- // etc.) but no internal state (i.e. a DisplayDevice).
- if (state.surface != NULL) {
-
- int width = 0;
- int status = state.surface->query(
- NATIVE_WINDOW_WIDTH, &width);
- ALOGE_IF(status != NO_ERROR,
- "Unable to query width (%d)", status);
- int height = 0;
- status = state.surface->query(
- NATIVE_WINDOW_HEIGHT, &height);
- ALOGE_IF(status != NO_ERROR,
- "Unable to query height (%d)", status);
- if (mUseHwcVirtualDisplays &&
- (SurfaceFlinger::maxVirtualDisplaySize == 0 ||
- (width <= static_cast<int>(SurfaceFlinger::maxVirtualDisplaySize) &&
- height <= static_cast<int>(SurfaceFlinger::maxVirtualDisplaySize)))) {
- hwcDisplayId = allocateHwcDisplayId(state.type);
- }
-
- sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface(
- *mHwc, hwcDisplayId, state.surface,
- bqProducer, bqConsumer, state.displayName);
-
- dispSurface = vds;
- producer = vds;
- }
- } else {
- ALOGE_IF(state.surface!=NULL,
- "adding a supported display, but rendering "
- "surface is provided (%p), ignoring it",
- state.surface.get());
- hwcDisplayId = allocateHwcDisplayId(state.type);
- // for supported (by hwc) displays we provide our
- // own rendering surface
- dispSurface = new FramebufferSurface(*mHwc, state.type,
- bqConsumer);
- producer = bqProducer;
- }
-
- const wp<IBinder>& display(curr.keyAt(i));
- if (dispSurface != NULL) {
- sp<DisplayDevice> hw = new DisplayDevice(this,
- state.type, hwcDisplayId,
- mHwc->getFormat(hwcDisplayId), state.isSecure,
- display, dispSurface, producer,
- mRenderEngine->getEGLConfig(), false);
- hw->setLayerStack(state.layerStack);
- hw->setProjection(state.orientation,
- state.viewport, state.frame);
- hw->setDisplayName(state.displayName);
- mDisplays.add(display, hw);
- if (state.isVirtualDisplay()) {
- if (hwcDisplayId >= 0) {
- mHwc->setVirtualDisplayProperties(hwcDisplayId,
- hw->getWidth(), hw->getHeight(),
- hw->getFormat());
- }
- } else {
- mEventThread->onHotplugReceived(state.type, true);
- }
- }
- }
- }
- }
- }
-
- if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) {
- // The transform hint might have changed for some layers
- // (either because a display has changed, or because a layer
- // as changed).
- //
- // Walk through all the layers in currentLayers,
- // and update their transform hint.
- //
- // If a layer is visible only on a single display, then that
- // display is used to calculate the hint, otherwise we use the
- // default display.
- //
- // NOTE: we do this here, rather than in rebuildLayerStacks() so that
- // the hint is set before we acquire a buffer from the surface texture.
- //
- // NOTE: layer transactions have taken place already, so we use their
- // drawing state. However, SurfaceFlinger's own transaction has not
- // happened yet, so we must use the current state layer list
- // (soon to become the drawing state list).
- //
- sp<const DisplayDevice> disp;
- uint32_t currentlayerStack = 0;
- bool first = true;
- mCurrentState.traverseInZOrder([&](Layer* layer) {
- // NOTE: we rely on the fact that layers are sorted by
- // layerStack first (so we don't have to traverse the list
- // of displays for every layer).
- uint32_t layerStack = layer->getLayerStack();
- if (first || currentlayerStack != layerStack) {
- currentlayerStack = layerStack;
- // figure out if this layerstack is mirrored
- // (more than one display) if so, pick the default display,
- // if not, pick the only display it's on.
- disp.clear();
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- sp<const DisplayDevice> hw(mDisplays[dpy]);
- if (hw->getLayerStack() == currentlayerStack) {
- if (disp == NULL) {
- disp = hw;
- } else {
- disp = NULL;
- break;
- }
- }
- }
- }
- if (disp == NULL) {
- // NOTE: TEMPORARY FIX ONLY. Real fix should cause layers to
- // redraw after transform hint changes. See bug 8508397.
-
- // could be null when this layer is using a layerStack
- // that is not visible on any display. Also can occur at
- // screen off/on times.
- disp = getDefaultDisplayDeviceLocked();
- }
- layer->updateTransformHint(disp);
-
- first = false;
- });
- }
-
-
- /*
- * Perform our own transaction if needed
- */
-
- if (mLayersAdded) {
- mLayersAdded = false;
- // Layers have been added.
- mVisibleRegionsDirty = true;
- }
-
- // some layers might have been removed, so
- // we need to update the regions they're exposing.
- if (mLayersRemoved) {
- mLayersRemoved = false;
- mVisibleRegionsDirty = true;
- mDrawingState.traverseInZOrder([&](Layer* layer) {
- if (mLayersPendingRemoval.indexOf(layer) >= 0) {
- // this layer is not visible anymore
- // TODO: we could traverse the tree from front to back and
- // compute the actual visible region
- // TODO: we could cache the transformed region
- Region visibleReg;
- visibleReg.set(layer->computeScreenBounds());
- invalidateLayerStack(layer, visibleReg);
- }
- });
- }
-
- commitTransaction();
-
- updateCursorAsync();
-}
-
-void SurfaceFlinger::updateCursorAsync()
-{
- HWComposer& hwc(getHwComposer());
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- sp<const DisplayDevice> hw(mDisplays[dpy]);
- const int32_t id = hw->getHwcDisplayId();
- if (id < 0) {
- continue;
- }
- const Vector< sp<Layer> >& currentLayers(
- hw->getVisibleLayersSortedByZ());
- const size_t count = currentLayers.size();
- HWComposer::LayerListIterator cur = hwc.begin(id);
- const HWComposer::LayerListIterator end = hwc.end(id);
- for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
- if (cur->getCompositionType() != HWC_CURSOR_OVERLAY) {
- continue;
- }
- const sp<Layer>& layer(currentLayers[i]);
- Rect cursorPos = layer->getPosition(hw);
- hwc.setCursorPositionAsync(id, cursorPos);
- break;
- }
- }
-}
-
-void SurfaceFlinger::commitTransaction()
-{
- if (!mLayersPendingRemoval.isEmpty()) {
- // Notify removed layers now that they can't be drawn from
- for (const auto& l : mLayersPendingRemoval) {
- recordBufferingStats(l->getName().string(),
- l->getOccupancyHistory(true));
- l->onRemoved();
- }
- mLayersPendingRemoval.clear();
- }
-
- // If this transaction is part of a window animation then the next frame
- // we composite should be considered an animation as well.
- mAnimCompositionPending = mAnimTransactionPending;
-
- mDrawingState = mCurrentState;
- mDrawingState.traverseInZOrder([](Layer* layer) {
- layer->commitChildList();
- });
- mTransactionPending = false;
- mAnimTransactionPending = false;
- mTransactionCV.broadcast();
-}
-
-void SurfaceFlinger::computeVisibleRegions(const sp<const DisplayDevice>& displayDevice,
- Region& outDirtyRegion, Region& outOpaqueRegion)
-{
- ATRACE_CALL();
-
- Region aboveOpaqueLayers;
- Region aboveCoveredLayers;
- Region dirty;
-
- outDirtyRegion.clear();
-
- mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
- // start with the whole surface at its current location
- const Layer::State& s(layer->getDrawingState());
-
- // only consider the layers on the given layer stack
- if (layer->getLayerStack() != displayDevice->getLayerStack())
- return;
-
- /*
- * opaqueRegion: area of a surface that is fully opaque.
- */
- Region opaqueRegion;
-
- /*
- * visibleRegion: area of a surface that is visible on screen
- * and not fully transparent. This is essentially the layer's
- * footprint minus the opaque regions above it.
- * Areas covered by a translucent surface are considered visible.
- */
- Region visibleRegion;
-
- /*
- * coveredRegion: area of a surface that is covered by all
- * visible regions above it (which includes the translucent areas).
- */
- Region coveredRegion;
-
- /*
- * transparentRegion: area of a surface that is hinted to be completely
- * transparent. This is only used to tell when the layer has no visible
- * non-transparent regions and can be removed from the layer list. It
- * does not affect the visibleRegion of this layer or any layers
- * beneath it. The hint may not be correct if apps don't respect the
- * SurfaceView restrictions (which, sadly, some don't).
- */
- Region transparentRegion;
-
-
- // handle hidden surfaces by setting the visible region to empty
- if (CC_LIKELY(layer->isVisible())) {
- const bool translucent = !layer->isOpaque(s);
- Rect bounds(layer->computeScreenBounds());
- visibleRegion.set(bounds);
- Transform tr = layer->getTransform();
- if (!visibleRegion.isEmpty()) {
- // Remove the transparent area from the visible region
- if (translucent) {
- if (tr.preserveRects()) {
- // transform the transparent region
- transparentRegion = tr.transform(s.activeTransparentRegion);
- } else {
- // transformation too complex, can't do the
- // transparent region optimization.
- transparentRegion.clear();
- }
- }
-
- // compute the opaque region
- const int32_t layerOrientation = tr.getOrientation();
- if (s.alpha==255 && !translucent &&
- ((layerOrientation & Transform::ROT_INVALID) == false)) {
- // the opaque region is the layer's footprint
- opaqueRegion = visibleRegion;
- }
- }
- }
-
- // Clip the covered region to the visible region
- coveredRegion = aboveCoveredLayers.intersect(visibleRegion);
-
- // Update aboveCoveredLayers for next (lower) layer
- aboveCoveredLayers.orSelf(visibleRegion);
-
- // subtract the opaque region covered by the layers above us
- visibleRegion.subtractSelf(aboveOpaqueLayers);
-
- // compute this layer's dirty region
- if (layer->contentDirty) {
- // we need to invalidate the whole region
- dirty = visibleRegion;
- // as well, as the old visible region
- dirty.orSelf(layer->visibleRegion);
- layer->contentDirty = false;
- } else {
- /* compute the exposed region:
- * the exposed region consists of two components:
- * 1) what's VISIBLE now and was COVERED before
- * 2) what's EXPOSED now less what was EXPOSED before
- *
- * note that (1) is conservative, we start with the whole
- * visible region but only keep what used to be covered by
- * something -- which mean it may have been exposed.
- *
- * (2) handles areas that were not covered by anything but got
- * exposed because of a resize.
- */
- const Region newExposed = visibleRegion - coveredRegion;
- const Region oldVisibleRegion = layer->visibleRegion;
- const Region oldCoveredRegion = layer->coveredRegion;
- const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
- dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed);
- }
- dirty.subtractSelf(aboveOpaqueLayers);
-
- // accumulate to the screen dirty region
- outDirtyRegion.orSelf(dirty);
-
- // Update aboveOpaqueLayers for next (lower) layer
- aboveOpaqueLayers.orSelf(opaqueRegion);
-
- // Store the visible region in screen space
- layer->setVisibleRegion(visibleRegion);
- layer->setCoveredRegion(coveredRegion);
- layer->setVisibleNonTransparentRegion(
- visibleRegion.subtract(transparentRegion));
- });
-
- outOpaqueRegion = aboveOpaqueLayers;
-}
-
-void SurfaceFlinger::invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty) {
- uint32_t layerStack = layer->getLayerStack();
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- const sp<DisplayDevice>& hw(mDisplays[dpy]);
- if (hw->getLayerStack() == layerStack) {
- hw->dirtyRegion.orSelf(dirty);
- }
- }
-}
-
-bool SurfaceFlinger::handlePageFlip()
-{
- nsecs_t latchTime = systemTime();
- Region dirtyRegion;
-
- bool visibleRegions = false;
- bool frameQueued = false;
-
- // Store the set of layers that need updates. This set must not change as
- // buffers are being latched, as this could result in a deadlock.
- // Example: Two producers share the same command stream and:
- // 1.) Layer 0 is latched
- // 2.) Layer 0 gets a new frame
- // 2.) Layer 1 gets a new frame
- // 3.) Layer 1 is latched.
- // Display is now waiting on Layer 1's frame, which is behind layer 0's
- // second frame. But layer 0's second frame could be waiting on display.
- Vector<Layer*> layersWithQueuedFrames;
- mDrawingState.traverseInZOrder([&](Layer* layer) {
- if (layer->hasQueuedFrame()) {
- frameQueued = true;
- if (layer->shouldPresentNow(mPrimaryDispSync)) {
- layersWithQueuedFrames.push_back(layer);
- } else {
- layer->useEmptyDamage();
- }
- } else {
- layer->useEmptyDamage();
- }
- });
- for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) {
- Layer* layer = layersWithQueuedFrames[i];
- const Region dirty(layer->latchBuffer(visibleRegions, latchTime));
- layer->useSurfaceDamage();
- invalidateLayerStack(layer, dirty);
- }
-
- mVisibleRegionsDirty |= visibleRegions;
-
- // If we will need to wake up at some time in the future to deal with a
- // queued frame that shouldn't be displayed during this vsync period, wake
- // up during the next vsync period to check again.
- if (frameQueued && layersWithQueuedFrames.empty()) {
- signalLayerUpdate();
- }
-
- // Only continue with the refresh if there is actually new work to do
- return !layersWithQueuedFrames.empty();
-}
-
-void SurfaceFlinger::invalidateHwcGeometry()
-{
- mHwWorkListDirty = true;
-}
-
-
-void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,
- const Region& inDirtyRegion)
-{
- // We only need to actually compose the display if:
- // 1) It is being handled by hardware composer, which may need this to
- // keep its virtual display state machine in sync, or
- // 2) There is work to be done (the dirty region isn't empty)
- bool isHwcDisplay = hw->getHwcDisplayId() >= 0;
- if (!isHwcDisplay && inDirtyRegion.isEmpty()) {
- return;
- }
-
- Region dirtyRegion(inDirtyRegion);
-
- // compute the invalid region
- hw->swapRegion.orSelf(dirtyRegion);
-
- uint32_t flags = hw->getFlags();
- if (flags & DisplayDevice::SWAP_RECTANGLE) {
- // we can redraw only what's dirty, but since SWAP_RECTANGLE only
- // takes a rectangle, we must make sure to update that whole
- // rectangle in that case
- dirtyRegion.set(hw->swapRegion.bounds());
- } else {
- if (flags & DisplayDevice::PARTIAL_UPDATES) {
- // We need to redraw the rectangle that will be updated
- // (pushed to the framebuffer).
- // This is needed because PARTIAL_UPDATES only takes one
- // rectangle instead of a region (see DisplayDevice::flip())
- dirtyRegion.set(hw->swapRegion.bounds());
- } else {
- // we need to redraw everything (the whole screen)
- dirtyRegion.set(hw->bounds());
- hw->swapRegion = dirtyRegion;
- }
- }
-
- if (CC_LIKELY(!mDaltonize && !mHasColorMatrix)) {
- if (!doComposeSurfaces(hw, dirtyRegion)) return;
- } else {
- RenderEngine& engine(getRenderEngine());
- mat4 colorMatrix = mColorMatrix;
- if (mDaltonize) {
- colorMatrix = colorMatrix * mDaltonizer();
- }
- mat4 oldMatrix = engine.setupColorTransform(colorMatrix);
- doComposeSurfaces(hw, dirtyRegion);
- engine.setupColorTransform(oldMatrix);
- }
-
- // update the swap region and clear the dirty region
- hw->swapRegion.orSelf(dirtyRegion);
-
- // swap buffers (presentation)
- hw->swapBuffers(getHwComposer());
-}
-
-bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)
-{
- RenderEngine& engine(getRenderEngine());
- const int32_t id = hw->getHwcDisplayId();
- HWComposer& hwc(getHwComposer());
- HWComposer::LayerListIterator cur = hwc.begin(id);
- const HWComposer::LayerListIterator end = hwc.end(id);
-
- bool hasGlesComposition = hwc.hasGlesComposition(id);
- if (hasGlesComposition) {
- if (!hw->makeCurrent(mEGLDisplay, mEGLContext)) {
- ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
- hw->getDisplayName().string());
- eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- if(!getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext)) {
- ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");
- }
- return false;
- }
-
- // Never touch the framebuffer if we don't have any framebuffer layers
- const bool hasHwcComposition = hwc.hasHwcComposition(id);
- if (hasHwcComposition) {
- // when using overlays, we assume a fully transparent framebuffer
- // NOTE: we could reduce how much we need to clear, for instance
- // remove where there are opaque FB layers. however, on some
- // GPUs doing a "clean slate" clear might be more efficient.
- // We'll revisit later if needed.
- engine.clearWithColor(0, 0, 0, 0);
- } else {
- // we start with the whole screen area
- const Region bounds(hw->getBounds());
-
- // we remove the scissor part
- // we're left with the letterbox region
- // (common case is that letterbox ends-up being empty)
- const Region letterbox(bounds.subtract(hw->getScissor()));
-
- // compute the area to clear
- Region region(hw->undefinedRegion.merge(letterbox));
-
- // but limit it to the dirty region
- region.andSelf(dirty);
-
- // screen is already cleared here
- if (!region.isEmpty()) {
- // can happen with SurfaceView
- drawWormhole(hw, region);
- }
- }
-
- if (hw->getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) {
- // just to be on the safe side, we don't set the
- // scissor on the main display. It should never be needed
- // anyways (though in theory it could since the API allows it).
- const Rect& bounds(hw->getBounds());
- const Rect& scissor(hw->getScissor());
- if (scissor != bounds) {
- // scissor doesn't match the screen's dimensions, so we
- // need to clear everything outside of it and enable
- // the GL scissor so we don't draw anything where we shouldn't
-
- // enable scissor for this frame
- const uint32_t height = hw->getHeight();
- engine.setScissor(scissor.left, height - scissor.bottom,
- scissor.getWidth(), scissor.getHeight());
- }
- }
- }
-
- /*
- * and then, render the layers targeted at the framebuffer
- */
-
- const Vector< sp<Layer> >& layers(hw->getVisibleLayersSortedByZ());
- const size_t count = layers.size();
- const Transform& tr = hw->getTransform();
- if (cur != end) {
- // we're using h/w composer
- for (size_t i=0 ; i<count && cur!=end ; ++i, ++cur) {
- const sp<Layer>& layer(layers[i]);
- const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));
- if (!clip.isEmpty()) {
- switch (cur->getCompositionType()) {
- case HWC_CURSOR_OVERLAY:
- case HWC_OVERLAY: {
- const Layer::State& state(layer->getDrawingState());
- if ((cur->getHints() & HWC_HINT_CLEAR_FB)
- && i
- && layer->isOpaque(state) && (state.alpha == 0xFF)
- && hasGlesComposition) {
- // never clear the very first layer since we're
- // guaranteed the FB is already cleared
- layer->clearWithOpenGL(hw);
- }
- break;
- }
- case HWC_FRAMEBUFFER: {
- layer->draw(hw, clip);
- break;
- }
- case HWC_FRAMEBUFFER_TARGET: {
- // this should not happen as the iterator shouldn't
- // let us get there.
- ALOGW("HWC_FRAMEBUFFER_TARGET found in hwc list (index=%zu)", i);
- break;
- }
- }
- }
- layer->setAcquireFence(hw, *cur);
- }
- } else {
- // we're not using h/w composer
- for (size_t i=0 ; i<count ; ++i) {
- const sp<Layer>& layer(layers[i]);
- const Region clip(dirty.intersect(
- tr.transform(layer->visibleRegion)));
- if (!clip.isEmpty()) {
- layer->draw(hw, clip);
- }
- }
- }
-
- // disable scissor at the end of the frame
- engine.disableScissor();
- return true;
-}
-
-void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& hw, const Region& region) const {
- const int32_t height = hw->getHeight();
- RenderEngine& engine(getRenderEngine());
- engine.fillRegionWithColor(region, height, 0, 0, 0, 0);
-}
-
-status_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
- const sp<IBinder>& handle,
- const sp<IGraphicBufferProducer>& gbc,
- const sp<Layer>& lbc,
- const sp<Layer>& parent)
-{
- // add this layer to the current state list
- {
- Mutex::Autolock _l(mStateLock);
- if (mNumLayers >= MAX_LAYERS) {
- return NO_MEMORY;
- }
- if (parent == nullptr) {
- mCurrentState.layersSortedByZ.add(lbc);
- } else {
- if (mCurrentState.layersSortedByZ.indexOf(parent) < 0) {
- ALOGE("addClientLayer called with a removed parent");
- return NAME_NOT_FOUND;
- }
- parent->addChild(lbc);
- }
-
- mGraphicBufferProducerList.add(IInterface::asBinder(gbc));
- mLayersAdded = true;
- mNumLayers++;
- }
-
- // attach this layer to the client
- client->attachLayer(handle, lbc);
-
- return NO_ERROR;
-}
-
-status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer, bool topLevelOnly) {
- Mutex::Autolock _l(mStateLock);
-
- const auto& p = layer->getParent();
- ssize_t index;
- if (p != nullptr) {
- if (topLevelOnly) {
- return NO_ERROR;
- }
-
- sp<Layer> ancestor = p;
- while (ancestor->getParent() != nullptr) {
- ancestor = ancestor->getParent();
- }
- if (mCurrentState.layersSortedByZ.indexOf(ancestor) < 0) {
- ALOGE("removeLayer called with a layer whose parent has been removed");
- return NAME_NOT_FOUND;
- }
-
- index = p->removeChild(layer);
- } else {
- index = mCurrentState.layersSortedByZ.remove(layer);
- }
-
- // As a matter of normal operation, the LayerCleaner will produce a second
- // attempt to remove the surface. The Layer will be kept alive in mDrawingState
- // so we will succeed in promoting it, but it's already been removed
- // from mCurrentState. As long as we can find it in mDrawingState we have no problem
- // otherwise something has gone wrong and we are leaking the layer.
- if (index < 0 && mDrawingState.layersSortedByZ.indexOf(layer) < 0) {
- ALOGE("Failed to find layer (%s) in layer parent (%s).",
- layer->getName().string(),
- (p != nullptr) ? p->getName().string() : "no-parent");
- return BAD_VALUE;
- } else if (index < 0) {
- return NO_ERROR;
- }
-
- layer->onRemovedFromCurrentState();
- mLayersPendingRemoval.add(layer);
- mLayersRemoved = true;
- mNumLayers -= 1 + layer->getChildrenCount();
- setTransactionFlags(eTransactionNeeded);
- return NO_ERROR;
-}
-
-uint32_t SurfaceFlinger::peekTransactionFlags() {
- return android_atomic_release_load(&mTransactionFlags);
-}
-
-uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags) {
- return android_atomic_and(~flags, &mTransactionFlags) & flags;
-}
-
-uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) {
- uint32_t old = android_atomic_or(flags, &mTransactionFlags);
- if ((old & flags)==0) { // wake the server up
- signalTransaction();
- }
- return old;
-}
-
-void SurfaceFlinger::setTransactionState(
- const Vector<ComposerState>& state,
- const Vector<DisplayState>& displays,
- uint32_t flags)
-{
- ATRACE_CALL();
- Mutex::Autolock _l(mStateLock);
- uint32_t transactionFlags = 0;
-
- if (flags & eAnimation) {
- // For window updates that are part of an animation we must wait for
- // previous animation "frames" to be handled.
- while (mAnimTransactionPending) {
- status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
- if (CC_UNLIKELY(err != NO_ERROR)) {
- // just in case something goes wrong in SF, return to the
- // caller after a few seconds.
- ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out "
- "waiting for previous animation frame");
- mAnimTransactionPending = false;
- break;
- }
- }
- }
-
- size_t count = displays.size();
- for (size_t i=0 ; i<count ; i++) {
- const DisplayState& s(displays[i]);
- transactionFlags |= setDisplayStateLocked(s);
- }
-
- count = state.size();
- for (size_t i=0 ; i<count ; i++) {
- const ComposerState& s(state[i]);
- // Here we need to check that the interface we're given is indeed
- // one of our own. A malicious client could give us a NULL
- // IInterface, or one of its own or even one of our own but a
- // different type. All these situations would cause us to crash.
- //
- // NOTE: it would be better to use RTTI as we could directly check
- // that we have a Client*. however, RTTI is disabled in Android.
- if (s.client != NULL) {
- sp<IBinder> binder = IInterface::asBinder(s.client);
- if (binder != NULL) {
- if (binder->queryLocalInterface(ISurfaceComposerClient::descriptor) != NULL) {
- sp<Client> client( static_cast<Client *>(s.client.get()) );
- transactionFlags |= setClientStateLocked(client, s.state);
- }
- }
- }
- }
-
- // If a synchronous transaction is explicitly requested without any changes,
- // force a transaction anyway. This can be used as a flush mechanism for
- // previous async transactions.
- if (transactionFlags == 0 && (flags & eSynchronous)) {
- transactionFlags = eTransactionNeeded;
- }
-
- if (transactionFlags) {
- if (mInterceptor.isEnabled()) {
- mInterceptor.saveTransaction(state, mCurrentState.displays, displays, flags);
- }
-
- // this triggers the transaction
- setTransactionFlags(transactionFlags);
-
- // if this is a synchronous transaction, wait for it to take effect
- // before returning.
- if (flags & eSynchronous) {
- mTransactionPending = true;
- }
- if (flags & eAnimation) {
- mAnimTransactionPending = true;
- }
- while (mTransactionPending) {
- status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
- if (CC_UNLIKELY(err != NO_ERROR)) {
- // just in case something goes wrong in SF, return to the
- // called after a few seconds.
- ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
- mTransactionPending = false;
- break;
- }
- }
- }
-}
-
-uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s)
-{
- ssize_t dpyIdx = mCurrentState.displays.indexOfKey(s.token);
- if (dpyIdx < 0)
- return 0;
-
- uint32_t flags = 0;
- DisplayDeviceState& disp(mCurrentState.displays.editValueAt(dpyIdx));
- if (disp.isValid()) {
- const uint32_t what = s.what;
- if (what & DisplayState::eSurfaceChanged) {
- if (IInterface::asBinder(disp.surface) != IInterface::asBinder(s.surface)) {
- disp.surface = s.surface;
- flags |= eDisplayTransactionNeeded;
- }
- }
- if (what & DisplayState::eLayerStackChanged) {
- if (disp.layerStack != s.layerStack) {
- disp.layerStack = s.layerStack;
- flags |= eDisplayTransactionNeeded;
- }
- }
- if (what & DisplayState::eDisplayProjectionChanged) {
- if (disp.orientation != s.orientation) {
- disp.orientation = s.orientation;
- flags |= eDisplayTransactionNeeded;
- }
- if (disp.frame != s.frame) {
- disp.frame = s.frame;
- flags |= eDisplayTransactionNeeded;
- }
- if (disp.viewport != s.viewport) {
- disp.viewport = s.viewport;
- flags |= eDisplayTransactionNeeded;
- }
- }
- if (what & DisplayState::eDisplaySizeChanged) {
- if (disp.width != s.width) {
- disp.width = s.width;
- flags |= eDisplayTransactionNeeded;
- }
- if (disp.height != s.height) {
- disp.height = s.height;
- flags |= eDisplayTransactionNeeded;
- }
- }
- }
- return flags;
-}
-
-uint32_t SurfaceFlinger::setClientStateLocked(
- 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 (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) {
- 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(uint8_t(255.0f*s.alpha+0.5f)))
- 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::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;
-}
-
-status_t SurfaceFlinger::createLayer(
- const String8& name,
- const sp<Client>& client,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
- uint32_t windowType, uint32_t ownerUid, sp<IBinder>* handle,
- sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent)
-{
- if (int32_t(w|h) < 0) {
- ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
- int(w), int(h));
- return BAD_VALUE;
- }
-
- status_t result = NO_ERROR;
-
- sp<Layer> layer;
-
- String8 uniqueName = getUniqueLayerName(name);
-
- switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
- case ISurfaceComposerClient::eFXSurfaceNormal:
- result = createNormalLayer(client,
- uniqueName, w, h, flags, format,
- handle, gbp, &layer);
- break;
- case ISurfaceComposerClient::eFXSurfaceDim:
- result = createDimLayer(client,
- uniqueName, w, h, flags,
- handle, gbp, &layer);
- break;
- default:
- result = BAD_VALUE;
- break;
- }
-
- if (result != NO_ERROR) {
- return result;
- }
-
- layer->setInfo(windowType, ownerUid);
-
- result = addClientLayer(client, *handle, *gbp, layer, *parent);
- if (result != NO_ERROR) {
- return result;
- }
- mInterceptor.saveSurfaceCreation(layer);
-
- setTransactionFlags(eTransactionNeeded);
- return result;
-}
-
-String8 SurfaceFlinger::getUniqueLayerName(const String8& name)
-{
- bool matchFound = true;
- uint32_t dupeCounter = 0;
-
- // Tack on our counter whether there is a hit or not, so everyone gets a tag
- String8 uniqueName = name + "#" + String8(std::to_string(dupeCounter).c_str());
-
- // Loop over layers until we're sure there is no matching name
- while (matchFound) {
- matchFound = false;
- mDrawingState.traverseInZOrder([&](Layer* layer) {
- if (layer->getName() == uniqueName) {
- matchFound = true;
- uniqueName = name + "#" + String8(std::to_string(++dupeCounter).c_str());
- }
- });
- }
-
- ALOGD_IF(dupeCounter > 0, "duplicate layer name: changing %s to %s", name.c_str(), uniqueName.c_str());
-
- return uniqueName;
-}
-
-status_t SurfaceFlinger::createNormalLayer(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)
-{
- // initialize the surfaces
- switch (format) {
- case PIXEL_FORMAT_TRANSPARENT:
- case PIXEL_FORMAT_TRANSLUCENT:
- format = PIXEL_FORMAT_RGBA_8888;
- break;
- case PIXEL_FORMAT_OPAQUE:
- format = PIXEL_FORMAT_RGBX_8888;
- break;
- }
-
- *outLayer = new Layer(this, client, name, w, h, flags);
- status_t err = (*outLayer)->setBuffers(w, h, format, flags);
- if (err == NO_ERROR) {
- *handle = (*outLayer)->getHandle();
- *gbp = (*outLayer)->getProducer();
- }
-
- ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err));
- return err;
-}
-
-status_t SurfaceFlinger::createDimLayer(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)
-{
- *outLayer = new LayerDim(this, client, name, w, h, flags);
- *handle = (*outLayer)->getHandle();
- *gbp = (*outLayer)->getProducer();
- return NO_ERROR;
-}
-
-status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle)
-{
- // called by a client when it wants to remove a Layer
- status_t err = NO_ERROR;
- sp<Layer> l(client->getLayerUser(handle));
- if (l != NULL) {
- mInterceptor.saveSurfaceDeletion(l);
- err = removeLayer(l);
- ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
- "error removing layer=%p (%s)", l.get(), strerror(-err));
- }
- return err;
-}
-
-status_t SurfaceFlinger::onLayerDestroyed(const wp<Layer>& layer)
-{
- // called by ~LayerCleaner() when all references to the IBinder (handle)
- // are gone
- sp<Layer> l = layer.promote();
- if (l == nullptr) {
- // The layer has already been removed, carry on
- return NO_ERROR;
- }
- // If we have a parent, then we can continue to live as long as it does.
- return removeLayer(l, true);
-}
-
-// ---------------------------------------------------------------------------
-
-void SurfaceFlinger::onInitializeDisplays() {
- // reset screen orientation and use primary layer stack
- Vector<ComposerState> state;
- Vector<DisplayState> displays;
- DisplayState d;
- d.what = DisplayState::eDisplayProjectionChanged |
- DisplayState::eLayerStackChanged;
- d.token = mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY];
- d.layerStack = 0;
- d.orientation = DisplayState::eOrientationDefault;
- d.frame.makeInvalid();
- d.viewport.makeInvalid();
- d.width = 0;
- d.height = 0;
- displays.add(d);
- setTransactionState(state, displays, 0);
- setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL);
-
- const nsecs_t period =
- getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
- mAnimFrameTracker.setDisplayRefreshPeriod(period);
-
- // Use phase of 0 since phase is not known.
- // Use latency of 0, which will snap to the ideal latency.
- setCompositorTimingSnapped(0, period, 0);
-}
-
-void SurfaceFlinger::initializeDisplays() {
- class MessageScreenInitialized : public MessageBase {
- SurfaceFlinger* flinger;
- public:
- explicit MessageScreenInitialized(SurfaceFlinger* flinger) : flinger(flinger) { }
- virtual bool handler() {
- flinger->onInitializeDisplays();
- return true;
- }
- };
- sp<MessageBase> msg = new MessageScreenInitialized(this);
- postMessageAsync(msg); // we may be called from main thread, use async message
-}
-
-void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw,
- int mode) {
- ALOGD("Set power mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
- this);
- int32_t type = hw->getDisplayType();
- int currentMode = hw->getPowerMode();
-
- if (mode == currentMode) {
- ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode);
- return;
- }
-
- hw->setPowerMode(mode);
- if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
- ALOGW("Trying to set power mode for virtual display");
- return;
- }
-
- if (mInterceptor.isEnabled()) {
- Mutex::Autolock _l(mStateLock);
- ssize_t idx = mCurrentState.displays.indexOfKey(hw->getDisplayToken());
- if (idx < 0) {
- ALOGW("Surface Interceptor SavePowerMode: invalid display token");
- return;
- }
- mInterceptor.savePowerModeUpdate(mCurrentState.displays.valueAt(idx).displayId, mode);
- }
-
- if (currentMode == HWC_POWER_MODE_OFF) {
- // Turn on the display
- getHwComposer().setPowerMode(type, mode);
- if (type == DisplayDevice::DISPLAY_PRIMARY &&
- mode != HWC_POWER_MODE_DOZE_SUSPEND) {
- // FIXME: eventthread only knows about the main display right now
- mEventThread->onScreenAcquired();
- resyncToHardwareVsync(true);
- }
-
- mVisibleRegionsDirty = true;
- mHasPoweredOff = true;
- repaintEverything();
-
- struct sched_param param = {0};
- param.sched_priority = 1;
- if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) {
- ALOGW("Couldn't set SCHED_FIFO on display on");
- }
- } else if (mode == HWC_POWER_MODE_OFF) {
- // Turn off the display
- struct sched_param param = {0};
- if (sched_setscheduler(0, SCHED_OTHER, ¶m) != 0) {
- ALOGW("Couldn't set SCHED_OTHER on display off");
- }
-
- if (type == DisplayDevice::DISPLAY_PRIMARY) {
- disableHardwareVsync(true); // also cancels any in-progress resync
-
- // FIXME: eventthread only knows about the main display right now
- mEventThread->onScreenReleased();
- }
-
- getHwComposer().setPowerMode(type, mode);
- mVisibleRegionsDirty = true;
- // from this point on, SF will stop drawing on this display
- } else if (mode == HWC_POWER_MODE_DOZE ||
- mode == HWC_POWER_MODE_NORMAL) {
- // Update display while dozing
- getHwComposer().setPowerMode(type, mode);
- if (type == DisplayDevice::DISPLAY_PRIMARY) {
- // FIXME: eventthread only knows about the main display right now
- mEventThread->onScreenAcquired();
- resyncToHardwareVsync(true);
- }
- } else if (mode == HWC_POWER_MODE_DOZE_SUSPEND) {
- // Leave display going to doze
- if (type == DisplayDevice::DISPLAY_PRIMARY) {
- disableHardwareVsync(true); // also cancels any in-progress resync
- // FIXME: eventthread only knows about the main display right now
- mEventThread->onScreenReleased();
- }
- getHwComposer().setPowerMode(type, mode);
- } else {
- ALOGE("Attempting to set unknown power mode: %d\n", mode);
- getHwComposer().setPowerMode(type, mode);
- }
-}
-
-void SurfaceFlinger::setPowerMode(const sp<IBinder>& display, int mode) {
- class MessageSetPowerMode: public MessageBase {
- SurfaceFlinger& mFlinger;
- sp<IBinder> mDisplay;
- int mMode;
- public:
- MessageSetPowerMode(SurfaceFlinger& flinger,
- const sp<IBinder>& disp, int mode) : mFlinger(flinger),
- mDisplay(disp) { mMode = mode; }
- virtual bool handler() {
- sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
- if (hw == NULL) {
- ALOGE("Attempt to set power mode = %d for null display %p",
- mMode, mDisplay.get());
- } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
- ALOGW("Attempt to set power mode = %d for virtual display",
- mMode);
- } else {
- mFlinger.setPowerModeInternal(hw, mMode);
- }
- return true;
- }
- };
- sp<MessageBase> msg = new MessageSetPowerMode(*this, display, mode);
- postMessageSync(msg);
-}
-
-// ---------------------------------------------------------------------------
-
-status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
-{
- 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: "
- "can't dump SurfaceFlinger from pid=%d, uid=%d\n", pid, uid);
- } else {
- // Try to get the main lock, but give up after one second
- // (this would indicate SF is stuck, but we want to be able to
- // print something in dumpsys).
- status_t err = mStateLock.timedLock(s2ns(1));
- bool locked = (err == NO_ERROR);
- if (!locked) {
- result.appendFormat(
- "SurfaceFlinger appears to be unresponsive (%s [%d]), "
- "dumping anyways (no locks held)\n", strerror(-err), err);
- }
-
- bool dumpAll = true;
- size_t index = 0;
- size_t numArgs = args.size();
- if (numArgs) {
- if ((index < numArgs) &&
- (args[index] == String16("--list"))) {
- index++;
- listLayersLocked(args, index, result);
- dumpAll = false;
- }
-
- if ((index < numArgs) &&
- (args[index] == String16("--latency"))) {
- index++;
- dumpStatsLocked(args, index, result);
- dumpAll = false;
- }
-
- if ((index < numArgs) &&
- (args[index] == String16("--latency-clear"))) {
- index++;
- clearStatsLocked(args, index, result);
- dumpAll = false;
- }
-
- if ((index < numArgs) &&
- (args[index] == String16("--dispsync"))) {
- index++;
- mPrimaryDispSync.dump(result);
- dumpAll = false;
- }
-
- if ((index < numArgs) &&
- (args[index] == String16("--static-screen"))) {
- index++;
- dumpStaticScreenStats(result);
- dumpAll = false;
- }
-
- if ((index < numArgs) &&
- (args[index] == String16("--frame-events"))) {
- index++;
- dumpFrameEventsLocked(result);
- dumpAll = false;
- }
- }
-
- if (dumpAll) {
- dumpAllLocked(args, index, result);
- }
-
- if (locked) {
- mStateLock.unlock();
- }
- }
- write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-void SurfaceFlinger::listLayersLocked(const Vector<String16>& /* args */,
- size_t& /* index */, String8& result) const
-{
- mCurrentState.traverseInZOrder([&](Layer* layer) {
- result.appendFormat("%s\n", layer->getName().string());
- });
-}
-
-void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index,
- String8& result) const
-{
- String8 name;
- if (index < args.size()) {
- name = String8(args[index]);
- index++;
- }
-
- const nsecs_t period =
- getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
- result.appendFormat("%" PRId64 "\n", period);
-
- if (name.isEmpty()) {
- mAnimFrameTracker.dumpStats(result);
- } else {
- mCurrentState.traverseInZOrder([&](Layer* layer) {
- if (name == layer->getName()) {
- layer->dumpFrameStats(result);
- }
- });
- }
-}
-
-void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& index,
- String8& /* result */)
-{
- String8 name;
- if (index < args.size()) {
- name = String8(args[index]);
- index++;
- }
-
- mCurrentState.traverseInZOrder([&](Layer* layer) {
- if (name.isEmpty() || (name == layer->getName())) {
- layer->clearFrameStats();
- }
- });
-
- mAnimFrameTracker.clearStats();
-}
-
-// This should only be called from the main thread. Otherwise it would need
-// the lock and should use mCurrentState rather than mDrawingState.
-void SurfaceFlinger::logFrameStats() {
- mDrawingState.traverseInZOrder([&](Layer* layer) {
- layer->logFrameStats();
- });
-
- mAnimFrameTracker.logAndResetStats(String8("<win-anim>"));
-}
-
-void SurfaceFlinger::appendSfConfigString(String8& result) const
-{
- result.append(" [sf");
- result.appendFormat(" HAS_CONTEXT_PRIORITY=%d", useContextPriority);
-
- if (isLayerTripleBufferingDisabled())
- result.append(" DISABLE_TRIPLE_BUFFERING");
-
- result.appendFormat(" PRESENT_TIME_OFFSET=%" PRId64, dispSyncPresentTimeOffset);
- result.appendFormat(" FORCE_HWC_FOR_RBG_TO_YUV=%d", useHwcForRgbToYuv);
- result.appendFormat(" MAX_VIRT_DISPLAY_DIM=%" PRIu64, maxVirtualDisplaySize);
- result.appendFormat(" RUNNING_WITHOUT_SYNC_FRAMEWORK=%d", !hasSyncFramework);
- result.appendFormat(" NUM_FRAMEBUFFER_SURFACE_BUFFERS=%" PRId64,
- maxFrameBufferAcquiredBuffers);
- result.append("]");
-}
-
-void SurfaceFlinger::dumpStaticScreenStats(String8& result) const
-{
- result.appendFormat("Static screen stats:\n");
- for (size_t b = 0; b < NUM_BUCKETS - 1; ++b) {
- float bucketTimeSec = mFrameBuckets[b] / 1e9;
- float percent = 100.0f *
- static_cast<float>(mFrameBuckets[b]) / mTotalTime;
- result.appendFormat(" < %zd frames: %.3f s (%.1f%%)\n",
- b + 1, bucketTimeSec, percent);
- }
- float bucketTimeSec = mFrameBuckets[NUM_BUCKETS - 1] / 1e9;
- float percent = 100.0f *
- static_cast<float>(mFrameBuckets[NUM_BUCKETS - 1]) / mTotalTime;
- result.appendFormat(" %zd+ frames: %.3f s (%.1f%%)\n",
- NUM_BUCKETS - 1, bucketTimeSec, percent);
-}
-
-void SurfaceFlinger::dumpFrameEventsLocked(String8& result) {
- result.appendFormat("Layer frame timestamps:\n");
-
- const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
- const size_t count = currentLayers.size();
- for (size_t i=0 ; i<count ; i++) {
- currentLayers[i]->dumpFrameEvents(result);
- }
-}
-
-void SurfaceFlinger::recordBufferingStats(const char* layerName,
- std::vector<OccupancyTracker::Segment>&& history) {
- Mutex::Autolock lock(mBufferingStatsMutex);
- auto& stats = mBufferingStats[layerName];
- for (const auto& segment : history) {
- if (!segment.usedThirdBuffer) {
- stats.twoBufferTime += segment.totalTime;
- }
- if (segment.occupancyAverage < 1.0f) {
- stats.doubleBufferedTime += segment.totalTime;
- } else if (segment.occupancyAverage < 2.0f) {
- stats.tripleBufferedTime += segment.totalTime;
- }
- ++stats.numSegments;
- stats.totalTime += segment.totalTime;
- }
-}
-
-void SurfaceFlinger::dumpBufferingStats(String8& result) const {
- result.append("Buffering stats:\n");
- result.append(" [Layer name] <Active time> <Two buffer> "
- "<Double buffered> <Triple buffered>\n");
- Mutex::Autolock lock(mBufferingStatsMutex);
- typedef std::tuple<std::string, float, float, float> BufferTuple;
- std::map<float, BufferTuple, std::greater<float>> sorted;
- for (const auto& statsPair : mBufferingStats) {
- const char* name = statsPair.first.c_str();
- const BufferingStats& stats = statsPair.second;
- if (stats.numSegments == 0) {
- continue;
- }
- float activeTime = ns2ms(stats.totalTime) / 1000.0f;
- float twoBufferRatio = static_cast<float>(stats.twoBufferTime) /
- stats.totalTime;
- float doubleBufferRatio = static_cast<float>(
- stats.doubleBufferedTime) / stats.totalTime;
- float tripleBufferRatio = static_cast<float>(
- stats.tripleBufferedTime) / stats.totalTime;
- sorted.insert({activeTime, {name, twoBufferRatio,
- doubleBufferRatio, tripleBufferRatio}});
- }
- for (const auto& sortedPair : sorted) {
- float activeTime = sortedPair.first;
- const BufferTuple& values = sortedPair.second;
- result.appendFormat(" [%s] %.2f %.3f %.3f %.3f\n",
- std::get<0>(values).c_str(), activeTime,
- std::get<1>(values), std::get<2>(values),
- std::get<3>(values));
- }
- result.append("\n");
-}
-
-void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
- String8& result) const
-{
- bool colorize = false;
- if (index < args.size()
- && (args[index] == String16("--color"))) {
- colorize = true;
- index++;
- }
-
- Colorizer colorizer(colorize);
-
- // figure out if we're stuck somewhere
- const nsecs_t now = systemTime();
- const nsecs_t inSwapBuffers(mDebugInSwapBuffers);
- const nsecs_t inTransaction(mDebugInTransaction);
- nsecs_t inSwapBuffersDuration = (inSwapBuffers) ? now-inSwapBuffers : 0;
- nsecs_t inTransactionDuration = (inTransaction) ? now-inTransaction : 0;
-
- /*
- * Dump library configuration.
- */
-
- colorizer.bold(result);
- result.append("Build configuration:");
- colorizer.reset(result);
- appendSfConfigString(result);
- appendUiConfigString(result);
- appendGuiConfigString(result);
- result.append("\n");
-
- colorizer.bold(result);
- result.append("Sync configuration: ");
- colorizer.reset(result);
- result.append(SyncFeatures::getInstance().toString());
- result.append("\n");
-
- colorizer.bold(result);
- result.append("DispSync configuration: ");
- colorizer.reset(result);
- result.appendFormat("app phase %" PRId64 " ns, sf phase %" PRId64 " ns, "
- "present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
- vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, dispSyncPresentTimeOffset,
- mHwc->getRefreshPeriod(HWC_DISPLAY_PRIMARY));
- result.append("\n");
-
- // Dump static screen stats
- result.append("\n");
- dumpStaticScreenStats(result);
- result.append("\n");
-
- dumpBufferingStats(result);
-
- /*
- * Dump the visible layer list
- */
- 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());
- });
-
- /*
- * Dump Display state
- */
-
- colorizer.bold(result);
- result.appendFormat("Displays (%zu entries)\n", mDisplays.size());
- colorizer.reset(result);
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- const sp<const DisplayDevice>& hw(mDisplays[dpy]);
- hw->dump(result);
- }
-
- /*
- * Dump SurfaceFlinger global state
- */
-
- colorizer.bold(result);
- result.append("SurfaceFlinger global state:\n");
- colorizer.reset(result);
-
- HWComposer& hwc(getHwComposer());
- sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
-
- colorizer.bold(result);
- result.appendFormat("EGL implementation : %s\n",
- eglQueryStringImplementationANDROID(mEGLDisplay, EGL_VERSION));
- colorizer.reset(result);
- result.appendFormat("%s\n",
- eglQueryStringImplementationANDROID(mEGLDisplay, EGL_EXTENSIONS));
-
- mRenderEngine->dump(result);
-
- hw->undefinedRegion.dump(result, "undefinedRegion");
- result.appendFormat(" orientation=%d, isDisplayOn=%d\n",
- hw->getOrientation(), hw->isDisplayOn());
- result.appendFormat(
- " last eglSwapBuffers() time: %f us\n"
- " last transaction time : %f us\n"
- " transaction-flags : %08x\n"
- " refresh-rate : %f fps\n"
- " x-dpi : %f\n"
- " y-dpi : %f\n"
- " gpu_to_cpu_unsupported : %d\n"
- ,
- mLastSwapBufferTime/1000.0,
- mLastTransactionTime/1000.0,
- mTransactionFlags,
- 1e9 / hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY),
- hwc.getDpiX(HWC_DISPLAY_PRIMARY),
- hwc.getDpiY(HWC_DISPLAY_PRIMARY),
- !mGpuToCpuSupported);
-
- result.appendFormat(" eglSwapBuffers time: %f us\n",
- inSwapBuffersDuration/1000.0);
-
- result.appendFormat(" transaction time: %f us\n",
- inTransactionDuration/1000.0);
-
- /*
- * VSYNC state
- */
- mEventThread->dump(result);
-
- /*
- * Dump HWComposer state
- */
- colorizer.bold(result);
- result.append("h/w composer state:\n");
- colorizer.reset(result);
- result.appendFormat(" h/w composer %s and %s\n",
- hwc.initCheck()==NO_ERROR ? "present" : "not present",
- (mDebugDisableHWC || mDebugRegion || mDaltonize
- || mHasColorMatrix) ? "disabled" : "enabled");
- hwc.dump(result);
-
- /*
- * Dump gralloc state
- */
- const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
- alloc.dump(result);
-}
-
-const Vector< sp<Layer> >&
-SurfaceFlinger::getLayerSortedByZForHwcDisplay(int id) {
- // Note: mStateLock is held here
- wp<IBinder> dpy;
- for (size_t i=0 ; i<mDisplays.size() ; i++) {
- if (mDisplays.valueAt(i)->getHwcDisplayId() == id) {
- dpy = mDisplays.keyAt(i);
- break;
- }
- }
- if (dpy == NULL) {
- ALOGE("getLayerSortedByZForHwcDisplay: invalid hwc display id %d", id);
- // Just use the primary display so we have something to return
- dpy = getBuiltInDisplay(DisplayDevice::DISPLAY_PRIMARY);
- }
- return getDisplayDeviceLocked(dpy)->getVisibleLayersSortedByZ();
-}
-
-bool SurfaceFlinger::startDdmConnection()
-{
- void* libddmconnection_dso =
- dlopen("libsurfaceflinger_ddmconnection.so", RTLD_NOW);
- if (!libddmconnection_dso) {
- return false;
- }
- void (*DdmConnection_start)(const char* name);
- DdmConnection_start =
- (decltype(DdmConnection_start))dlsym(libddmconnection_dso, "DdmConnection_start");
- if (!DdmConnection_start) {
- dlclose(libddmconnection_dso);
- return false;
- }
- (*DdmConnection_start)(getServiceName());
- return true;
-}
-
-status_t SurfaceFlinger::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch (code) {
- case CREATE_CONNECTION:
- case CREATE_DISPLAY:
- case BOOT_FINISHED:
- case CLEAR_ANIMATION_FRAME_STATS:
- case GET_ANIMATION_FRAME_STATS:
- case SET_POWER_MODE:
- case GET_HDR_CAPABILITIES:
- {
- // codes that require permission check
- IPCThreadState* ipc = IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
- if ((uid != AID_GRAPHICS && uid != AID_SYSTEM) &&
- !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) {
- ALOGE("Permission Denial: "
- "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
- return PERMISSION_DENIED;
- }
- break;
- }
- /*
- * Calling setTransactionState is safe, because you need to have been
- * granted a reference to Client* and Handle* to do anything with it.
- *
- * Creating a scoped connection is safe, as per discussion in ISurfaceComposer.h
- */
- case SET_TRANSACTION_STATE:
- case CREATE_SCOPED_CONNECTION:
- {
- break;
- }
- case CAPTURE_SCREEN:
- {
- // codes that require permission check
- 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);
- if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- if (CC_UNLIKELY(!PermissionCache::checkCallingPermission(sHardwareTest))) {
- IPCThreadState* ipc = IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
- ALOGE("Permission Denial: "
- "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
- return PERMISSION_DENIED;
- }
- int n;
- switch (code) {
- case 1000: // SHOW_CPU, NOT SUPPORTED ANYMORE
- case 1001: // SHOW_FPS, NOT SUPPORTED ANYMORE
- return NO_ERROR;
- case 1002: // SHOW_UPDATES
- n = data.readInt32();
- mDebugRegion = n ? n : (mDebugRegion ? 0 : 1);
- invalidateHwcGeometry();
- repaintEverything();
- return NO_ERROR;
- case 1004:{ // repaint everything
- repaintEverything();
- return NO_ERROR;
- }
- case 1005:{ // force transaction
- setTransactionFlags(
- eTransactionNeeded|
- eDisplayTransactionNeeded|
- eTraversalNeeded);
- return NO_ERROR;
- }
- case 1006:{ // send empty update
- signalRefresh();
- return NO_ERROR;
- }
- case 1008: // toggle use of hw composer
- n = data.readInt32();
- mDebugDisableHWC = n ? 1 : 0;
- invalidateHwcGeometry();
- repaintEverything();
- return NO_ERROR;
- case 1009: // toggle use of transform hint
- n = data.readInt32();
- mDebugDisableTransformHint = n ? 1 : 0;
- invalidateHwcGeometry();
- repaintEverything();
- return NO_ERROR;
- case 1010: // interrogate.
- reply->writeInt32(0);
- reply->writeInt32(0);
- reply->writeInt32(mDebugRegion);
- reply->writeInt32(0);
- reply->writeInt32(mDebugDisableHWC);
- return NO_ERROR;
- case 1013: {
- Mutex::Autolock _l(mStateLock);
- sp<const DisplayDevice> hw(getDefaultDisplayDevice());
- reply->writeInt32(hw->getPageFlipCount());
- return NO_ERROR;
- }
- case 1014: {
- // daltonize
- n = data.readInt32();
- switch (n % 10) {
- case 1:
- mDaltonizer.setType(ColorBlindnessType::Protanomaly);
- break;
- case 2:
- mDaltonizer.setType(ColorBlindnessType::Deuteranomaly);
- break;
- case 3:
- mDaltonizer.setType(ColorBlindnessType::Tritanomaly);
- break;
- }
- if (n >= 10) {
- mDaltonizer.setMode(ColorBlindnessMode::Correction);
- } else {
- mDaltonizer.setMode(ColorBlindnessMode::Simulation);
- }
- mDaltonize = n > 0;
- invalidateHwcGeometry();
- repaintEverything();
- return NO_ERROR;
- }
- case 1015: {
- // apply a color matrix
- n = data.readInt32();
- mHasColorMatrix = n ? 1 : 0;
- if (n) {
- // color matrix is sent as mat3 matrix followed by vec3
- // offset, then packed into a mat4 where the last row is
- // the offset and extra values are 0
- for (size_t i = 0 ; i < 4; i++) {
- for (size_t j = 0; j < 4; j++) {
- mColorMatrix[i][j] = data.readFloat();
- }
- }
- } else {
- mColorMatrix = mat4();
- }
- invalidateHwcGeometry();
- repaintEverything();
- return NO_ERROR;
- }
- // This is an experimental interface
- // Needs to be shifted to proper binder interface when we productize
- case 1016: {
- n = data.readInt32();
- mPrimaryDispSync.setRefreshSkipCount(n);
- return NO_ERROR;
- }
- case 1017: {
- n = data.readInt32();
- mForceFullDamage = static_cast<bool>(n);
- return NO_ERROR;
- }
- case 1018: { // Modify Choreographer's phase offset
- n = data.readInt32();
- mEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
- return NO_ERROR;
- }
- case 1019: { // Modify SurfaceFlinger's phase offset
- n = data.readInt32();
- mSFEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
- return NO_ERROR;
- }
- case 1020: { // Layer updates interceptor
- n = data.readInt32();
- if (n) {
- ALOGV("Interceptor enabled");
- mInterceptor.enable(mDrawingState.layersSortedByZ, mDrawingState.displays);
- }
- else{
- ALOGV("Interceptor disabled");
- mInterceptor.disable();
- }
- return NO_ERROR;
- }
- case 1021: { // Disable HWC virtual displays
- n = data.readInt32();
- mUseHwcVirtualDisplays = !n;
- return NO_ERROR;
- }
- }
- }
- return err;
-}
-
-void SurfaceFlinger::repaintEverything() {
- android_atomic_or(1, &mRepaintEverything);
- signalTransaction();
-}
-
-// ---------------------------------------------------------------------------
-// Capture screen into an IGraphiBufferProducer
-// ---------------------------------------------------------------------------
-
-/* The code below is here to handle b/8734824
- *
- * We create a IGraphicBufferProducer wrapper that forwards all calls
- * from the surfaceflinger thread to the calling binder thread, where they
- * are executed. This allows the calling thread in the calling process to be
- * reused and not depend on having "enough" binder threads to handle the
- * requests.
- */
-class GraphicProducerWrapper : public BBinder, public MessageHandler {
- /* Parts of GraphicProducerWrapper are run on two different threads,
- * communicating by sending messages via Looper but also by shared member
- * data. Coherence maintenance is subtle and in places implicit (ugh).
- *
- * Don't rely on Looper's sendMessage/handleMessage providing
- * release/acquire semantics for any data not actually in the Message.
- * Data going from surfaceflinger to binder threads needs to be
- * synchronized explicitly.
- *
- * Barrier open/wait do provide release/acquire semantics. This provides
- * implicit synchronization for data coming back from binder to
- * surfaceflinger threads.
- */
-
- sp<IGraphicBufferProducer> impl;
- sp<Looper> looper;
- status_t result;
- bool exitPending;
- bool exitRequested;
- Barrier barrier;
- uint32_t code;
- Parcel const* data;
- Parcel* reply;
-
- enum {
- MSG_API_CALL,
- MSG_EXIT
- };
-
- /*
- * Called on surfaceflinger thread. This is called by our "fake"
- * BpGraphicBufferProducer. We package the data and reply Parcel and
- * forward them to the binder thread.
- */
- virtual status_t transact(uint32_t code,
- const Parcel& data, Parcel* reply, uint32_t /* flags */) {
- this->code = code;
- this->data = &data;
- this->reply = reply;
- if (exitPending) {
- // if we've exited, we run the message synchronously right here.
- // note (JH): as far as I can tell from looking at the code, this
- // never actually happens. if it does, i'm not sure if it happens
- // on the surfaceflinger or binder thread.
- handleMessage(Message(MSG_API_CALL));
- } else {
- barrier.close();
- // Prevent stores to this->{code, data, reply} from being
- // reordered later than the construction of Message.
- atomic_thread_fence(memory_order_release);
- looper->sendMessage(this, Message(MSG_API_CALL));
- barrier.wait();
- }
- return result;
- }
-
- /*
- * here we run on the binder thread. All we've got to do is
- * call the real BpGraphicBufferProducer.
- */
- virtual void handleMessage(const Message& message) {
- int what = message.what;
- // Prevent reads below from happening before the read from Message
- atomic_thread_fence(memory_order_acquire);
- if (what == MSG_API_CALL) {
- result = IInterface::asBinder(impl)->transact(code, data[0], reply);
- barrier.open();
- } else if (what == MSG_EXIT) {
- exitRequested = true;
- }
- }
-
-public:
- explicit GraphicProducerWrapper(const sp<IGraphicBufferProducer>& impl)
- : impl(impl),
- looper(new Looper(true)),
- result(NO_ERROR),
- exitPending(false),
- exitRequested(false),
- code(0),
- data(NULL),
- reply(NULL)
- {}
-
- // Binder thread
- status_t waitForResponse() {
- do {
- looper->pollOnce(-1);
- } while (!exitRequested);
- return result;
- }
-
- // Client thread
- void exit(status_t result) {
- this->result = result;
- exitPending = true;
- // Ensure this->result is visible to the binder thread before it
- // handles the message.
- atomic_thread_fence(memory_order_release);
- looper->sendMessage(this, Message(MSG_EXIT));
- }
-};
-
-
-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) {
-
- if (CC_UNLIKELY(display == 0))
- return BAD_VALUE;
-
- if (CC_UNLIKELY(producer == 0))
- return BAD_VALUE;
-
- // 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;
- }
-
- class MessageCaptureScreen : public MessageBase {
- SurfaceFlinger* flinger;
- sp<IBinder> display;
- 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)
- {
- }
- 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);
- static_cast<GraphicProducerWrapper*>(IInterface::asBinder(producer).get())->exit(result);
- return true;
- }
- };
-
- // this creates a "fake" BBinder which will serve as a "fake" remote
- // binder to receive the marshaled calls and forward them to the
- // real remote (a BpGraphicBufferProducer)
- sp<GraphicProducerWrapper> wrapper = new GraphicProducerWrapper(producer);
-
- // 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);
-
- status_t res = postMessageAsync(msg);
- if (res == NO_ERROR) {
- res = wrapper->waitForResponse();
- }
- 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)
-{
- 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;
-
- // 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));
- }
-
- // 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.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);
- }
-
- // make sure to clear all GL error flags
- engine.checkErrors();
-
- // set-up our viewport
- engine.setViewportAndProjection(
- reqWidth, reqHeight, sourceCrop, hw_h, yswap, rotation);
- 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);
- });
- }
-
- // compositionComplete is needed for older driver
- 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)
-{
- 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());
- });
- }
-
- if (!isLocalScreenshot && secureLayerIsVisible) {
- ALOGW("FB is protected: PERMISSION_DENIED");
- return PERMISSION_DENIED;
- }
-
- // create a surface (because we're a producer, and we need to
- // dequeue/queue a buffer)
- sp<Surface> sur = new Surface(producer, false);
- ANativeWindow* window = sur.get();
-
- status_t result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
- if (result == NO_ERROR) {
- uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
- GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
-
- int err = 0;
- err = native_window_set_buffers_dimensions(window, reqWidth, reqHeight);
- 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);
-
- if (err == NO_ERROR) {
- ANativeWindowBuffer* buffer;
- /* TODO: Once we have the sync framework everywhere this can use
- * server-side waits on the fence that dequeueBuffer returns.
- */
- result = native_window_dequeue_buffer_and_wait(window, &buffer);
- if (result == NO_ERROR) {
- int syncFd = -1;
- // create an EGLImage from the buffer so we can later
- // turn it into a texture
- EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT,
- EGL_NATIVE_BUFFER_ANDROID, buffer, NULL);
- if (image != EGL_NO_IMAGE_KHR) {
- // this binds the given EGLImage as a framebuffer for the
- // duration of this scope.
- RenderEngine::BindImageAsFramebuffer imageBond(getRenderEngine(), image);
- if (imageBond.getStatus() == NO_ERROR) {
- // this will in fact render into our dequeued buffer
- // 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);
-
- // 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
- // wait on it directly.
- EGLSyncKHR sync;
- if (!DEBUG_SCREENSHOTS) {
- sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
- // native fence fd will not be populated until flush() is done.
- getRenderEngine().flush();
- } else {
- sync = EGL_NO_SYNC_KHR;
- }
- if (sync != EGL_NO_SYNC_KHR) {
- // get the sync fd
- syncFd = eglDupNativeFenceFDANDROID(mEGLDisplay, sync);
- if (syncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
- ALOGW("captureScreen: failed to dup sync khr object");
- syncFd = -1;
- }
- eglDestroySyncKHR(mEGLDisplay, sync);
- } else {
- // fallback path
- sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL);
- if (sync != EGL_NO_SYNC_KHR) {
- EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync,
- EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 2000000000 /*2 sec*/);
- EGLint eglErr = eglGetError();
- if (result == EGL_TIMEOUT_EXPIRED_KHR) {
- ALOGW("captureScreen: fence wait timed out");
- } else {
- ALOGW_IF(eglErr != EGL_SUCCESS,
- "captureScreen: error waiting on EGL fence: %#x", eglErr);
- }
- eglDestroySyncKHR(mEGLDisplay, sync);
- } else {
- ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError());
- }
- }
- 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);
- delete [] pixels;
- }
-
- } else {
- ALOGE("got GL_FRAMEBUFFER_COMPLETE_OES error while taking screenshot");
- result = INVALID_OPERATION;
- window->cancelBuffer(window, buffer, syncFd);
- buffer = NULL;
- }
- // destroy our image
- eglDestroyImageKHR(mEGLDisplay, image);
- } else {
- result = BAD_VALUE;
- }
- if (buffer) {
- // queueBuffer takes ownership of syncFd
- result = window->queueBuffer(window, buffer, syncFd);
- }
- }
- } else {
- result = BAD_VALUE;
- }
- native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
- }
-
- return result;
-}
-
-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) {
- 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++) {
- if (p[x] != 0xFF000000) return;
- }
- }
- ALOGE("*** we just took a black screenshot ***\n"
- "requested minz=%d, maxz=%d, layerStack=%d",
- minLayerZ, maxLayerZ, hw->getLayerStack());
- size_t i = 0;
- for (const auto& layer : mDrawingState.layersSortedByZ) {
- 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++;
- });
- }
- }
- }
-}
-
-// ---------------------------------------------------------------------------
-
-void SurfaceFlinger::State::traverseInZOrder(const LayerVector::Visitor& visitor) const {
- layersSortedByZ.traverseInZOrder(stateSet, visitor);
-}
-
-void SurfaceFlinger::State::traverseInReverseZOrder(const LayerVector::Visitor& visitor) const {
- layersSortedByZ.traverseInReverseZOrder(stateSet, visitor);
-}
-
-}; // 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/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..590ab96
--- /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/wmtrace/layers_trace.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..bf37e1e
--- /dev/null
+++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
@@ -0,0 +1,288 @@
+/*
+ * 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;
+
+ int32_t lz = lhs->z;
+ int32_t rz = rhs->z;
+ if (lz != rz) {
+ return (lz > rz) ? 1 : -1;
+ }
+
+ 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..be4127c 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": "LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*"
}
-}
\ 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..ff81dc9 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -14,26 +14,138 @@
* limitations under the License.
*/
+#include <algorithm>
+#include <functional>
+#include <limits>
+#include <ostream>
+
#include <gtest/gtest.h>
#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 <ui/Rect.h>
+#include <utils/String8.h>
#include <math.h>
+#include <math/vec3.h>
namespace android {
+namespace {
+
+struct Color {
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+ uint8_t a;
+
+ static const Color RED;
+ static const Color GREEN;
+ static const Color BLUE;
+ static const Color WHITE;
+ static const Color BLACK;
+ static const Color TRANSPARENT;
+};
+
+const Color Color::RED{255, 0, 0, 255};
+const Color Color::GREEN{0, 255, 0, 255};
+const Color Color::BLUE{0, 0, 255, 255};
+const Color Color::WHITE{255, 255, 255, 255};
+const Color Color::BLACK{0, 0, 0, 255};
+const Color Color::TRANSPARENT{0, 0, 0, 0};
+
+std::ostream& operator<<(std::ostream& os, const Color& color) {
+ os << int(color.r) << ", " << int(color.g) << ", " << int(color.b) << ", " << int(color.a);
+ return os;
+}
+
+// Fill a region with the specified color.
+void fillBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect, const Color& color) {
+ int32_t x = rect.left;
+ int32_t y = rect.top;
+ int32_t width = rect.right - rect.left;
+ int32_t height = rect.bottom - rect.top;
+
+ if (x < 0) {
+ width += x;
+ x = 0;
+ }
+ if (y < 0) {
+ height += y;
+ y = 0;
+ }
+ if (x + width > buffer.width) {
+ x = std::min(x, buffer.width);
+ width = buffer.width - x;
+ }
+ if (y + height > buffer.height) {
+ y = std::min(y, buffer.height);
+ height = buffer.height - y;
+ }
+
+ for (int32_t j = 0; j < height; j++) {
+ uint8_t* dst = static_cast<uint8_t*>(buffer.bits) + (buffer.stride * (y + j) + x) * 4;
+ for (int32_t i = 0; i < width; i++) {
+ dst[0] = color.r;
+ dst[1] = color.g;
+ dst[2] = color.b;
+ dst[3] = color.a;
+ dst += 4;
+ }
+ }
+}
+
+// Check if a region has the specified color.
+void expectBufferColor(const sp<GraphicBuffer>& outBuffer, uint8_t* pixels, const Rect& rect,
+ const Color& color, uint8_t tolerance) {
+ int32_t x = rect.left;
+ int32_t y = rect.top;
+ int32_t width = rect.right - rect.left;
+ int32_t height = rect.bottom - rect.top;
+
+ int32_t bufferWidth = int32_t(outBuffer->getWidth());
+ int32_t bufferHeight = int32_t(outBuffer->getHeight());
+ if (x + width > bufferWidth) {
+ x = std::min(x, bufferWidth);
+ width = bufferWidth - x;
+ }
+ if (y + height > bufferHeight) {
+ y = std::min(y, bufferHeight);
+ height = bufferHeight - y;
+ }
+
+ auto colorCompare = [tolerance](uint8_t a, uint8_t b) {
+ uint8_t tmp = a >= b ? a - b : b - a;
+ return tmp <= tolerance;
+ };
+ for (int32_t j = 0; j < height; j++) {
+ const uint8_t* src = pixels + (outBuffer->getStride() * (y + j) + x) * 4;
+ for (int32_t i = 0; i < width; i++) {
+ const uint8_t expected[4] = {color.r, color.g, color.b, color.a};
+ EXPECT_TRUE(std::equal(src, src + 4, expected, colorCompare))
+ << "pixel @ (" << x + i << ", " << y + j << "): "
+ << "expected (" << color << "), "
+ << "got (" << Color{src[0], src[1], src[2], src[3]} << ")";
+ src += 4;
+ }
+ }
+}
+
+} // anonymous namespace
+
+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) {
+static void fillSurfaceRGBA8(const sp<SurfaceControl>& sc, uint8_t r, uint8_t g, uint8_t b,
+ bool unlock = true) {
ANativeWindow_Buffer outBuffer;
sp<Surface> s = sc->getSurface();
ASSERT_TRUE(s != NULL);
@@ -41,7 +153,7 @@
uint8_t* img = reinterpret_cast<uint8_t*>(outBuffer.bits);
for (int y = 0; y < outBuffer.height; y++) {
for (int x = 0; x < outBuffer.width; x++) {
- uint8_t* pixel = img + (4 * (y*outBuffer.stride + x));
+ uint8_t* pixel = img + (4 * (y * outBuffer.stride + x));
pixel[0] = r;
pixel[1] = g;
pixel[2] = b;
@@ -57,67 +169,1310 @@
// individual pixel values for testing purposes.
class ScreenCapture : public RefBase {
public:
- static void captureScreen(sp<ScreenCapture>* sc) {
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer);
- sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
+ static void captureScreen(sp<ScreenCapture>* sc, int32_t minLayerZ = 0,
+ int32_t maxLayerZ = std::numeric_limits<int32_t>::max()) {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- sp<IBinder> display(sf->getBuiltInDisplay(
- ISurfaceComposer::eDisplayIdMain));
- SurfaceComposerClient::openGlobalTransaction();
- SurfaceComposerClient::closeGlobalTransaction(true);
- ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(), 0, 0,
- 0, INT_MAX, false));
- *sc = new ScreenCapture(cpuConsumer);
+ sp<IBinder> display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+ SurfaceComposerClient::Transaction().apply(true);
+
+ sp<GraphicBuffer> outBuffer;
+ ASSERT_EQ(NO_ERROR,
+ sf->captureScreen(display, &outBuffer, Rect(), 0, 0, minLayerZ, maxLayerZ,
+ false));
+ *sc = new ScreenCapture(outBuffer);
+ }
+
+ static void captureLayers(std::unique_ptr<ScreenCapture>* sc, sp<IBinder>& parentHandle,
+ Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) {
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ SurfaceComposerClient::Transaction().apply(true);
+
+ sp<GraphicBuffer> outBuffer;
+ ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, &outBuffer, crop, frameScale));
+ *sc = std::make_unique<ScreenCapture>(outBuffer);
+ }
+
+ void expectColor(const Rect& rect, const Color& color, uint8_t tolerance = 0) {
+ ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
+ expectBufferColor(mOutBuffer, mPixels, rect, color, tolerance);
+ }
+
+ void expectBorder(const Rect& rect, const Color& color, uint8_t tolerance = 0) {
+ ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
+ const bool leftBorder = rect.left > 0;
+ const bool topBorder = rect.top > 0;
+ const bool rightBorder = rect.right < int32_t(mOutBuffer->getWidth());
+ const bool bottomBorder = rect.bottom < int32_t(mOutBuffer->getHeight());
+
+ if (topBorder) {
+ Rect top(rect.left, rect.top - 1, rect.right, rect.top);
+ if (leftBorder) {
+ top.left -= 1;
+ }
+ if (rightBorder) {
+ top.right += 1;
+ }
+ expectColor(top, color, tolerance);
+ }
+ if (leftBorder) {
+ Rect left(rect.left - 1, rect.top, rect.left, rect.bottom);
+ expectColor(left, color, tolerance);
+ }
+ if (rightBorder) {
+ Rect right(rect.right, rect.top, rect.right + 1, rect.bottom);
+ expectColor(right, color, tolerance);
+ }
+ if (bottomBorder) {
+ Rect bottom(rect.left, rect.bottom, rect.right, rect.bottom + 1);
+ if (leftBorder) {
+ bottom.left -= 1;
+ }
+ if (rightBorder) {
+ bottom.right += 1;
+ }
+ expectColor(bottom, color, tolerance);
+ }
+ }
+
+ void expectQuadrant(const Rect& rect, const Color& topLeft, const Color& topRight,
+ const Color& bottomLeft, const Color& bottomRight, bool filtered = false,
+ uint8_t tolerance = 0) {
+ ASSERT_TRUE((rect.right - rect.left) % 2 == 0 && (rect.bottom - rect.top) % 2 == 0);
+
+ const int32_t centerX = rect.left + (rect.right - rect.left) / 2;
+ const int32_t centerY = rect.top + (rect.bottom - rect.top) / 2;
+ // avoid checking borders due to unspecified filtering behavior
+ const int32_t offsetX = filtered ? 2 : 0;
+ const int32_t offsetY = filtered ? 2 : 0;
+ expectColor(Rect(rect.left, rect.top, centerX - offsetX, centerY - offsetY), topLeft,
+ tolerance);
+ expectColor(Rect(centerX + offsetX, rect.top, rect.right, centerY - offsetY), topRight,
+ tolerance);
+ expectColor(Rect(rect.left, centerY + offsetY, centerX - offsetX, rect.bottom), bottomLeft,
+ tolerance);
+ expectColor(Rect(centerX + offsetX, centerY + offsetY, rect.right, rect.bottom),
+ bottomRight, tolerance);
}
void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) {
- ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format);
- const uint8_t* img = static_cast<const uint8_t*>(mBuf.data);
- const uint8_t* pixel = img + (4 * (y * mBuf.stride + x));
+ ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
+ const uint8_t* pixel = mPixels + (4 * (y * mOutBuffer->getStride() + 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]));
+ "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 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); }
+
+ ScreenCapture(const sp<GraphicBuffer>& outBuffer) : mOutBuffer(outBuffer) {
+ mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&mPixels));
}
- 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);
- }
+ ~ScreenCapture() { mOutBuffer->unlock(); }
private:
- ScreenCapture(const sp<CpuConsumer>& cc) :
- mCC(cc) {
- EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuf));
- }
-
- ~ScreenCapture() {
- mCC->unlockBuffer(mBuf);
- }
-
- sp<CpuConsumer> mCC;
- CpuConsumer::LockedBuffer mBuf;
+ sp<GraphicBuffer> mOutBuffer;
+ uint8_t* mPixels = NULL;
};
-class LayerUpdateTest : public ::testing::Test {
+class LayerTransactionTest : public ::testing::Test {
+protected:
+ void SetUp() override {
+ mClient = new SurfaceComposerClient;
+ ASSERT_EQ(NO_ERROR, mClient->initCheck()) << "failed to create SurfaceComposerClient";
+
+ ASSERT_NO_FATAL_FAILURE(SetUpDisplay());
+ }
+
+ sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height,
+ uint32_t flags = 0) {
+ auto layer =
+ mClient->createSurface(String8(name), width, height, PIXEL_FORMAT_RGBA_8888, flags);
+ EXPECT_NE(nullptr, layer.get()) << "failed to create SurfaceControl";
+
+ status_t error = Transaction()
+ .setLayerStack(layer, mDisplayLayerStack)
+ .setLayer(layer, mLayerZBase)
+ .apply();
+ if (error != NO_ERROR) {
+ ADD_FAILURE() << "failed to initialize SurfaceControl";
+ layer.clear();
+ }
+
+ return layer;
+ }
+
+ ANativeWindow_Buffer getLayerBuffer(const sp<SurfaceControl>& layer) {
+ // wait for previous transactions (such as setSize) to complete
+ Transaction().apply(true);
+
+ ANativeWindow_Buffer buffer = {};
+ EXPECT_EQ(NO_ERROR, layer->getSurface()->lock(&buffer, nullptr));
+
+ return buffer;
+ }
+
+ void postLayerBuffer(const sp<SurfaceControl>& layer) {
+ ASSERT_EQ(NO_ERROR, layer->getSurface()->unlockAndPost());
+
+ // wait for the newly posted buffer to be latched
+ waitForLayerBuffers();
+ }
+
+ void fillLayerColor(const sp<SurfaceControl>& layer, const Color& color) {
+ ANativeWindow_Buffer buffer;
+ ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer));
+ fillBufferColor(buffer, Rect(0, 0, buffer.width, buffer.height), color);
+ postLayerBuffer(layer);
+ }
+
+ void fillLayerQuadrant(const sp<SurfaceControl>& layer, const Color& topLeft,
+ const Color& topRight, const Color& bottomLeft,
+ const Color& bottomRight) {
+ ANativeWindow_Buffer buffer;
+ ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer));
+ ASSERT_TRUE(buffer.width % 2 == 0 && buffer.height % 2 == 0);
+
+ const int32_t halfW = buffer.width / 2;
+ const int32_t halfH = buffer.height / 2;
+ fillBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft);
+ fillBufferColor(buffer, Rect(halfW, 0, buffer.width, halfH), topRight);
+ fillBufferColor(buffer, Rect(0, halfH, halfW, buffer.height), bottomLeft);
+ fillBufferColor(buffer, Rect(halfW, halfH, buffer.width, buffer.height), bottomRight);
+
+ postLayerBuffer(layer);
+ }
+
+ sp<ScreenCapture> screenshot() {
+ sp<ScreenCapture> screenshot;
+ ScreenCapture::captureScreen(&screenshot, mLayerZBase);
+ return screenshot;
+ }
+
+ sp<SurfaceComposerClient> mClient;
+
+ sp<IBinder> mDisplay;
+ uint32_t mDisplayWidth;
+ uint32_t mDisplayHeight;
+ uint32_t mDisplayLayerStack;
+
+ // leave room for ~256 layers
+ const int32_t mLayerZBase = std::numeric_limits<int32_t>::max() - 256;
+
+private:
+ void SetUpDisplay() {
+ mDisplay = mClient->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain);
+ ASSERT_NE(nullptr, mDisplay.get()) << "failed to get built-in display";
+
+ // get display width/height
+ DisplayInfo info;
+ SurfaceComposerClient::getDisplayInfo(mDisplay, &info);
+ mDisplayWidth = info.w;
+ mDisplayHeight = info.h;
+
+ // After a new buffer is queued, SurfaceFlinger is notified and will
+ // latch the new buffer on next vsync. Let's heuristically wait for 3
+ // vsyncs.
+ mBufferPostDelay = int32_t(1e6 / info.fps) * 3;
+
+ mDisplayLayerStack = 0;
+ // set layer stack (b/68888219)
+ Transaction t;
+ t.setDisplayLayerStack(mDisplay, mDisplayLayerStack);
+ t.apply();
+ }
+
+ void waitForLayerBuffers() { usleep(mBufferPostDelay); }
+
+ int32_t mBufferPostDelay;
+};
+
+TEST_F(LayerTransactionTest, SetPositionBasic) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ {
+ SCOPED_TRACE("default position");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+
+ Transaction().setPosition(layer, 5, 10).apply();
+ {
+ SCOPED_TRACE("new position");
+ auto shot = screenshot();
+ shot->expectColor(Rect(5, 10, 37, 42), Color::RED);
+ shot->expectBorder(Rect(5, 10, 37, 42), Color::BLACK);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetPositionRounding) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ // GLES requires only 4 bits of subpixel precision during rasterization
+ // XXX GLES composition does not match HWC composition due to precision
+ // loss (b/69315223)
+ const float epsilon = 1.0f / 16.0f;
+ Transaction().setPosition(layer, 0.5f - epsilon, 0.5f - epsilon).apply();
+ {
+ SCOPED_TRACE("rounding down");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ Transaction().setPosition(layer, 0.5f + epsilon, 0.5f + epsilon).apply();
+ {
+ SCOPED_TRACE("rounding up");
+ screenshot()->expectColor(Rect(1, 1, 33, 33), Color::RED);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetPositionOutOfBounds) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ Transaction().setPosition(layer, -32, -32).apply();
+ {
+ SCOPED_TRACE("negative coordinates");
+ screenshot()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+ }
+
+ Transaction().setPosition(layer, mDisplayWidth, mDisplayHeight).apply();
+ {
+ SCOPED_TRACE("positive coordinates");
+ screenshot()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetPositionPartiallyOutOfBounds) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ // partially out of bounds
+ Transaction().setPosition(layer, -30, -30).apply();
+ {
+ SCOPED_TRACE("negative coordinates");
+ screenshot()->expectColor(Rect(0, 0, 2, 2), Color::RED);
+ }
+
+ Transaction().setPosition(layer, mDisplayWidth - 2, mDisplayHeight - 2).apply();
+ {
+ SCOPED_TRACE("positive coordinates");
+ screenshot()->expectColor(Rect(mDisplayWidth - 2, mDisplayHeight - 2, mDisplayWidth,
+ mDisplayHeight),
+ Color::RED);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetPositionWithResize) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ // setPosition is applied immediately by default, with or without resize
+ // pending
+ Transaction().setPosition(layer, 5, 10).setSize(layer, 64, 64).apply();
+ {
+ SCOPED_TRACE("resize pending");
+ auto shot = screenshot();
+ shot->expectColor(Rect(5, 10, 37, 42), Color::RED);
+ shot->expectBorder(Rect(5, 10, 37, 42), Color::BLACK);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ {
+ SCOPED_TRACE("resize applied");
+ screenshot()->expectColor(Rect(5, 10, 69, 74), Color::RED);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetPositionWithNextResize) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ // request setPosition to be applied with the next resize
+ Transaction().setPosition(layer, 5, 10).setGeometryAppliesWithResize(layer).apply();
+ {
+ SCOPED_TRACE("new position pending");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ Transaction().setPosition(layer, 15, 20).apply();
+ {
+ SCOPED_TRACE("pending new position modified");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ Transaction().setSize(layer, 64, 64).apply();
+ {
+ SCOPED_TRACE("resize pending");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ // finally resize and latch the buffer
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ {
+ SCOPED_TRACE("new position applied");
+ screenshot()->expectColor(Rect(15, 20, 79, 84), Color::RED);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetPositionWithNextResizeScaleToWindow) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ // setPosition is not immediate even with SCALE_TO_WINDOW override
+ Transaction()
+ .setPosition(layer, 5, 10)
+ .setSize(layer, 64, 64)
+ .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
+ .setGeometryAppliesWithResize(layer)
+ .apply();
+ {
+ SCOPED_TRACE("new position pending");
+ screenshot()->expectColor(Rect(0, 0, 64, 64), Color::RED);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ {
+ SCOPED_TRACE("new position applied");
+ screenshot()->expectColor(Rect(5, 10, 69, 74), Color::RED);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetSizeBasic) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ Transaction().setSize(layer, 64, 64).apply();
+ {
+ SCOPED_TRACE("resize pending");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ {
+ SCOPED_TRACE("resize applied");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 64, 64), Color::RED);
+ shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetSizeInvalid) {
+ // cannot test robustness against invalid sizes (zero or really huge)
+}
+
+TEST_F(LayerTransactionTest, SetSizeWithScaleToWindow) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ // setSize is immediate with SCALE_TO_WINDOW, unlike setPosition
+ Transaction()
+ .setSize(layer, 64, 64)
+ .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
+ .apply();
+ screenshot()->expectColor(Rect(0, 0, 64, 64), Color::RED);
+}
+
+TEST_F(LayerTransactionTest, SetZBasic) {
+ sp<SurfaceControl> layerR;
+ sp<SurfaceControl> layerG;
+ ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+
+ Transaction().setLayer(layerR, mLayerZBase + 1).apply();
+ {
+ SCOPED_TRACE("layerR");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ Transaction().setLayer(layerG, mLayerZBase + 2).apply();
+ {
+ SCOPED_TRACE("layerG");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::GREEN);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetZNegative) {
+ sp<SurfaceControl> layerR;
+ sp<SurfaceControl> layerG;
+ ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+
+ Transaction().setLayer(layerR, -1).setLayer(layerG, -2).apply();
+ {
+ SCOPED_TRACE("layerR");
+ sp<ScreenCapture> screenshot;
+ ScreenCapture::captureScreen(&screenshot, -2, -1);
+ screenshot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ Transaction().setLayer(layerR, -3).apply();
+ {
+ SCOPED_TRACE("layerG");
+ sp<ScreenCapture> screenshot;
+ ScreenCapture::captureScreen(&screenshot, -3, -1);
+ screenshot->expectColor(Rect(0, 0, 32, 32), Color::GREEN);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetRelativeZBasic) {
+ sp<SurfaceControl> layerR;
+ sp<SurfaceControl> layerG;
+ ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+
+ Transaction()
+ .setPosition(layerG, 16, 16)
+ .setRelativeLayer(layerG, layerR->getHandle(), 1)
+ .apply();
+ {
+ SCOPED_TRACE("layerG above");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 16, 16), Color::RED);
+ shot->expectColor(Rect(16, 16, 48, 48), Color::GREEN);
+ }
+
+ Transaction().setRelativeLayer(layerG, layerR->getHandle(), -1).apply();
+ {
+ SCOPED_TRACE("layerG below");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectColor(Rect(32, 32, 48, 48), Color::GREEN);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetRelativeZNegative) {
+ sp<SurfaceControl> layerR;
+ sp<SurfaceControl> layerG;
+ sp<SurfaceControl> layerB;
+ ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+ ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE));
+
+ // layerR = mLayerZBase, layerG = layerR - 1, layerB = -2
+ Transaction().setRelativeLayer(layerG, layerR->getHandle(), -1).setLayer(layerB, -2).apply();
+
+ sp<ScreenCapture> screenshot;
+ // only layerB is in this range
+ ScreenCapture::captureScreen(&screenshot, -2, -1);
+ screenshot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
+}
+
+TEST_F(LayerTransactionTest, SetRelativeZGroup) {
+ sp<SurfaceControl> layerR;
+ sp<SurfaceControl> layerG;
+ sp<SurfaceControl> layerB;
+ ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+ ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE));
+
+ // layerR = 0, layerG = layerR + 3, layerB = 2
+ Transaction()
+ .setPosition(layerG, 8, 8)
+ .setRelativeLayer(layerG, layerR->getHandle(), 3)
+ .setPosition(layerB, 16, 16)
+ .setLayer(layerB, mLayerZBase + 2)
+ .apply();
+ {
+ SCOPED_TRACE("(layerR < layerG) < layerB");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 8, 8), Color::RED);
+ shot->expectColor(Rect(8, 8, 16, 16), Color::GREEN);
+ shot->expectColor(Rect(16, 16, 48, 48), Color::BLUE);
+ }
+
+ // layerR = 4, layerG = layerR + 3, layerB = 2
+ Transaction().setLayer(layerR, mLayerZBase + 4).apply();
+ {
+ SCOPED_TRACE("layerB < (layerR < layerG)");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 8, 8), Color::RED);
+ shot->expectColor(Rect(8, 8, 40, 40), Color::GREEN);
+ shot->expectColor(Rect(40, 40, 48, 48), Color::BLUE);
+ }
+
+ // layerR = 4, layerG = layerR - 3, layerB = 2
+ Transaction().setRelativeLayer(layerG, layerR->getHandle(), -3).apply();
+ {
+ SCOPED_TRACE("layerB < (layerG < layerR)");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectColor(Rect(32, 32, 40, 40), Color::GREEN);
+ shot->expectColor(Rect(40, 40, 48, 48), Color::BLUE);
+ }
+
+ // restore to absolute z
+ // layerR = 4, layerG = 0, layerB = 2
+ Transaction().setLayer(layerG, mLayerZBase).apply();
+ {
+ SCOPED_TRACE("layerG < layerB < layerR");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectColor(Rect(32, 32, 48, 48), Color::BLUE);
+ }
+
+ // layerR should not affect layerG anymore
+ // layerR = 1, layerG = 0, layerB = 2
+ Transaction().setLayer(layerR, mLayerZBase + 1).apply();
+ {
+ SCOPED_TRACE("layerG < layerR < layerB");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 16, 16), Color::RED);
+ shot->expectColor(Rect(16, 16, 48, 48), Color::BLUE);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetRelativeZBug64572777) {
+ sp<SurfaceControl> layerR;
+ sp<SurfaceControl> layerG;
+
+ ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+
+ Transaction()
+ .setPosition(layerG, 16, 16)
+ .setRelativeLayer(layerG, layerR->getHandle(), 1)
+ .apply();
+
+ mClient->destroySurface(layerG->getHandle());
+ // layerG should have been removed
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+}
+
+TEST_F(LayerTransactionTest, SetFlagsHidden) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ Transaction().setFlags(layer, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden).apply();
+ {
+ SCOPED_TRACE("layer hidden");
+ screenshot()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+ }
+
+ Transaction().setFlags(layer, 0, layer_state_t::eLayerHidden).apply();
+ {
+ SCOPED_TRACE("layer shown");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetFlagsOpaque) {
+ const Color translucentRed = {100, 0, 0, 100};
+ sp<SurfaceControl> layerR;
+ sp<SurfaceControl> layerG;
+ ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, translucentRed));
+ ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+
+ Transaction()
+ .setLayer(layerR, mLayerZBase + 1)
+ .setFlags(layerR, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque)
+ .apply();
+ {
+ SCOPED_TRACE("layerR opaque");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), {100, 0, 0, 255});
+ }
+
+ Transaction().setFlags(layerR, 0, layer_state_t::eLayerOpaque).apply();
+ {
+ SCOPED_TRACE("layerR translucent");
+ const uint8_t g = uint8_t(255 - translucentRed.a);
+ screenshot()->expectColor(Rect(0, 0, 32, 32), {100, g, 0, 255});
+ }
+}
+
+TEST_F(LayerTransactionTest, SetFlagsSecure) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+ sp<GraphicBuffer> outBuffer;
+ Transaction()
+ .setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure)
+ .apply(true);
+ ASSERT_EQ(PERMISSION_DENIED,
+ composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, mLayerZBase, mLayerZBase,
+ false));
+
+ Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true);
+ ASSERT_EQ(NO_ERROR,
+ composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, mLayerZBase, mLayerZBase,
+ false));
+}
+
+TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic) {
+ const Rect top(0, 0, 32, 16);
+ const Rect bottom(0, 16, 32, 32);
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+
+ ANativeWindow_Buffer buffer;
+ ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer));
+ ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, top, Color::TRANSPARENT));
+ ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, bottom, Color::RED));
+ // setTransparentRegionHint always applies to the following buffer
+ Transaction().setTransparentRegionHint(layer, Region(top)).apply();
+ ASSERT_NO_FATAL_FAILURE(postLayerBuffer(layer));
+ {
+ SCOPED_TRACE("top transparent");
+ auto shot = screenshot();
+ shot->expectColor(top, Color::BLACK);
+ shot->expectColor(bottom, Color::RED);
+ }
+
+ Transaction().setTransparentRegionHint(layer, Region(bottom)).apply();
+ {
+ SCOPED_TRACE("transparent region hint pending");
+ auto shot = screenshot();
+ shot->expectColor(top, Color::BLACK);
+ shot->expectColor(bottom, Color::RED);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer));
+ ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, top, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, bottom, Color::TRANSPARENT));
+ ASSERT_NO_FATAL_FAILURE(postLayerBuffer(layer));
+ {
+ SCOPED_TRACE("bottom transparent");
+ auto shot = screenshot();
+ shot->expectColor(top, Color::RED);
+ shot->expectColor(bottom, Color::BLACK);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetTransparentRegionHintOutOfBounds) {
+ sp<SurfaceControl> layerTransparent;
+ sp<SurfaceControl> layerR;
+ ASSERT_NO_FATAL_FAILURE(layerTransparent = createLayer("test transparent", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
+
+ // check that transparent region hint is bound by the layer size
+ Transaction()
+ .setTransparentRegionHint(layerTransparent,
+ Region(Rect(0, 0, mDisplayWidth, mDisplayHeight)))
+ .setPosition(layerR, 16, 16)
+ .setLayer(layerR, mLayerZBase + 1)
+ .apply();
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerTransparent, Color::TRANSPARENT));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+ screenshot()->expectColor(Rect(16, 16, 48, 48), Color::RED);
+}
+
+TEST_F(LayerTransactionTest, SetAlphaBasic) {
+ sp<SurfaceControl> layer1;
+ sp<SurfaceControl> layer2;
+ ASSERT_NO_FATAL_FAILURE(layer1 = createLayer("test 1", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(layer2 = createLayer("test 2", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer1, {64, 0, 0, 255}));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer2, {0, 64, 0, 255}));
+
+ Transaction()
+ .setAlpha(layer1, 0.25f)
+ .setAlpha(layer2, 0.75f)
+ .setPosition(layer2, 16, 0)
+ .setLayer(layer2, mLayerZBase + 1)
+ .apply();
+ {
+ auto shot = screenshot();
+ uint8_t r = 16; // 64 * 0.25f
+ uint8_t g = 48; // 64 * 0.75f
+ shot->expectColor(Rect(0, 0, 16, 32), {r, 0, 0, 255});
+ shot->expectColor(Rect(32, 0, 48, 32), {0, g, 0, 255});
+
+ r /= 4; // r * (1.0f - 0.75f)
+ shot->expectColor(Rect(16, 0, 32, 32), {r, g, 0, 255});
+ }
+}
+
+TEST_F(LayerTransactionTest, SetAlphaClamped) {
+ const Color color = {64, 0, 0, 255};
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, color));
+
+ Transaction().setAlpha(layer, 2.0f).apply();
+ {
+ SCOPED_TRACE("clamped to 1.0f");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), color);
+ }
+
+ Transaction().setAlpha(layer, -1.0f).apply();
+ {
+ SCOPED_TRACE("clamped to 0.0f");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetColorBasic) {
+ sp<SurfaceControl> bufferLayer;
+ sp<SurfaceControl> colorLayer;
+ ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(
+ colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor));
+
+ Transaction().setLayer(colorLayer, mLayerZBase + 1).apply();
+ {
+ SCOPED_TRACE("default color");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+
+ const half3 color(15.0f / 255.0f, 51.0f / 255.0f, 85.0f / 255.0f);
+ const Color expected = {15, 51, 85, 255};
+ // this is handwavy, but the precison loss scaled by 255 (8-bit per
+ // channel) should be less than one
+ const uint8_t tolerance = 1;
+ Transaction().setColor(colorLayer, color).apply();
+ {
+ SCOPED_TRACE("new color");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), expected, tolerance);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetColorClamped) {
+ sp<SurfaceControl> colorLayer;
+ ASSERT_NO_FATAL_FAILURE(
+ colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor));
+
+ Transaction().setColor(colorLayer, half3(2.0f, -1.0f, 0.0f)).apply();
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+}
+
+TEST_F(LayerTransactionTest, SetColorWithAlpha) {
+ sp<SurfaceControl> bufferLayer;
+ sp<SurfaceControl> colorLayer;
+ ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(
+ colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor));
+
+ const half3 color(15.0f / 255.0f, 51.0f / 255.0f, 85.0f / 255.0f);
+ const float alpha = 0.25f;
+ const ubyte3 expected((vec3(color) * alpha + vec3(1.0f, 0.0f, 0.0f) * (1.0f - alpha)) * 255.0f);
+ // this is handwavy, but the precison loss scaled by 255 (8-bit per
+ // channel) should be less than one
+ const uint8_t tolerance = 1;
+ Transaction()
+ .setColor(colorLayer, color)
+ .setAlpha(colorLayer, alpha)
+ .setLayer(colorLayer, mLayerZBase + 1)
+ .apply();
+ screenshot()->expectColor(Rect(0, 0, 32, 32), {expected.r, expected.g, expected.b, 255},
+ tolerance);
+}
+
+TEST_F(LayerTransactionTest, SetColorWithBuffer) {
+ sp<SurfaceControl> bufferLayer;
+ ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED));
+
+ // color is ignored
+ Transaction().setColor(bufferLayer, half3(0.0f, 1.0f, 0.0f)).apply();
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+}
+
+TEST_F(LayerTransactionTest, SetLayerStackBasic) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ Transaction().setLayerStack(layer, mDisplayLayerStack + 1).apply();
+ {
+ SCOPED_TRACE("non-existing layer stack");
+ screenshot()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK);
+ }
+
+ Transaction().setLayerStack(layer, mDisplayLayerStack).apply();
+ {
+ SCOPED_TRACE("original layer stack");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetMatrixBasic) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(
+ fillLayerQuadrant(layer, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE));
+
+ Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f).setPosition(layer, 0, 0).apply();
+ {
+ SCOPED_TRACE("IDENTITY");
+ screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, Color::BLUE,
+ Color::WHITE);
+ }
+
+ Transaction().setMatrix(layer, -1.0f, 0.0f, 0.0f, 1.0f).setPosition(layer, 32, 0).apply();
+ {
+ SCOPED_TRACE("FLIP_H");
+ screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::GREEN, Color::RED, Color::WHITE,
+ Color::BLUE);
+ }
+
+ Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, -1.0f).setPosition(layer, 0, 32).apply();
+ {
+ SCOPED_TRACE("FLIP_V");
+ screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::WHITE, Color::RED,
+ Color::GREEN);
+ }
+
+ Transaction().setMatrix(layer, 0.0f, 1.0f, -1.0f, 0.0f).setPosition(layer, 32, 0).apply();
+ {
+ SCOPED_TRACE("ROT_90");
+ screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::RED, Color::WHITE,
+ Color::GREEN);
+ }
+
+ Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).setPosition(layer, 0, 0).apply();
+ {
+ SCOPED_TRACE("SCALE");
+ screenshot()->expectQuadrant(Rect(0, 0, 64, 64), Color::RED, Color::GREEN, Color::BLUE,
+ Color::WHITE, true /* filtered */);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetMatrixRot45) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(
+ fillLayerQuadrant(layer, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE));
+
+ const float rot = M_SQRT1_2; // 45 degrees
+ const float trans = M_SQRT2 * 16.0f;
+ Transaction().setMatrix(layer, rot, rot, -rot, rot).setPosition(layer, trans, 0).apply();
+
+ auto shot = screenshot();
+ // check a 8x8 region inside each color
+ auto get8x8Rect = [](int32_t centerX, int32_t centerY) {
+ const int32_t halfL = 4;
+ return Rect(centerX - halfL, centerY - halfL, centerX + halfL, centerY + halfL);
+ };
+ const int32_t unit = int32_t(trans / 2);
+ shot->expectColor(get8x8Rect(2 * unit, 1 * unit), Color::RED);
+ shot->expectColor(get8x8Rect(3 * unit, 2 * unit), Color::GREEN);
+ shot->expectColor(get8x8Rect(1 * unit, 2 * unit), Color::BLUE);
+ shot->expectColor(get8x8Rect(2 * unit, 3 * unit), Color::WHITE);
+}
+
+TEST_F(LayerTransactionTest, SetMatrixWithResize) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ // setMatrix is applied after any pending resize, unlike setPosition
+ Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).setSize(layer, 64, 64).apply();
+ {
+ SCOPED_TRACE("resize pending");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ {
+ SCOPED_TRACE("resize applied");
+ screenshot()->expectColor(Rect(0, 0, 128, 128), Color::RED);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetMatrixWithScaleToWindow) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ // setMatrix is immediate with SCALE_TO_WINDOW, unlike setPosition
+ Transaction()
+ .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f)
+ .setSize(layer, 64, 64)
+ .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
+ .apply();
+ screenshot()->expectColor(Rect(0, 0, 128, 128), Color::RED);
+}
+
+TEST_F(LayerTransactionTest, SetOverrideScalingModeBasic) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(
+ fillLayerQuadrant(layer, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE));
+
+ // XXX SCALE_CROP is not respected; calling setSize and
+ // setOverrideScalingMode in separate transactions does not work
+ // (b/69315456)
+ Transaction()
+ .setSize(layer, 64, 16)
+ .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
+ .apply();
+ {
+ SCOPED_TRACE("SCALE_TO_WINDOW");
+ screenshot()->expectQuadrant(Rect(0, 0, 64, 16), Color::RED, Color::GREEN, Color::BLUE,
+ Color::WHITE, true /* filtered */);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetCropBasic) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ const Rect crop(8, 8, 24, 24);
+
+ Transaction().setCrop(layer, crop).apply();
+ auto shot = screenshot();
+ shot->expectColor(crop, Color::RED);
+ shot->expectBorder(crop, Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetCropEmpty) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ {
+ SCOPED_TRACE("empty rect");
+ Transaction().setCrop(layer, Rect(8, 8, 8, 8)).apply();
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ {
+ SCOPED_TRACE("negative rect");
+ Transaction().setCrop(layer, Rect(8, 8, 0, 0)).apply();
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetCropOutOfBounds) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ Transaction().setCrop(layer, Rect(-128, -64, 128, 64)).apply();
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetCropWithTranslation) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ const Point position(32, 32);
+ const Rect crop(8, 8, 24, 24);
+ Transaction().setPosition(layer, position.x, position.y).setCrop(layer, crop).apply();
+ auto shot = screenshot();
+ shot->expectColor(crop + position, Color::RED);
+ shot->expectBorder(crop + position, Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetCropWithScale) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ // crop is affected by matrix
+ Transaction()
+ .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f)
+ .setCrop(layer, Rect(8, 8, 24, 24))
+ .apply();
+ auto shot = screenshot();
+ shot->expectColor(Rect(16, 16, 48, 48), Color::RED);
+ shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetCropWithResize) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ // setCrop is applied immediately by default, with or without resize pending
+ Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply();
+ {
+ SCOPED_TRACE("resize pending");
+ auto shot = screenshot();
+ shot->expectColor(Rect(8, 8, 24, 24), Color::RED);
+ shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ {
+ SCOPED_TRACE("resize applied");
+ auto shot = screenshot();
+ shot->expectColor(Rect(8, 8, 16, 16), Color::RED);
+ shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetCropWithNextResize) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ // request setCrop to be applied with the next resize
+ Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setGeometryAppliesWithResize(layer).apply();
+ {
+ SCOPED_TRACE("waiting for next resize");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ Transaction().setCrop(layer, Rect(4, 4, 12, 12)).apply();
+ {
+ SCOPED_TRACE("pending crop modified");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ Transaction().setSize(layer, 16, 16).apply();
+ {
+ SCOPED_TRACE("resize pending");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ // finally resize
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ {
+ SCOPED_TRACE("new crop applied");
+ auto shot = screenshot();
+ shot->expectColor(Rect(4, 4, 12, 12), Color::RED);
+ shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ // setCrop is not immediate even with SCALE_TO_WINDOW override
+ Transaction()
+ .setCrop(layer, Rect(4, 4, 12, 12))
+ .setSize(layer, 16, 16)
+ .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
+ .setGeometryAppliesWithResize(layer)
+ .apply();
+ {
+ SCOPED_TRACE("new crop pending");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 16, 16), Color::RED);
+ shot->expectBorder(Rect(0, 0, 16, 16), Color::BLACK);
+ }
+
+ // XXX crop is never latched without other geometry change (b/69315677)
+ Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply();
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ Transaction().setPosition(layer, 0, 0).apply();
+ {
+ SCOPED_TRACE("new crop applied");
+ auto shot = screenshot();
+ shot->expectColor(Rect(4, 4, 12, 12), Color::RED);
+ shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetFinalCropBasic) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ const Rect crop(8, 8, 24, 24);
+
+ // same as in SetCropBasic
+ Transaction().setFinalCrop(layer, crop).apply();
+ auto shot = screenshot();
+ shot->expectColor(crop, Color::RED);
+ shot->expectBorder(crop, Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetFinalCropEmpty) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ // same as in SetCropEmpty
+ {
+ SCOPED_TRACE("empty rect");
+ Transaction().setFinalCrop(layer, Rect(8, 8, 8, 8)).apply();
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ {
+ SCOPED_TRACE("negative rect");
+ Transaction().setFinalCrop(layer, Rect(8, 8, 0, 0)).apply();
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetFinalCropOutOfBounds) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ // same as in SetCropOutOfBounds
+ Transaction().setFinalCrop(layer, Rect(-128, -64, 128, 64)).apply();
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetFinalCropWithTranslation) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ // final crop is applied post-translation
+ Transaction().setPosition(layer, 16, 16).setFinalCrop(layer, Rect(8, 8, 24, 24)).apply();
+ auto shot = screenshot();
+ shot->expectColor(Rect(16, 16, 24, 24), Color::RED);
+ shot->expectBorder(Rect(16, 16, 24, 24), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetFinalCropWithScale) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ // final crop is not affected by matrix
+ Transaction()
+ .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f)
+ .setFinalCrop(layer, Rect(8, 8, 24, 24))
+ .apply();
+ auto shot = screenshot();
+ shot->expectColor(Rect(8, 8, 24, 24), Color::RED);
+ shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetFinalCropWithResize) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ // same as in SetCropWithResize
+ Transaction().setFinalCrop(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply();
+ {
+ SCOPED_TRACE("resize pending");
+ auto shot = screenshot();
+ shot->expectColor(Rect(8, 8, 24, 24), Color::RED);
+ shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ {
+ SCOPED_TRACE("resize applied");
+ auto shot = screenshot();
+ shot->expectColor(Rect(8, 8, 16, 16), Color::RED);
+ shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetFinalCropWithNextResize) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ // same as in SetCropWithNextResize
+ Transaction()
+ .setFinalCrop(layer, Rect(8, 8, 24, 24))
+ .setGeometryAppliesWithResize(layer)
+ .apply();
+ {
+ SCOPED_TRACE("waiting for next resize");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ Transaction().setFinalCrop(layer, Rect(4, 4, 12, 12)).apply();
+ {
+ SCOPED_TRACE("pending final crop modified");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ Transaction().setSize(layer, 16, 16).apply();
+ {
+ SCOPED_TRACE("resize pending");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ // finally resize
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ {
+ SCOPED_TRACE("new final crop applied");
+ auto shot = screenshot();
+ shot->expectColor(Rect(4, 4, 12, 12), Color::RED);
+ shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+
+ // same as in SetCropWithNextResizeScaleToWindow
+ Transaction()
+ .setFinalCrop(layer, Rect(4, 4, 12, 12))
+ .setSize(layer, 16, 16)
+ .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
+ .setGeometryAppliesWithResize(layer)
+ .apply();
+ {
+ SCOPED_TRACE("new final crop pending");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 16, 16), Color::RED);
+ shot->expectBorder(Rect(0, 0, 16, 16), Color::BLACK);
+ }
+
+ // XXX final crop is never latched without other geometry change (b/69315677)
+ Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply();
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ Transaction().setPosition(layer, 0, 0).apply();
+ {
+ SCOPED_TRACE("new final crop applied");
+ auto shot = screenshot();
+ shot->expectColor(Rect(4, 4, 12, 12), Color::RED);
+ shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK);
+ }
+}
+
+class LayerUpdateTest : public LayerTransactionTest {
protected:
virtual void SetUp() {
mComposerClient = new SurfaceComposerClient;
ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
- sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(
- ISurfaceComposer::eDisplayIdMain));
+ sp<IBinder> display(
+ SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
DisplayInfo info;
SurfaceComposerClient::getDisplayInfo(display, &info);
@@ -125,46 +1480,42 @@
ssize_t displayHeight = info.h;
// Background surface
- mBGSurfaceControl = mComposerClient->createSurface(
- String8("BG Test Surface"), displayWidth, displayHeight,
- PIXEL_FORMAT_RGBA_8888, 0);
+ mBGSurfaceControl =
+ mComposerClient->createSurface(String8("BG Test Surface"), displayWidth,
+ displayHeight, PIXEL_FORMAT_RGBA_8888, 0);
ASSERT_TRUE(mBGSurfaceControl != NULL);
ASSERT_TRUE(mBGSurfaceControl->isValid());
fillSurfaceRGBA8(mBGSurfaceControl, 63, 63, 195);
// Foreground surface
- mFGSurfaceControl = mComposerClient->createSurface(
- String8("FG Test Surface"), 64, 64, PIXEL_FORMAT_RGBA_8888, 0);
+ mFGSurfaceControl = mComposerClient->createSurface(String8("FG Test Surface"), 64, 64,
+ PIXEL_FORMAT_RGBA_8888, 0);
ASSERT_TRUE(mFGSurfaceControl != NULL);
ASSERT_TRUE(mFGSurfaceControl->isValid());
fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
// Synchronization surface
- mSyncSurfaceControl = mComposerClient->createSurface(
- String8("Sync Test Surface"), 1, 1, PIXEL_FORMAT_RGBA_8888, 0);
+ mSyncSurfaceControl = mComposerClient->createSurface(String8("Sync Test Surface"), 1, 1,
+ PIXEL_FORMAT_RGBA_8888, 0);
ASSERT_TRUE(mSyncSurfaceControl != NULL);
ASSERT_TRUE(mSyncSurfaceControl->isValid());
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 +1536,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;
@@ -194,287 +1551,45 @@
sp<SurfaceControl> mSyncSurfaceControl;
};
-TEST_F(LayerUpdateTest, LayerMoveWorks) {
+TEST_F(LayerUpdateTest, RelativesAreNotDetached) {
sp<ScreenCapture> sc;
- {
- SCOPED_TRACE("before move");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(0, 12);
- sc->expectFGColor(75, 75);
- sc->expectBGColor(145, 145);
- }
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(128, 128));
- SurfaceComposerClient::closeGlobalTransaction(true);
- {
- // This should reflect the new position, but not the new color.
- SCOPED_TRACE("after move, before redraw");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
- sc->expectBGColor(75, 75);
- sc->expectFGColor(145, 145);
- }
-
- fillSurfaceRGBA8(mFGSurfaceControl, 63, 195, 63);
+ sp<SurfaceControl> relative = mComposerClient->createSurface(String8("relativeTestSurface"), 10,
+ 10, PIXEL_FORMAT_RGBA_8888, 0);
+ fillSurfaceRGBA8(relative, 10, 10, 10);
waitForPostedBuffers();
- {
- // This should reflect the new position and the new color.
- SCOPED_TRACE("after redraw");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
- sc->expectBGColor(75, 75);
- sc->checkPixel(145, 145, 63, 195, 63);
- }
-}
-TEST_F(LayerUpdateTest, LayerResizeWorks) {
- sp<ScreenCapture> sc;
+ Transaction{}
+ .setRelativeLayer(relative, mFGSurfaceControl->getHandle(), 1)
+ .setPosition(relative, 64, 64)
+ .apply();
+
{
- SCOPED_TRACE("before resize");
+ // The relative should be on top of the FG control.
ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(0, 12);
- sc->expectFGColor(75, 75);
- sc->expectBGColor(145, 145);
+ sc->checkPixel(64, 64, 10, 10, 10);
+ }
+ Transaction{}.detachChildren(mFGSurfaceControl).apply();
+
+ {
+ // Nothing should change at this point.
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(64, 64, 10, 10, 10);
}
- ALOGD("resizing");
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setSize(128, 128));
- SurfaceComposerClient::closeGlobalTransaction(true);
- ALOGD("resized");
- {
- // This should not reflect the new size or color because SurfaceFlinger
- // has not yet received a buffer of the correct size.
- SCOPED_TRACE("after resize, before redraw");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(0, 12);
- sc->expectFGColor(75, 75);
- sc->expectBGColor(145, 145);
- }
+ Transaction{}.hide(relative).apply();
- ALOGD("drawing");
- fillSurfaceRGBA8(mFGSurfaceControl, 63, 195, 63);
- waitForPostedBuffers();
- ALOGD("drawn");
{
- // This should reflect the new size and the new color.
- SCOPED_TRACE("after redraw");
+ // Ensure that the relative was actually hidden, rather than
+ // being left in the detached but visible state.
ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
- sc->checkPixel(75, 75, 63, 195, 63);
- sc->checkPixel(145, 145, 63, 195, 63);
- }
-}
-
-TEST_F(LayerUpdateTest, LayerCropWorks) {
- sp<ScreenCapture> sc;
- {
- SCOPED_TRACE("before crop");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
- sc->expectFGColor(75, 75);
- sc->expectBGColor(145, 145);
- }
-
- SurfaceComposerClient::openGlobalTransaction();
- Rect cropRect(16, 16, 32, 32);
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setCrop(cropRect));
- SurfaceComposerClient::closeGlobalTransaction(true);
- {
- // This should crop the foreground surface.
- SCOPED_TRACE("after crop");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
- sc->expectBGColor(75, 75);
- sc->expectFGColor(95, 80);
- sc->expectFGColor(80, 95);
- sc->expectBGColor(96, 96);
- }
-}
-
-TEST_F(LayerUpdateTest, LayerFinalCropWorks) {
- sp<ScreenCapture> sc;
- {
- SCOPED_TRACE("before crop");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
- 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);
- {
- // This should crop the foreground surface.
- SCOPED_TRACE("after crop");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
- sc->expectBGColor(75, 75);
- sc->expectBGColor(95, 80);
- sc->expectBGColor(80, 95);
- sc->expectBGColor(96, 96);
- }
-}
-
-TEST_F(LayerUpdateTest, LayerSetLayerWorks) {
- sp<ScreenCapture> sc;
- {
- SCOPED_TRACE("before setLayer");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
- sc->expectFGColor(75, 75);
- sc->expectBGColor(145, 145);
- }
-
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT_MAX - 3));
- SurfaceComposerClient::closeGlobalTransaction(true);
- {
- // This should hide the foreground surface beneath the background.
- SCOPED_TRACE("after setLayer");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
- sc->expectBGColor(75, 75);
- sc->expectBGColor(145, 145);
- }
-}
-
-TEST_F(LayerUpdateTest, LayerShowHideWorks) {
- sp<ScreenCapture> sc;
- {
- SCOPED_TRACE("before hide");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
- sc->expectFGColor(75, 75);
- sc->expectBGColor(145, 145);
- }
-
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->hide());
- SurfaceComposerClient::closeGlobalTransaction(true);
- {
- // This should hide the foreground surface.
- SCOPED_TRACE("after hide, before show");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
- sc->expectBGColor(75, 75);
- sc->expectBGColor(145, 145);
- }
-
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->show());
- SurfaceComposerClient::closeGlobalTransaction(true);
- {
- // This should show the foreground surface.
- SCOPED_TRACE("after show");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
- sc->expectFGColor(75, 75);
- sc->expectBGColor(145, 145);
- }
-}
-
-TEST_F(LayerUpdateTest, LayerSetAlphaWorks) {
- sp<ScreenCapture> sc;
- {
- SCOPED_TRACE("before setAlpha");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
- sc->expectFGColor(75, 75);
- sc->expectBGColor(145, 145);
- }
-
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.75f));
- SurfaceComposerClient::closeGlobalTransaction(true);
- {
- // This should set foreground to be 75% opaque.
- SCOPED_TRACE("after setAlpha");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
- sc->checkPixel(75, 75, 162, 63, 96);
- sc->expectBGColor(145, 145);
- }
-}
-
-TEST_F(LayerUpdateTest, LayerSetLayerStackWorks) {
- sp<ScreenCapture> sc;
- {
- SCOPED_TRACE("before setLayerStack");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
- sc->expectFGColor(75, 75);
- sc->expectBGColor(145, 145);
- }
-
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayerStack(1));
- SurfaceComposerClient::closeGlobalTransaction(true);
- {
- // This should hide the foreground surface since it goes to a different
- // layer stack.
- SCOPED_TRACE("after setLayerStack");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
- sc->expectBGColor(75, 75);
- sc->expectBGColor(145, 145);
- }
-}
-
-TEST_F(LayerUpdateTest, LayerSetFlagsWorks) {
- sp<ScreenCapture> sc;
- {
- SCOPED_TRACE("before setFlags");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
- sc->expectFGColor(75, 75);
- sc->expectBGColor(145, 145);
- }
-
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setFlags(
- layer_state_t::eLayerHidden, layer_state_t::eLayerHidden));
- SurfaceComposerClient::closeGlobalTransaction(true);
- {
- // This should hide the foreground surface
- SCOPED_TRACE("after setFlags");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
- sc->expectBGColor(75, 75);
- sc->expectBGColor(145, 145);
- }
-}
-
-TEST_F(LayerUpdateTest, LayerSetMatrixWorks) {
- sp<ScreenCapture> sc;
- {
- SCOPED_TRACE("before setMatrix");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
- sc->expectFGColor(91, 96);
- sc->expectFGColor(96, 101);
- 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);
- {
- SCOPED_TRACE("after setMatrix");
- ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
- sc->expectFGColor(91, 96);
- sc->expectBGColor(96, 91);
- sc->expectBGColor(145, 145);
+ sc->expectFGColor(64, 64);
}
}
class GeometryLatchingTest : public LayerUpdateTest {
protected:
- void EXPECT_INITIAL_STATE(const char * trace) {
+ void EXPECT_INITIAL_STATE(const char* trace) {
SCOPED_TRACE(trace);
ScreenCapture::captureScreen(&sc);
// We find the leading edge of the FG surface.
@@ -482,9 +1597,7 @@
sc->expectBGColor(128, 128);
}
- void lockAndFillFGBuffer() {
- fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63, false);
- }
+ void lockAndFillFGBuffer() { fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63, false); }
void unlockFGBuffer() {
sp<Surface> s = mFGSurfaceControl->getSurface();
@@ -497,65 +1610,18 @@
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");
}
sp<ScreenCapture> sc;
};
-TEST_F(GeometryLatchingTest, SurfacePositionLatching) {
- EXPECT_INITIAL_STATE("before anything");
-
- // 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);
-
- {
- SCOPED_TRACE("After moving surface");
- ScreenCapture::captureScreen(&sc);
- // If we moved, the FG Surface should cover up what was previously BG
- // however if we didn't move the FG wouldn't be large enough now.
- sc->expectFGColor(163, 163);
- }
-
- restoreInitialState();
-
- // 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);
-
- {
- SCOPED_TRACE("While resize is pending");
- ScreenCapture::captureScreen(&sc);
- // This time we shouldn't have moved, so the BG color
- // should still be visible.
- sc->expectBGColor(128, 128);
- }
-
- completeFGResize();
-
- {
- SCOPED_TRACE("After the resize");
- ScreenCapture::captureScreen(&sc);
- // But after the resize completes, we should move
- // and the FG should be visible here.
- sc->expectFGColor(128, 128);
- }
-}
-
class CropLatchingTest : public GeometryLatchingTest {
protected:
void EXPECT_CROPPED_STATE(const char* trace) {
@@ -577,65 +1643,15 @@
}
};
-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);
-
- 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);
-
- EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)");
-
- completeFGResize();
-
- EXPECT_CROPPED_STATE("after the resize finishes");
-}
-
-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);
-
- 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);
-
- EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)");
-
- completeFGResize();
-
- EXPECT_CROPPED_STATE("after the resize finishes");
-}
-
// In this test we ensure that setGeometryAppliesWithResize actually demands
// a buffer of the new size, and not just any size.
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 +1661,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)");
@@ -664,30 +1680,6 @@
EXPECT_CROPPED_STATE("after the resize finishes");
}
-TEST_F(CropLatchingTest, FinalCropLatchingRegressionForb37531386) {
- EXPECT_INITIAL_STATE("before anything");
- // 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);
-
- EXPECT_INITIAL_STATE("after setting crops with geometryAppliesWithResize");
-
- SurfaceComposerClient::openGlobalTransaction();
- mFGSurfaceControl->setFinalCrop(Rect(0, 0, -1, -1));
- SurfaceComposerClient::closeGlobalTransaction(true);
-
- EXPECT_INITIAL_STATE("after setting another crop");
-
- completeFGResize();
-
- EXPECT_RESIZE_STATE("after the resize finishes");
-}
-
TEST_F(LayerUpdateTest, DeferredTransactionTest) {
sp<ScreenCapture> sc;
{
@@ -699,17 +1691,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 +1722,7 @@
}
// 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);
@@ -745,46 +1735,55 @@
}
}
-TEST_F(LayerUpdateTest, LayerSetRelativeLayerWorks) {
+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 adding relative surface");
+ SCOPED_TRACE("before move");
ScreenCapture::captureScreen(&sc);
- sc->expectBGColor(24, 24);
+ sc->expectBGColor(0, 12);
sc->expectFGColor(75, 75);
sc->expectBGColor(145, 145);
}
- auto relativeSurfaceControl = mComposerClient->createSurface(
- String8("Test Surface"), 64, 64, PIXEL_FORMAT_RGBA_8888, 0);
- fillSurfaceRGBA8(relativeSurfaceControl, 255, 177, 177);
- 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);
-
+ 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();
{
- SCOPED_TRACE("after adding relative surface");
ScreenCapture::captureScreen(&sc);
- // our relative surface should be visible now.
- sc->checkPixel(75, 75, 255, 177, 177);
- }
-
- // A call to setLayer will override a call to setRelativeLayer
- SurfaceComposerClient::openGlobalTransaction();
- relativeSurfaceControl->setLayer(0);
- SurfaceComposerClient::closeGlobalTransaction();
-
- {
- SCOPED_TRACE("after set layer");
- ScreenCapture::captureScreen(&sc);
- // now the FG surface should be visible again.
- sc->expectFGColor(75, 75);
+ sc->expectFGColor(1, 1);
}
}
@@ -792,10 +1791,8 @@
protected:
void SetUp() override {
LayerUpdateTest::SetUp();
- mChild = mComposerClient->createSurface(
- String8("Child surface"),
- 10, 10, PIXEL_FORMAT_RGBA_8888,
- 0, mFGSurfaceControl.get());
+ mChild = mComposerClient->createSurface(String8("Child surface"), 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
fillSurfaceRGBA8(mChild, 200, 200, 200);
{
@@ -814,11 +1811,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 +1827,7 @@
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 +1841,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 +1857,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 +1873,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 +1891,7 @@
}
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 +1900,7 @@
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 +1919,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 +1931,7 @@
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 +1939,7 @@
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 +1949,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 +1964,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 +1981,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 +1998,51 @@
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 +2054,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 +2068,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 +2087,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 +2100,9 @@
// 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 +2129,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 +2150,314 @@
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);
+ }
+}
+
+TEST_F(ChildLayerTest, ChildLayerRelativeLayer) {
+ sp<SurfaceControl> relative = mComposerClient->createSurface(String8("Relative surface"), 128,
+ 128, PIXEL_FORMAT_RGBA_8888, 0);
+ fillSurfaceRGBA8(relative, 255, 255, 255);
+
+ Transaction t;
+ t.setLayer(relative, INT32_MAX)
+ .setRelativeLayer(mChild, relative->getHandle(), 1)
+ .setPosition(mFGSurfaceControl, 0, 0)
+ .apply(true);
+
+ // We expect that the child should have been elevated above our
+ // INT_MAX layer even though it's not a child of it.
+ {
+ ScreenCapture::captureScreen(&mCapture);
+ mCapture->expectChildColor(0, 0);
+ mCapture->expectChildColor(9, 9);
+ mCapture->checkPixel(10, 10, 255, 255, 255);
+ }
+}
+
+class ScreenCaptureTest : public LayerUpdateTest {
+protected:
+ std::unique_ptr<ScreenCapture> mCapture;
+};
+
+TEST_F(ScreenCaptureTest, CaptureSingleLayer) {
+ auto bgHandle = mBGSurfaceControl->getHandle();
+ ScreenCapture::captureLayers(&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.
+ ScreenCapture::captureLayers(&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.
+ ScreenCapture::captureLayers(&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.
+ ScreenCapture::captureLayers(&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.
+ ScreenCapture::captureLayers(&mCapture, grandchildHandle);
+ mCapture->checkPixel(0, 0, 50, 50, 50);
+ mCapture->checkPixel(4, 4, 50, 50, 50);
+}
+
+TEST_F(ScreenCaptureTest, CaptureCrop) {
+ sp<SurfaceControl> redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60,
+ PIXEL_FORMAT_RGBA_8888, 0);
+ sp<SurfaceControl> blueLayer =
+ mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888,
+ 0, redLayer.get());
+
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE));
+
+ SurfaceComposerClient::Transaction()
+ .setLayer(redLayer, INT32_MAX - 1)
+ .show(redLayer)
+ .show(blueLayer)
+ .apply(true);
+
+ auto redLayerHandle = redLayer->getHandle();
+
+ // Capturing full screen should have both red and blue are visible.
+ ScreenCapture::captureLayers(&mCapture, redLayerHandle);
+ mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
+ // red area below the blue area
+ mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED);
+ // red area to the right of the blue area
+ mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
+
+ Rect crop = Rect(0, 0, 30, 30);
+ ScreenCapture::captureLayers(&mCapture, redLayerHandle, crop);
+ // Capturing the cropped screen, cropping out the shown red area, should leave only the blue
+ // area visible.
+ mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
+ mCapture->checkPixel(30, 30, 0, 0, 0);
+}
+
+TEST_F(ScreenCaptureTest, CaptureSize) {
+ sp<SurfaceControl> redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60,
+ PIXEL_FORMAT_RGBA_8888, 0);
+ sp<SurfaceControl> blueLayer =
+ mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888,
+ 0, redLayer.get());
+
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE));
+
+ SurfaceComposerClient::Transaction()
+ .setLayer(redLayer, INT32_MAX - 1)
+ .show(redLayer)
+ .show(blueLayer)
+ .apply(true);
+
+ auto redLayerHandle = redLayer->getHandle();
+
+ // Capturing full screen should have both red and blue are visible.
+ ScreenCapture::captureLayers(&mCapture, redLayerHandle);
+ mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
+ // red area below the blue area
+ mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED);
+ // red area to the right of the blue area
+ mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
+
+ ScreenCapture::captureLayers(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5);
+ // Capturing the downsized area (30x30) should leave both red and blue but in a smaller area.
+ mCapture->expectColor(Rect(0, 0, 14, 14), Color::BLUE);
+ // red area below the blue area
+ mCapture->expectColor(Rect(0, 15, 29, 29), Color::RED);
+ // red area to the right of the blue area
+ mCapture->expectColor(Rect(15, 0, 29, 29), Color::RED);
+ mCapture->checkPixel(30, 30, 0, 0, 0);
+}
+
+TEST_F(ScreenCaptureTest, CaptureInvalidLayer) {
+ sp<SurfaceControl> redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60,
+ PIXEL_FORMAT_RGBA_8888, 0);
+
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED));
+
+ auto redLayerHandle = redLayer->getHandle();
+ mComposerClient->destroySurface(redLayerHandle);
+ SurfaceComposerClient::Transaction().apply(true);
+
+ sp<GraphicBuffer> outBuffer;
+
+ // Layer was deleted so captureLayers should fail with NAME_NOT_FOUND
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, &outBuffer, Rect::EMPTY_RECT, 1.0));
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index 94f3f25..47c4f4a 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",
@@ -30,6 +31,9 @@
"libtrace_proto",
"libgmock"
],
+ cppflags: [
+ "-std=c++1z",
+ ],
tags: ["tests"],
test_suites: ["device-tests"]
}
\ No newline at end of file
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..b944182 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.h
@@ -16,9 +16,16 @@
#pragma once
+#define HWC2_USE_CPP11
+#define HWC2_INCLUDE_STRINGIFICATION
#include "ComposerClient.h"
+#undef HWC2_USE_CPP11
+#undef HWC2_INCLUDE_STRINGIFICATION
#include "RenderState.h"
+// Needed for display type/ID enums
+#include <hardware/hwcomposer_defs.h>
+
#include <utils/Condition.h>
#include <chrono>
@@ -40,6 +47,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/bufferhubd/bufferhubd.rc b/services/vr/bufferhubd/bufferhubd.rc
index 46fe5f9..c470de5 100644
--- a/services/vr/bufferhubd/bufferhubd.rc
+++ b/services/vr/bufferhubd/bufferhubd.rc
@@ -2,5 +2,4 @@
class core
user system
group system
- writepid /dev/cpuset/tasks
socket pdx/system/buffer_hub/client stream 0660 system system u:object_r:pdx_bufferhub_client_endpoint_socket:s0
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/services/vr/performanced/performanced.rc b/services/vr/performanced/performanced.rc
index 2605a47..af9760e 100644
--- a/services/vr/performanced/performanced.rc
+++ b/services/vr/performanced/performanced.rc
@@ -2,5 +2,4 @@
class core
user root
group system readproc
- writepid /dev/cpuset/tasks
socket pdx/system/performance/client stream 0666 system system u:object_r:pdx_performance_client_endpoint_socket:s0
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/include/vulkan/vulkan_loader_data.h b/vulkan/include/vulkan/vulkan_loader_data.h
deleted file mode 100644
index 8ea4666..0000000
--- a/vulkan/include/vulkan/vulkan_loader_data.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef VULKAN_VULKAN_LOADER_DATA_H
-#define VULKAN_VULKAN_LOADER_DATA_H
-
-#include <string>
-
-struct android_namespace_t;
-
-namespace vulkan {
- struct LoaderData {
- std::string layer_path;
- android_namespace_t* app_namespace;
-
- __attribute__((visibility("default"))) static LoaderData& GetInstance();
- };
-}
-
-#endif
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 5f9b357..c9faf28 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -61,7 +61,6 @@
"layers_extensions.cpp",
"stubhal.cpp",
"swapchain.cpp",
- "vulkan_loader_data.cpp",
],
export_header_lib_headers: ["vulkan_headers"],
@@ -80,6 +79,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..673a066 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -29,14 +29,17 @@
#include <new>
#include <utility>
+#include <android-base/strings.h>
#include <cutils/properties.h>
#include <log/log.h>
#include <vulkan/vk_layer_interface.h>
+#include <graphicsenv/GraphicsEnv.h>
#include "api.h"
#include "driver.h"
#include "layers_extensions.h"
+
namespace vulkan {
namespace api {
@@ -121,15 +124,33 @@
if (!is_instance_ || !driver::Debuggable())
return;
- ParseDebugVulkanLayers();
- property_list(ParseDebugVulkanLayer, this);
+ GetLayersFromSettings();
- // sort by priorities
- auto& arr = implicit_layers_;
- std::sort(arr.elements, arr.elements + arr.count,
- [](const ImplicitLayer& a, const ImplicitLayer& b) {
- return (a.priority < b.priority);
- });
+ // If no layers specified via Settings, check legacy properties
+ if (implicit_layers_.count <= 0) {
+ ParseDebugVulkanLayers();
+ property_list(ParseDebugVulkanLayer, this);
+
+ // sort by priorities
+ auto& arr = implicit_layers_;
+ std::sort(arr.elements, arr.elements + arr.count,
+ [](const ImplicitLayer& a, const ImplicitLayer& b) {
+ return (a.priority < b.priority);
+ });
+ }
+ }
+
+ void GetLayersFromSettings() {
+ // These will only be available if conditions are met in GraphicsEnvironemnt
+ // gpu_debug_layers = layer1:layer2:layerN
+ const std::string layers = android::GraphicsEnv::getInstance().getDebugLayers();
+ if (!layers.empty()) {
+ ALOGV("Debug layer list: %s", layers.c_str());
+ std::vector<std::string> paths = android::base::Split(layers, ":");
+ for (uint32_t i = 0; i < paths.size(); i++) {
+ AddImplicitLayer(int(i), paths[i].c_str(), paths[i].length());
+ }
+ }
}
void ParseDebugVulkanLayers() {
@@ -1280,5 +1301,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/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index 05856d3..3a59208 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -29,11 +29,10 @@
#include <android/dlext.h>
#include <android-base/strings.h>
#include <cutils/properties.h>
+#include <graphicsenv/GraphicsEnv.h>
#include <log/log.h>
#include <ziparchive/zip_archive.h>
-#include <vulkan/vulkan_loader_data.h>
-
// TODO(jessehall): The whole way we deal with extensions is pretty hokey, and
// not a good long-term solution. Having a hard-coded enum of extensions is
// bad, of course. Representing sets of extensions (requested, supported, etc.)
@@ -69,11 +68,16 @@
class LayerLibrary {
public:
- explicit LayerLibrary(const std::string& path)
- : path_(path), dlhandle_(nullptr), refcount_(0) {}
+ explicit LayerLibrary(const std::string& path,
+ const std::string& filename)
+ : path_(path),
+ filename_(filename),
+ dlhandle_(nullptr),
+ refcount_(0) {}
LayerLibrary(LayerLibrary&& other)
: path_(std::move(other.path_)),
+ filename_(std::move(other.filename_)),
dlhandle_(other.dlhandle_),
refcount_(other.refcount_) {
other.dlhandle_ = nullptr;
@@ -94,9 +98,14 @@
const char* gpa_name,
size_t gpa_name_len) const;
+ const std::string GetFilename() { return filename_; }
+
private:
const std::string path_;
+ // Track the filename alone so we can detect duplicates
+ const std::string filename_;
+
std::mutex mutex_;
void* dlhandle_;
size_t refcount_;
@@ -111,7 +120,7 @@
// any symbol dependencies will be resolved by system libraries. They
// can't safely use libc++_shared, for example. Which is one reason
// (among several) we only allow them in non-user builds.
- auto app_namespace = LoaderData::GetInstance().app_namespace;
+ auto app_namespace = android::GraphicsEnv::getInstance().getAppNamespace();
if (app_namespace &&
!android::base::StartsWith(path_, kSystemLayerLibraryDir)) {
android_dlextinfo dlextinfo = {};
@@ -305,8 +314,8 @@
std::vector<LayerLibrary> g_layer_libraries;
std::vector<Layer> g_instance_layers;
-void AddLayerLibrary(const std::string& path) {
- LayerLibrary library(path);
+void AddLayerLibrary(const std::string& path, const std::string& filename) {
+ LayerLibrary library(path + "/" + filename, filename);
if (!library.Open())
return;
@@ -398,7 +407,25 @@
ForEachFileInPath(path, [&](const std::string& filename) {
if (android::base::StartsWith(filename, "libVkLayer") &&
android::base::EndsWith(filename, ".so")) {
- AddLayerLibrary(path + "/" + filename);
+
+ // Check to ensure we haven't seen this layer already
+ // Let the first instance of the shared object be enumerated
+ // We're searching for layers in following order:
+ // 1. system path
+ // 2. libraryPermittedPath (if enabled)
+ // 3. libraryPath
+
+ bool duplicate = false;
+ for (auto& layer : g_layer_libraries) {
+ if (layer.GetFilename() == filename) {
+ ALOGV("Skipping duplicate layer %s in %s",
+ filename.c_str(), path.c_str());
+ duplicate = true;
+ }
+ }
+
+ if (!duplicate)
+ AddLayerLibrary(path, filename);
}
});
}
@@ -428,8 +455,8 @@
prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
DiscoverLayersInPathList(kSystemLayerLibraryDir);
}
- if (!LoaderData::GetInstance().layer_path.empty())
- DiscoverLayersInPathList(LoaderData::GetInstance().layer_path);
+ if (!android::GraphicsEnv::getInstance().getLayerPaths().empty())
+ DiscoverLayersInPathList(android::GraphicsEnv::getInstance().getLayerPaths());
}
uint32_t GetLayerCount() {
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/libvulkan/vulkan_loader_data.cpp b/vulkan/libvulkan/vulkan_loader_data.cpp
deleted file mode 100644
index 0eda0af..0000000
--- a/vulkan/libvulkan/vulkan_loader_data.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <vulkan/vulkan_loader_data.h>
-
-using namespace vulkan;
-
-LoaderData& LoaderData::GetInstance() {
- static LoaderData loader_data = {};
- return loader_data;
-}
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);