Merge "Create prebuilts for NFC hal permission files" into main
diff --git a/Android.bp b/Android.bp
index 72311f0..a689b2d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -48,6 +48,7 @@
export_include_dirs: [
"include/",
],
+ product_available: true,
}
ndk_headers {
@@ -125,3 +126,9 @@
srcs: ["aidl/android/hardware/display/IDeviceProductInfoConstants.aidl"],
path: "aidl",
}
+
+dirgroup {
+ name: "trusty_dirgroup_frameworks_native",
+ dirs: ["libs/binder"],
+ visibility: ["//trusty/vendor/google/aosp/scripts"],
+}
diff --git a/METADATA b/METADATA
index d97975c..86892cd 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,3 @@
-third_party {
+ third_party {
license_type: NOTICE
}
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 9c01169..a4a22a0 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -4,9 +4,6 @@
"name": "SurfaceFlinger_test",
"options": [
{
- "include-filter": "*"
- },
- {
// TODO(b/305717998): Deflake and re-enable
"exclude-filter": "*ChildLayerTest*"
}
@@ -23,10 +20,21 @@
],
"hwasan-postsubmit": [
{
+ "name": "SurfaceFlinger_test"
+ }
+ ],
+ "postsubmit": [
+ {
"name": "SurfaceFlinger_test",
+ "keywords": [ "primary-device" ],
"options": [
+ // TODO(b/328119950) Known to be broken.
{
- "include-filter": "*"
+ "exclude-filter": "LayerCallbackTest#SetNullBuffer"
+ },
+ // TODO(b/398306512) Flaky on real device.
+ {
+ "exclude-filter": "LayerRenderTypeTransactionTests/LayerRenderTypeTransactionTest#SetRelativeZBasic_BufferQueue/*"
}
]
}
diff --git a/aidl/binder/android/os/PersistableBundle.aidl b/aidl/binder/android/os/PersistableBundle.aidl
index 248e973..9b11109 100644
--- a/aidl/binder/android/os/PersistableBundle.aidl
+++ b/aidl/binder/android/os/PersistableBundle.aidl
@@ -17,4 +17,4 @@
package android.os;
-@JavaOnlyStableParcelable @NdkOnlyStableParcelable parcelable PersistableBundle cpp_header "binder/PersistableBundle.h" ndk_header "android/persistable_bundle_aidl.h";
+@JavaOnlyStableParcelable @NdkOnlyStableParcelable @RustOnlyStableParcelable parcelable PersistableBundle cpp_header "binder/PersistableBundle.h" ndk_header "android/persistable_bundle_aidl.h" rust_type "binder::PersistableBundle";
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index 372008e..fdb032b 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -83,14 +83,16 @@
"aconfig_lib_cc_static_link.defaults",
"dumpstate_cflag_defaults",
],
+ // See README.md: "Dumpstate philosophy: exec not link"
+ // Do not add things here - keep dumpstate as simple as possible and exec where possible.
shared_libs: [
"android.hardware.dumpstate@1.0",
"android.hardware.dumpstate@1.1",
"android.hardware.dumpstate-V1-ndk",
"libziparchive",
"libbase",
- "libbinder",
- "libbinder_ndk",
+ "libbinder", // BAD: dumpstate should not link code directly, should only exec binaries
+ "libbinder_ndk", // BAD: dumpstate should not link code directly, should only exec binaries
"libcrypto",
"libcutils",
"libdebuggerd_client",
@@ -98,11 +100,11 @@
"libdumpstateutil",
"libdumputils",
"libhardware_legacy",
- "libhidlbase",
+ "libhidlbase", // BAD: dumpstate should not link code directly, should only exec binaries
"liblog",
"libutils",
- "libvintf",
- "libbinderdebug",
+ "libvintf", // BAD: dumpstate should not link code directly, should only exec binaries
+ "libbinderdebug", // BAD: dumpstate should not link code directly, should only exec binaries
"packagemanager_aidl-cpp",
"server_configurable_flags",
"device_policy_aconfig_flags_c_lib",
@@ -115,6 +117,7 @@
"libdumpsys",
"libserviceutils",
"android.tracing.flags_c_lib",
+ "perfetto_flags_c_lib",
],
}
@@ -134,6 +137,7 @@
"main.cpp",
],
required: [
+ "alloctop",
"atrace",
"bugreport_procdump",
"default_screenshot",
diff --git a/cmds/dumpstate/DumpstateInternal.cpp b/cmds/dumpstate/DumpstateInternal.cpp
index 6f7fea3..ce7c55c 100644
--- a/cmds/dumpstate/DumpstateInternal.cpp
+++ b/cmds/dumpstate/DumpstateInternal.cpp
@@ -108,7 +108,7 @@
const uint32_t cap_syslog_mask = CAP_TO_MASK(CAP_SYSLOG);
const uint32_t cap_syslog_index = CAP_TO_INDEX(CAP_SYSLOG);
- bool has_cap_syslog = (capdata[cap_syslog_index].effective & cap_syslog_mask) != 0;
+ bool has_cap_syslog = (capdata[cap_syslog_index].permitted & cap_syslog_mask) != 0;
memset(&capdata, 0, sizeof(capdata));
if (has_cap_syslog) {
diff --git a/cmds/dumpstate/README.md b/cmds/dumpstate/README.md
index 26dabbb..3ab971a 100644
--- a/cmds/dumpstate/README.md
+++ b/cmds/dumpstate/README.md
@@ -21,6 +21,18 @@
mmm -j frameworks/native/cmds/dumpstate device/acme/secret_device/dumpstate/ hardware/interfaces/dumpstate
```
+## Dumpstate philosophy: exec not link
+
+Never link code directly into dumpstate. Dumpstate should execute many
+binaries and collect the results. In general, code should fail hard fail fast,
+but dumpstate is the last to solve many Android bugs. Oftentimes, failures
+in core Android infrastructure or tools are issues that cause problems in
+bugreport directly, so bugreport should not rely on these tools working.
+We want dumpstate to have as minimal of code loaded in process so that
+only that core subset needs to be bugfree for bugreport to work. Even if
+many pieces of Android break, that should not prevent dumpstate from
+working.
+
## To build, deploy, and take a bugreport
```
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index d24edc4..9e3e2b0 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -57,6 +57,7 @@
#include <log/log_read.h>
#include <math.h>
#include <openssl/sha.h>
+#include <perfetto_flags.h>
#include <poll.h>
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
@@ -128,6 +129,9 @@
using android::os::dumpstate::TaskQueue;
using android::os::dumpstate::WaitForTask;
+// BAD - See README.md: "Dumpstate philosophy: exec not link"
+// Do not add more complicated variables here, prefer to execute only. Don't link more code here.
+
// Keep in sync with
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
@@ -187,11 +191,10 @@
#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
#define LINKERCONFIG_DIR "/linkerconfig"
#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
-#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
+#define SYSTEM_TRACE_DIR "/data/misc/perfetto-traces/bugreport"
#define CGROUPFS_DIR "/sys/fs/cgroup"
#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
#define DROPBOX_DIR "/data/system/dropbox"
-#define PRINT_FLAGS "/system/bin/printflags"
#define UWB_LOG_DIR "/data/misc/apexdata/com.android.uwb/log"
// TODO(narayan): Since this information has to be kept in sync
@@ -357,6 +360,31 @@
return CopyFileToFd(input_file, out_fd.get());
}
+template <typename Func>
+size_t ForEachTrace(Func func) {
+ std::unique_ptr<DIR, decltype(&closedir)> traces_dir(opendir(SYSTEM_TRACE_DIR), closedir);
+
+ if (traces_dir == nullptr) {
+ MYLOGW("Unable to open directory %s: %s\n", SYSTEM_TRACE_DIR, strerror(errno));
+ return 0;
+ }
+
+ size_t traces_found = 0;
+ struct dirent* entry = nullptr;
+ while ((entry = readdir(traces_dir.get()))) {
+ if (entry->d_type != DT_REG) {
+ continue;
+ }
+ std::string trace_path = std::string(SYSTEM_TRACE_DIR) + "/" + entry->d_name;
+ if (access(trace_path.c_str(), F_OK) != 0) {
+ continue;
+ }
+ ++traces_found;
+ func(trace_path);
+ }
+ return traces_found;
+}
+
} // namespace
} // namespace os
} // namespace android
@@ -1099,20 +1127,16 @@
// This function copies into the .zip the system trace that was snapshotted
// by the early call to MaybeSnapshotSystemTraceAsync(), if any background
// tracing was happening.
- bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
- if (!system_trace_exists) {
- // No background trace was happening at the time MaybeSnapshotSystemTraceAsync() was invoked
- if (!PropertiesHelper::IsUserBuild()) {
- MYLOGI(
- "No system traces found. Check for previously uploaded traces by looking for "
- "go/trace-uuid in logcat")
- }
- return;
+ size_t traces_found = android::os::ForEachTrace([&](const std::string& trace_path) {
+ ds.AddZipEntry(ZIP_ROOT_DIR + trace_path, trace_path);
+ android::os::UnlinkAndLogOnError(trace_path);
+ });
+
+ if (traces_found == 0 && !PropertiesHelper::IsUserBuild()) {
+ MYLOGI(
+ "No system traces found. Check for previously uploaded traces by looking for "
+ "go/trace-uuid in logcat")
}
- ds.AddZipEntry(
- ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
- SYSTEM_TRACE_SNAPSHOT);
- android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
}
static void DumpVisibleWindowViews() {
@@ -1264,6 +1288,17 @@
RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
}
+static void DumpKernelMemoryAllocations() {
+ if (!access("/proc/allocinfo", F_OK)) {
+ // Print the top 100 biggest memory allocations of at least one byte.
+ // The output is sorted by size, descending.
+ RunCommand("KERNEL MEMORY ALLOCATIONS",
+ {"alloctop", "--once", "--sort", "s", "--min", "1", "--lines", "100"});
+ }
+}
+
+// BAD - See README.md: "Dumpstate philosophy: exec not link"
+// This should all be moved into a separate binary rather than have complex logic here.
static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
std::chrono::milliseconds timeout,
std::chrono::milliseconds service_timeout) {
@@ -1344,6 +1379,8 @@
service_timeout);
}
+// BAD - See README.md: "Dumpstate philosophy: exec not link"
+// This should all be moved into a separate binary rather than have complex logic here.
static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
std::chrono::milliseconds timeout,
std::chrono::milliseconds service_timeout) {
@@ -1425,6 +1462,8 @@
* Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
* if it's not running in the parallel task.
*/
+// BAD - See README.md: "Dumpstate philosophy: exec not link"
+// This should all be moved into a separate binary rather than have complex logic here.
static void DumpHals(int out_fd = STDOUT_FILENO) {
RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
@@ -1481,6 +1520,9 @@
}
}
+// BAD - See README.md: "Dumpstate philosophy: exec not link"
+// This should all be moved into a separate binary rather than have complex logic here.
+//
// Dump all of the files that make up the vendor interface.
// See the files listed in dumpFileList() for the latest list of files.
static void DumpVintf() {
@@ -1510,6 +1552,8 @@
printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
std::ifstream ifs("/proc/buddyinfo");
auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
+ // BAD - See README.md: "Dumpstate philosophy: exec not link"
+ // This should all be moved into a separate binary rather than have complex logic here.
for (std::string line; std::getline(ifs, line);) {
std::smatch match_results;
if (std::regex_match(line, match_results, unusable_index_regex)) {
@@ -1773,6 +1817,8 @@
DoKmsg();
+ DumpKernelMemoryAllocations();
+
DumpShutdownCheckpoints();
DumpIpAddrAndRules();
@@ -1798,12 +1844,8 @@
DumpFile("PRODUCT BUILD-TIME RELEASE FLAGS", "/product/etc/build_flags.json");
DumpFile("VENDOR BUILD-TIME RELEASE FLAGS", "/vendor/etc/build_flags.json");
- RunCommand("ACONFIG FLAGS", {PRINT_FLAGS},
- CommandOptions::WithTimeout(10).Always().DropRoot().Build());
RunCommand("ACONFIG FLAGS DUMP", {AFLAGS, "list"},
CommandOptions::WithTimeout(10).Always().AsRootIfAvailable().Build());
- RunCommand("WHICH ACONFIG FLAG STORAGE", {AFLAGS, "which-backing"},
- CommandOptions::WithTimeout(10).Always().AsRootIfAvailable().Build());
RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
@@ -1841,6 +1883,11 @@
RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
}
+ /* Dump USB information */
+ RunCommand("typec_connector_class", {"typec_connector_class"},
+ CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
+ RunCommand("lsusb", {"lsusb"}, CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
+
printf("========================================================\n");
printf("== Android Framework Services\n");
printf("========================================================\n");
@@ -2448,6 +2495,8 @@
return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
}
+// BAD - See README.md: "Dumpstate philosophy: exec not link"
+// This should all be moved into a separate binary rather than have complex logic here.
static void DoDumpstateBoardHidl(
const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
@@ -3385,8 +3434,8 @@
// duration is logged into MYLOG instead.
PrintHeader();
- bool system_trace_exists = access(SYSTEM_TRACE_SNAPSHOT, F_OK) == 0;
- if (options_->use_predumped_ui_data && !system_trace_exists) {
+ size_t trace_count = android::os::ForEachTrace([](const std::string&) {});
+ if (options_->use_predumped_ui_data && trace_count == 0) {
MYLOGW("Ignoring 'use predumped data' flag because no predumped data is available");
options_->use_predumped_ui_data = false;
}
@@ -3533,20 +3582,24 @@
}
// If a stale file exists already, remove it.
- unlink(SYSTEM_TRACE_SNAPSHOT);
+ android::os::ForEachTrace([&](const std::string& trace_path) { unlink(trace_path.c_str()); });
MYLOGI("Launching async '%s'", SERIALIZE_PERFETTO_TRACE_TASK.c_str())
+
return std::async(
std::launch::async, [this, outPath = std::move(outPath), outFd = std::move(outFd)] {
- // If a background system trace is happening and is marked as "suitable for
- // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
- // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
- // case that no trace is ongoing, this command is a no-op.
+ // If one or more background system traces are happening and are marked as
+ // "suitable for bugreport" (bugreport_score > 0 in the trace config), this command
+ // will snapshot them into SYSTEM_TRACE_DIR.
+ // In the (likely) case that no trace is ongoing, this command is a no-op.
// Note: this should not be enqueued as we need to freeze the trace before
// dumpstate starts. Otherwise the trace ring buffers will contain mostly
// the dumpstate's own activity which is irrelevant.
+ const char* cmd_arg = perfetto::flags::save_all_traces_in_bugreport()
+ ? "--save-all-for-bugreport"
+ : "--save-for-bugreport";
RunCommand(
- SERIALIZE_PERFETTO_TRACE_TASK, {"perfetto", "--save-for-bugreport"},
+ SERIALIZE_PERFETTO_TRACE_TASK, {"perfetto", cmd_arg},
CommandOptions::WithTimeout(30).DropRoot().CloseAllFileDescriptorsOnExec().Build(),
false, outFd);
// MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
@@ -4651,7 +4704,7 @@
void Dumpstate::TakeScreenshot(const std::string& path) {
const std::string& real_path = path.empty() ? screenshot_path_ : path;
int status =
- RunCommand("", {"/system/bin/screencap", "-p", real_path},
+ RunCommand("", {"screencap", "-p", real_path},
CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
if (status == 0) {
MYLOGD("Screenshot saved on %s\n", real_path.c_str());
diff --git a/cmds/dumpstate/dumpstate_smoke_test.xml b/cmds/dumpstate/dumpstate_smoke_test.xml
index 0aff200..7e3307d 100644
--- a/cmds/dumpstate/dumpstate_smoke_test.xml
+++ b/cmds/dumpstate/dumpstate_smoke_test.xml
@@ -22,7 +22,9 @@
<option name="cleanup" value="true" />
<option name="push" value="dumpstate_smoke_test->/data/local/tmp/dumpstate_smoke_test" />
</target_preparer>
-
+ <target_preparer class="com.android.tradefed.targetprep.FeatureFlagTargetPreparer">
+ <option name="flag-value" value="perfetto/perfetto.flags.save_all_traces_in_bugreport=true" />
+ </target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="dumpstate_smoke_test" />
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index a29923a..c72847c 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -24,8 +24,10 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <libgen.h>
+#include <signal.h>
#include <ziparchive/zip_archive.h>
+#include <cstdio>
#include <fstream>
#include <regex>
@@ -603,6 +605,93 @@
listener1->getErrorCode() == IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
}
+class DumpstateTracingTest : public Test {
+ protected:
+ void TearDown() override {
+ for (int pid : bg_process_pids) {
+ kill(pid, SIGKILL);
+ }
+ }
+
+ void StartTracing(const std::string& config) {
+ // Write the perfetto config into a file.
+ const int id = static_cast<int>(bg_process_pids.size());
+ char cfg[64];
+ snprintf(cfg, sizeof(cfg), "/data/misc/perfetto-configs/br-%d", id);
+ unlink(cfg); // Remove the config file if it exists already.
+ FILE* f = fopen(cfg, "w");
+ ASSERT_NE(f, nullptr);
+ fputs(config.c_str(), f);
+ fclose(f);
+
+ // Invoke perfetto to start tracing.
+ char cmd[255];
+ snprintf(cmd, sizeof(cmd), "perfetto --background-wait --txt -o /dev/null -c %s", cfg);
+ FILE* proc = popen(cmd, "r");
+ ASSERT_NE(proc, nullptr);
+
+ // Read back the PID of the background process. We will use it to kill
+ // all tracing sessions when the test ends or fails.
+ char pid_str[32]{};
+ ASSERT_NE(fgets(pid_str, sizeof(pid_str), proc), nullptr);
+ int pid = atoi(pid_str);
+ bg_process_pids.push_back(pid);
+
+ pclose(proc);
+ unlink(cfg);
+ }
+
+ std::vector<int> bg_process_pids;
+};
+
+TEST_F(DumpstateTracingTest, ManyTracesInBugreport) {
+ // Note the trace duration is irrelevant and is only an upper bound.
+ // Tracing is stopped as soon as the bugreport.zip creation ends.
+ StartTracing(R"(
+buffers { size_kb: 4096 }
+data_sources {
+ config {
+ name: "linux.ftrace"
+ }
+}
+
+duration_ms: 120000
+bugreport_filename: "sys.pftrace"
+bugreport_score: 100
+)");
+
+ StartTracing(R"(
+buffers { size_kb: 4096 }
+data_sources {
+ config {
+ name: "linux.ftrace"
+ }
+}
+
+duration_ms: 120000
+bugreport_score: 50
+bugreport_filename: "mem.pftrace"
+)");
+
+ ZippedBugreportGenerationTest::GenerateBugreport();
+ std::string zip_path = ZippedBugreportGenerationTest::getZipFilePath();
+ ZipArchiveHandle handle;
+ ASSERT_EQ(OpenArchive(zip_path.c_str(), &handle), 0);
+
+ const char* kExpectedEntries[]{
+ "FS/data/misc/perfetto-traces/bugreport/sys.pftrace",
+ "FS/data/misc/perfetto-traces/bugreport/mem.pftrace",
+ };
+
+ // Check that the bugreport contains both traces.
+ for (const char* file_path : kExpectedEntries) {
+ ZipEntry entry{};
+ GetEntry(handle, file_path, &entry);
+ EXPECT_GT(entry.uncompressed_length, 100);
+ }
+ CloseArchive(handle);
+}
+
} // namespace dumpstate
} // namespace os
} // namespace android
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index b8e5ce1..17ae0aa 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -67,6 +67,8 @@
MOCK_METHOD2(unregisterForNotifications, status_t(const String16&,
const sp<LocalRegistrationCallback>&));
MOCK_METHOD0(getServiceDebugInfo, std::vector<ServiceDebugInfo>());
+ MOCK_METHOD1(enableAddServiceCache, void(bool));
+
protected:
MOCK_METHOD0(onAsBinder, IBinder*());
};
diff --git a/cmds/flatland/GLHelper.cpp b/cmds/flatland/GLHelper.cpp
index 77e7328..6e6d27d 100644
--- a/cmds/flatland/GLHelper.cpp
+++ b/cmds/flatland/GLHelper.cpp
@@ -202,26 +202,13 @@
}
bool GLHelper::createNamedSurfaceTexture(GLuint name, uint32_t w, uint32_t h,
- sp<GLConsumer>* glConsumer, EGLSurface* surface) {
-#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
- sp<GLConsumer> glc = new GLConsumer(name, GL_TEXTURE_EXTERNAL_OES, false, true);
+ sp<GLConsumer>* glConsumer, EGLSurface* surface) {
+ auto [glc, surf] = GLConsumer::create(name, GL_TEXTURE_EXTERNAL_OES, false, true);
glc->setDefaultBufferSize(w, h);
- glc->getSurface()->setMaxDequeuedBufferCount(2);
glc->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
+ surf->setMaxDequeuedBufferCount(2);
+ sp<ANativeWindow> anw = surf;
- sp<ANativeWindow> anw = glc->getSurface();
-#else
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer);
- sp<GLConsumer> glc = new GLConsumer(consumer, name,
- GL_TEXTURE_EXTERNAL_OES, false, true);
- glc->setDefaultBufferSize(w, h);
- producer->setMaxDequeuedBufferCount(2);
- glc->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
-
- sp<ANativeWindow> anw = new Surface(producer);
-#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
EGLSurface s = eglCreateWindowSurface(mDisplay, mConfig, anw.get(), nullptr);
if (s == EGL_NO_SURFACE) {
fprintf(stderr, "eglCreateWindowSurface error: %#x\n", eglGetError());
diff --git a/cmds/flatland/Main.cpp b/cmds/flatland/Main.cpp
index 6d14d56..277300d 100644
--- a/cmds/flatland/Main.cpp
+++ b/cmds/flatland/Main.cpp
@@ -772,8 +772,8 @@
break;
case 'i':
- displayId = DisplayId::fromValue<PhysicalDisplayId>(atoll(optarg));
- if (!displayId) {
+ displayId = PhysicalDisplayId::fromValue(atoll(optarg));
+ if (std::find(ids.begin(), ids.end(), displayId) == ids.end()) {
fprintf(stderr, "Invalid display ID: %s.\n", optarg);
exit(4);
}
diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp
index 50c2cd8..36dcbca 100644
--- a/cmds/idlcli/Android.bp
+++ b/cmds/idlcli/Android.bp
@@ -50,6 +50,7 @@
"vibrator/CommandAlwaysOnEnable.cpp",
"vibrator/CommandCompose.cpp",
"vibrator/CommandComposePwle.cpp",
+ "vibrator/CommandGetFrequencyToOutputAccelerationMap.cpp",
"vibrator/CommandGetBandwidthAmplitudeMap.cpp",
"vibrator/CommandGetCapabilities.cpp",
"vibrator/CommandGetCompositionDelayMax.cpp",
@@ -72,6 +73,11 @@
"vibrator/CommandSetExternalControl.cpp",
"vibrator/CommandSupportsAmplitudeControl.cpp",
"vibrator/CommandSupportsExternalControl.cpp",
+ "vibrator/CommandGetPwleV2PrimitiveDurationMaxMillis.cpp",
+ "vibrator/CommandGetPwleV2CompositionSizeMax.cpp",
+ "vibrator/CommandGetPwleV2PrimitiveDurationMinMillis.cpp",
+ "vibrator/CommandComposePwleV2.cpp",
+ "vibrator/CommandPerformVendorEffect.cpp",
],
visibility: [":__subpackages__"],
}
diff --git a/cmds/idlcli/vibrator/CommandComposePwleV2.cpp b/cmds/idlcli/vibrator/CommandComposePwleV2.cpp
new file mode 100644
index 0000000..6d3cf84
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandComposePwleV2.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+
+#include <charconv>
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+using aidl::CompositePwleV2;
+using aidl::PwleV2Primitive;
+
+class CommandComposePwleV2 : public Command {
+ std::string getDescription() const override { return "Compose normalized PWLE vibration."; }
+
+ std::string getUsageSummary() const override {
+ return "[options] <time> <frequency> <amplitude> ...";
+ }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{
+ {"-b", {"Block for duration of vibration."}},
+ {"<time>", {"Segment duration in milliseconds"}},
+ {"<frequency>", {"Target frequency in Hz"}},
+ {"<amplitude>", {"Target amplitude in [0.0, 1.0]"}},
+ {"...", {"May repeat multiple times."}},
+ };
+ return details;
+ }
+
+ Status doArgs(Args& args) override {
+ while (args.get<std::string>().value_or("").find("-") == 0) {
+ auto opt = *args.pop<std::string>();
+ if (opt == "--") {
+ break;
+ } else if (opt == "-b") {
+ mBlocking = true;
+ } else {
+ std::cerr << "Invalid Option '" << opt << "'!" << std::endl;
+ return USAGE;
+ }
+ }
+
+ if (args.empty()) {
+ std::cerr << "Missing arguments! Please see usage" << std::endl;
+ return USAGE;
+ }
+
+ while (!args.empty()) {
+ PwleV2Primitive segment;
+
+ if (auto timeMs = args.pop<decltype(segment.timeMillis)>();
+ timeMs && *timeMs >= 0 && *timeMs <= 0x7ffff) {
+ segment.timeMillis = *timeMs;
+ std::cout << "Time: " << segment.timeMillis << std::endl;
+ } else {
+ std::cerr << "Missing or Invalid Time!" << std::endl;
+ return USAGE;
+ }
+
+ if (auto frequencyHz = args.pop<decltype(segment.frequencyHz)>();
+ frequencyHz && *frequencyHz >= 30 && *frequencyHz <= 300) {
+ segment.frequencyHz = *frequencyHz;
+ std::cout << "Frequency: " << segment.frequencyHz << std::endl;
+ } else {
+ std::cerr << "Missing or Invalid Frequency!" << std::endl;
+ return USAGE;
+ }
+
+ if (auto amplitude = args.pop<decltype(segment.amplitude)>();
+ amplitude && *amplitude >= 0 && *amplitude <= 1.0) {
+ segment.amplitude = *amplitude;
+ std::cout << "Amplitude: " << segment.amplitude << std::endl;
+ } else {
+ std::cerr << "Missing or Invalid Amplitude!" << std::endl;
+ return USAGE;
+ }
+
+ mCompositePwle.pwlePrimitives.emplace_back(std::move(segment));
+ }
+
+ if (!args.empty()) {
+ std::cerr << "Unexpected Arguments!" << std::endl;
+ return USAGE;
+ }
+
+ return OK;
+ }
+
+ Status doMain(Args&& /*args*/) override {
+ auto hal = getHal<aidl::IVibrator>();
+
+ if (!hal) {
+ return UNAVAILABLE;
+ }
+
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+
+ std::shared_ptr<VibratorCallback> callback;
+
+ if (mBlocking) {
+ callback = ndk::SharedRefBase::make<VibratorCallback>();
+ }
+
+ auto status = hal->call(&aidl::IVibrator::composePwleV2, mCompositePwle, callback);
+
+ if (status.isOk() && callback) {
+ callback->waitForComplete();
+ }
+
+ std::cout << "Status: " << status.getDescription() << std::endl;
+
+ return status.isOk() ? OK : ERROR;
+ }
+
+ bool mBlocking;
+ CompositePwleV2 mCompositePwle;
+};
+
+static const auto Command =
+ CommandRegistry<CommandVibrator>::Register<CommandComposePwleV2>("composePwleV2");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandGetFrequencyToOutputAccelerationMap.cpp b/cmds/idlcli/vibrator/CommandGetFrequencyToOutputAccelerationMap.cpp
new file mode 100644
index 0000000..2edd0ca
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandGetFrequencyToOutputAccelerationMap.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2024 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 "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+using aidl::FrequencyAccelerationMapEntry;
+
+class CommandGetFrequencyToOutputAccelerationMap : public Command {
+ std::string getDescription() const override {
+ return "Retrieves vibrator frequency to output acceleration map.";
+ }
+
+ std::string getUsageSummary() const override { return ""; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{};
+ return details;
+ }
+
+ Status doArgs(Args& args) override {
+ if (!args.empty()) {
+ std::cerr << "Unexpected Arguments!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args&& /*args*/) override {
+ std::string statusStr;
+ std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap;
+ Status ret;
+
+ if (auto hal = getHal<aidl::IVibrator>()) {
+ auto status = hal->call(&aidl::IVibrator::getFrequencyToOutputAccelerationMap,
+ &frequencyToOutputAccelerationMap);
+ statusStr = status.getDescription();
+ ret = (status.isOk() ? OK : ERROR);
+ } else {
+ return UNAVAILABLE;
+ }
+
+ std::cout << "Status: " << statusStr << std::endl;
+ std::cout << "Frequency to Output Amplitude Map: " << std::endl;
+ for (auto& entry : frequencyToOutputAccelerationMap) {
+ std::cout << entry.frequencyHz << " " << entry.maxOutputAccelerationGs << std::endl;
+ }
+
+ return ret;
+ }
+};
+
+static const auto Command =
+ CommandRegistry<CommandVibrator>::Register<CommandGetFrequencyToOutputAccelerationMap>(
+ "getFrequencyToOutputAccelerationMap");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandGetPwleV2CompositionSizeMax.cpp b/cmds/idlcli/vibrator/CommandGetPwleV2CompositionSizeMax.cpp
new file mode 100644
index 0000000..cca072c
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandGetPwleV2CompositionSizeMax.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2024 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 "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+class CommandGetPwleV2CompositionSizeMax : public Command {
+ std::string getDescription() const override {
+ return "Retrieves vibrator PwleV2 max composition size.";
+ }
+
+ std::string getUsageSummary() const override { return ""; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{};
+ return details;
+ }
+
+ Status doArgs(Args& args) override {
+ if (!args.empty()) {
+ std::cerr << "Unexpected Arguments!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args&& /*args*/) override {
+ std::string statusStr;
+ int32_t maxSize;
+ Status ret;
+
+ if (auto hal = getHal<aidl::IVibrator>()) {
+ auto status = hal->call(&aidl::IVibrator::getPwleV2CompositionSizeMax, &maxSize);
+ statusStr = status.getDescription();
+ ret = status.isOk() ? OK : ERROR;
+ } else {
+ return UNAVAILABLE;
+ }
+
+ std::cout << "Status: " << statusStr << std::endl;
+ std::cout << "Max Size: " << maxSize << std::endl;
+
+ return ret;
+ }
+};
+
+static const auto Command =
+ CommandRegistry<CommandVibrator>::Register<CommandGetPwleV2CompositionSizeMax>(
+ "getPwleV2CompositionSizeMax");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandGetPwleV2PrimitiveDurationMaxMillis.cpp b/cmds/idlcli/vibrator/CommandGetPwleV2PrimitiveDurationMaxMillis.cpp
new file mode 100644
index 0000000..dbbfe1a
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandGetPwleV2PrimitiveDurationMaxMillis.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2024 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 "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+class CommandGetPwleV2PrimitiveDurationMaxMillis : public Command {
+ std::string getDescription() const override {
+ return "Retrieves vibrator PwleV2 max primitive duration in milliseconds.";
+ }
+
+ std::string getUsageSummary() const override { return ""; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{};
+ return details;
+ }
+
+ Status doArgs(Args& args) override {
+ if (!args.empty()) {
+ std::cerr << "Unexpected Arguments!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args&& /*args*/) override {
+ std::string statusStr;
+ int32_t maxDurationMs;
+ Status ret;
+
+ if (auto hal = getHal<aidl::IVibrator>()) {
+ auto status = hal->call(&aidl::IVibrator::getPwleV2PrimitiveDurationMaxMillis,
+ &maxDurationMs);
+ statusStr = status.getDescription();
+ ret = status.isOk() ? OK : ERROR;
+ } else {
+ return UNAVAILABLE;
+ }
+
+ std::cout << "Status: " << statusStr << std::endl;
+ std::cout << "Primitive duration max: " << maxDurationMs << " ms" << std::endl;
+
+ return ret;
+ }
+};
+
+static const auto Command =
+ CommandRegistry<CommandVibrator>::Register<CommandGetPwleV2PrimitiveDurationMaxMillis>(
+ "getPwleV2PrimitiveDurationMaxMillis");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandGetPwleV2PrimitiveDurationMinMillis.cpp b/cmds/idlcli/vibrator/CommandGetPwleV2PrimitiveDurationMinMillis.cpp
new file mode 100644
index 0000000..09225c4
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandGetPwleV2PrimitiveDurationMinMillis.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2024 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 "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+class CommandGetPwleV2PrimitiveDurationMinMillis : public Command {
+ std::string getDescription() const override {
+ return "Retrieves vibrator PwleV2 minimum primitive duration in milliseconds.";
+ }
+
+ std::string getUsageSummary() const override { return ""; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{};
+ return details;
+ }
+
+ Status doArgs(Args& args) override {
+ if (!args.empty()) {
+ std::cerr << "Unexpected Arguments!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args&& /*args*/) override {
+ std::string statusStr;
+ int32_t minDurationMs;
+ Status ret;
+
+ if (auto hal = getHal<aidl::IVibrator>()) {
+ auto status = hal->call(&aidl::IVibrator::getPwleV2PrimitiveDurationMinMillis,
+ &minDurationMs);
+ statusStr = status.getDescription();
+ ret = status.isOk() ? OK : ERROR;
+ } else {
+ return UNAVAILABLE;
+ }
+
+ std::cout << "Status: " << statusStr << std::endl;
+ std::cout << "Primitive duration min: " << minDurationMs << " ms" << std::endl;
+
+ return ret;
+ }
+};
+
+static const auto Command =
+ CommandRegistry<CommandVibrator>::Register<CommandGetPwleV2PrimitiveDurationMinMillis>(
+ "getPwleV2PrimitiveDurationMinMillis");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandPerformVendorEffect.cpp b/cmds/idlcli/vibrator/CommandPerformVendorEffect.cpp
new file mode 100644
index 0000000..9c25bd2
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandPerformVendorEffect.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2024 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 <thread>
+
+#include "utils.h"
+#include "vibrator.h"
+
+using std::chrono::milliseconds;
+using std::this_thread::sleep_for;
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+using aidl::VendorEffect;
+
+class CommandPerformVendorEffect : public Command {
+ std::string getDescription() const override { return "Perform vendor vibration effect."; }
+
+ std::string getUsageSummary() const override { return "[options] <none>"; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{
+ {"-b", {"Block for duration of vibration."}},
+ {"<none>", {"No valid input."}},
+ };
+ return details;
+ }
+
+ Status doArgs(Args& args) override {
+ while (args.get<std::string>().value_or("").find("-") == 0) {
+ auto opt = *args.pop<std::string>();
+ if (opt == "--") {
+ break;
+ } else if (opt == "-b") {
+ mBlocking = true;
+ } else {
+ std::cerr << "Invalid Option '" << opt << "'!" << std::endl;
+ return USAGE;
+ }
+ }
+
+ return OK;
+ }
+
+ Status doMain(Args&& /*args*/) override { return UNAVAILABLE; }
+
+ bool mBlocking;
+ VendorEffect mEffect;
+};
+
+static const auto Command = CommandRegistry<CommandVibrator>::Register<CommandPerformVendorEffect>(
+ "performVendorEffect");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 4486bd6..db56551 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -119,7 +119,6 @@
*/
static constexpr const char* kAppDataIsolationEnabledProperty = "persist.zygote.app_data_isolation";
static constexpr const char* kMntSdcardfs = "/mnt/runtime/default/";
-static constexpr const char* kMntFuse = "/mnt/pass_through/0/";
static std::atomic<bool> sAppDataIsolationEnabled(false);
@@ -3697,7 +3696,9 @@
std::getline(in, ignored);
if (android::base::GetBoolProperty(kFuseProp, false)) {
- if (target.find(kMntFuse) == 0) {
+ const std::regex kMntFuseRe =
+ std::regex(R"(^/mnt/pass_through/(0|[0-9]+/[A-Z0-9]{4}-[A-Z0-9]{4}).*)");
+ if (std::regex_match(target, kMntFuseRe)) {
LOG(DEBUG) << "Found storage mount " << source << " at " << target;
mStorageMounts[source] = target;
}
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index c86adef..c818e0d 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -16,6 +16,7 @@
#include <fcntl.h>
#include <linux/unistd.h>
+#include <sched.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/wait.h>
diff --git a/cmds/installd/otapreopt_script.sh b/cmds/installd/otapreopt_script.sh
index b7ad331..5690e2f 100644
--- a/cmds/installd/otapreopt_script.sh
+++ b/cmds/installd/otapreopt_script.sh
@@ -23,6 +23,9 @@
TARGET_SLOT="$1"
STATUS_FD="$2"
+# "1" if the script is triggered by the `UpdateEngine.triggerPostinstall` API. Empty otherwise.
+TRIGGERED_BY_API="$3"
+
# Maximum number of packages/steps.
MAXIMUM_PACKAGES=1000
@@ -53,25 +56,43 @@
# A source that infinitely emits arbitrary lines.
# When connected to STDIN of another process, this source keeps STDIN open until
# the consumer process closes STDIN or this script dies.
+# In practice, the pm command keeps consuming STDIN, so we don't need to worry
+# about running out of buffer space.
function infinite_source {
while echo .; do
sleep 1
done
}
+if [[ "$TRIGGERED_BY_API" = "1" ]]; then
+ # During OTA installation, the script is called the first time, and
+ # `TRIGGERED_BY_API` can never be "1". `TRIGGERED_BY_API` being "1" means this
+ # is the second call to this script, through the
+ # `UpdateEngine.triggerPostinstall` API.
+ # When we reach here, it means Pre-reboot Dexopt is enabled in asynchronous
+ # mode and the job scheduler determined that it's the time to run the job.
+ # Start Pre-reboot Dexopt now and wait for it to finish.
+ infinite_source | pm art on-ota-staged --start
+ exit $?
+fi
+
PR_DEXOPT_JOB_VERSION="$(pm art pr-dexopt-job --version)"
if (( $? == 0 )) && (( $PR_DEXOPT_JOB_VERSION >= 3 )); then
# Delegate to Pre-reboot Dexopt, a feature of ART Service.
# ART Service decides what to do with this request:
# - If Pre-reboot Dexopt is disabled or unsupported, the command returns
- # non-zero. This is always the case if the current system is Android 14 or
- # earlier.
+ # non-zero.
+ # This is always the case if the current system is Android 14 or earlier.
# - If Pre-reboot Dexopt is enabled in synchronous mode, the command blocks
- # until Pre-reboot Dexopt finishes, and returns zero no matter it succeeds or
- # not. This is the default behavior if the current system is Android 15.
- # - If Pre-reboot Dexopt is enabled in asynchronous mode, the command schedules
- # an asynchronous job and returns 0 immediately. The job will then run by the
- # job scheduler when the device is idle and charging.
+ # until Pre-reboot Dexopt finishes, and returns zero no matter it succeeds
+ # or not.
+ # This is the default behavior if the current system is Android 15.
+ # - If Pre-reboot Dexopt is enabled in asynchronous mode, the command
+ # schedules an asynchronous job and returns 0 immediately.
+ # Later, when the device is idle and charging, the job will be run by the
+ # job scheduler. It will call this script again through the
+ # `UpdateEngine.triggerPostinstall` API, with `TRIGGERED_BY_API` being "1".
+ # This is always the case if the current system is Android 16 or later.
if infinite_source | pm art on-ota-staged --slot "$TARGET_SLOT_SUFFIX"; then
# Handled by Pre-reboot Dexopt.
exit 0
diff --git a/cmds/installd/tests/fuzzers/InstalldServiceFuzzer.cpp b/cmds/installd/tests/fuzzers/InstalldServiceFuzzer.cpp
index b1c6940..50ea0c7 100644
--- a/cmds/installd/tests/fuzzers/InstalldServiceFuzzer.cpp
+++ b/cmds/installd/tests/fuzzers/InstalldServiceFuzzer.cpp
@@ -47,6 +47,8 @@
} // namespace android
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ // TODO(b/183141167): need to rewrite 'dump' to avoid SIGPIPE.
+ signal(SIGPIPE, SIG_IGN);
auto service = sp<InstalldNativeService>::make();
fuzzService(service, FuzzedDataProvider(data, size));
return 0;
diff --git a/cmds/lshal/libprocpartition/include/procpartition/procpartition.h b/cmds/lshal/libprocpartition/include/procpartition/procpartition.h
index ca1e690..9c0fc18 100644
--- a/cmds/lshal/libprocpartition/include/procpartition/procpartition.h
+++ b/cmds/lshal/libprocpartition/include/procpartition/procpartition.h
@@ -27,6 +27,8 @@
enum class Partition {
UNKNOWN = 0,
SYSTEM,
+ SYSTEM_EXT,
+ PRODUCT,
VENDOR,
ODM
};
diff --git a/cmds/lshal/libprocpartition/procpartition.cpp b/cmds/lshal/libprocpartition/procpartition.cpp
index 9645f3a..35fad57 100644
--- a/cmds/lshal/libprocpartition/procpartition.cpp
+++ b/cmds/lshal/libprocpartition/procpartition.cpp
@@ -24,6 +24,8 @@
std::ostream& operator<<(std::ostream& os, Partition p) {
switch (p) {
case Partition::SYSTEM: return os << "system";
+ case Partition::SYSTEM_EXT: return os << "system_ext";
+ case Partition::PRODUCT: return os << "product";
case Partition::VENDOR: return os << "vendor";
case Partition::ODM: return os << "odm";
case Partition::UNKNOWN: // fallthrough
@@ -57,6 +59,12 @@
if (s == "system") {
return Partition::SYSTEM;
}
+ if (s == "system_ext") {
+ return Partition::SYSTEM_EXT;
+ }
+ if (s == "product") {
+ return Partition::PRODUCT;
+ }
if (s == "vendor") {
return Partition::VENDOR;
}
diff --git a/cmds/servicemanager/Access.cpp b/cmds/servicemanager/Access.cpp
index 8098724..6e2abf6 100644
--- a/cmds/servicemanager/Access.cpp
+++ b/cmds/servicemanager/Access.cpp
@@ -34,7 +34,9 @@
#ifdef __ANDROID__
static std::string getPidcon(pid_t pid) {
- android_errorWriteLog(0x534e4554, "121035042");
+ CHECK_EQ(nullptr, IPCThreadState::self()->getServingStackPointer())
+ << "Did not get context from PID " << pid
+ << ". We should always get contexts from other processes.";
char* lookup = nullptr;
if (getpidcon(pid, &lookup) < 0) {
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index fa7cb64..59c4d53 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -396,7 +396,7 @@
SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS(
PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str())));
- *outBinder = tryGetBinder(name, true);
+ *outBinder = tryGetBinder(name, true).service;
// returns ok regardless of result for legacy reasons
return Status::ok();
}
@@ -410,7 +410,16 @@
return Status::ok();
}
-Status ServiceManager::checkService(const std::string& name, os::Service* outService) {
+Status ServiceManager::checkService(const std::string& name, sp<IBinder>* outBinder) {
+ SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS(
+ PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str())));
+
+ *outBinder = tryGetBinder(name, false).service;
+ // returns ok regardless of result for legacy reasons
+ return Status::ok();
+}
+
+Status ServiceManager::checkService2(const std::string& name, os::Service* outService) {
SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS(
PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str())));
@@ -430,13 +439,15 @@
return os::Service::make<os::Service::Tag::accessor>(nullptr);
}
return os::Service::make<os::Service::Tag::accessor>(
- tryGetBinder(*accessorName, startIfNotFound));
+ tryGetBinder(*accessorName, startIfNotFound).service);
} else {
- return os::Service::make<os::Service::Tag::binder>(tryGetBinder(name, startIfNotFound));
+ return os::Service::make<os::Service::Tag::serviceWithMetadata>(
+ tryGetBinder(name, startIfNotFound));
}
}
-sp<IBinder> ServiceManager::tryGetBinder(const std::string& name, bool startIfNotFound) {
+os::ServiceWithMetadata ServiceManager::tryGetBinder(const std::string& name,
+ bool startIfNotFound) {
SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS(
PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str())));
@@ -450,13 +461,13 @@
if (!service->allowIsolated && is_multiuser_uid_isolated(ctx.uid)) {
LOG(WARNING) << "Isolated app with UID " << ctx.uid << " requested '" << name
<< "', but the service is not allowed for isolated apps.";
- return nullptr;
+ return os::ServiceWithMetadata();
}
out = service->binder;
}
if (!mAccess->canFind(ctx, name)) {
- return nullptr;
+ return os::ServiceWithMetadata();
}
if (!out && startIfNotFound) {
@@ -473,8 +484,11 @@
CHECK(handleServiceClientCallback(2 /* sm + transaction */, name, false));
service->guaranteeClient = true;
}
-
- return out;
+ os::ServiceWithMetadata serviceWithMetadata = os::ServiceWithMetadata();
+ serviceWithMetadata.service = out;
+ serviceWithMetadata.isLazyService =
+ service ? service->dumpPriority & FLAG_IS_LAZY_SERVICE : false;
+ return serviceWithMetadata;
}
bool isValidServiceName(const std::string& name) {
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
index c92141b..5c4d891 100644
--- a/cmds/servicemanager/ServiceManager.h
+++ b/cmds/servicemanager/ServiceManager.h
@@ -46,7 +46,8 @@
// getService will try to start any services it cannot find
binder::Status getService(const std::string& name, sp<IBinder>* outBinder) override;
binder::Status getService2(const std::string& name, os::Service* outService) override;
- binder::Status checkService(const std::string& name, os::Service* outService) override;
+ binder::Status checkService(const std::string& name, sp<IBinder>* outBinder) override;
+ binder::Status checkService2(const std::string& name, os::Service* outService) override;
binder::Status addService(const std::string& name, const sp<IBinder>& binder,
bool allowIsolated, int32_t dumpPriority) override;
binder::Status listServices(int32_t dumpPriority, std::vector<std::string>* outList) override;
@@ -114,7 +115,7 @@
void removeClientCallback(const wp<IBinder>& who, ClientCallbackMap::iterator* it);
os::Service tryGetService(const std::string& name, bool startIfNotFound);
- sp<IBinder> tryGetBinder(const std::string& name, bool startIfNotFound);
+ os::ServiceWithMetadata tryGetBinder(const std::string& name, bool startIfNotFound);
binder::Status canAddService(const Access::CallingContext& ctx, const std::string& name,
std::optional<std::string>* accessor);
binder::Status canFindService(const Access::CallingContext& ctx, const std::string& name,
diff --git a/cmds/servicemanager/main.cpp b/cmds/servicemanager/main.cpp
index c126e91..df5a8ed 100644
--- a/cmds/servicemanager/main.cpp
+++ b/cmds/servicemanager/main.cpp
@@ -165,6 +165,7 @@
IPCThreadState::self()->disableBackgroundScheduling(true);
sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());
+ manager->setRequestingSid(true);
if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
LOG(ERROR) << "Could not self register servicemanager";
}
diff --git a/cmds/servicemanager/test_sm.cpp b/cmds/servicemanager/test_sm.cpp
index 95f459f..7ad84fa 100644
--- a/cmds/servicemanager/test_sm.cpp
+++ b/cmds/servicemanager/test_sm.cpp
@@ -92,6 +92,11 @@
auto sm = getPermissiveServiceManager();
EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+
+ EXPECT_TRUE(sm->addService("lazyfoo", getBinder(), false /*allowIsolated*/,
+ IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT |
+ IServiceManager::FLAG_IS_LAZY_SERVICE)
+ .isOk());
}
TEST(AddService, EmptyNameDisallowed) {
@@ -156,7 +161,7 @@
Service outA;
EXPECT_TRUE(sm->getService2("foo", &outA).isOk());
- EXPECT_EQ(serviceA, outA.get<Service::Tag::binder>());
+ EXPECT_EQ(serviceA, outA.get<Service::Tag::serviceWithMetadata>().service);
sp<IBinder> outBinderA;
EXPECT_TRUE(sm->getService("foo", &outBinderA).isOk());
EXPECT_EQ(serviceA, outBinderA);
@@ -168,7 +173,7 @@
Service outB;
EXPECT_TRUE(sm->getService2("foo", &outB).isOk());
- EXPECT_EQ(serviceB, outB.get<Service::Tag::binder>());
+ EXPECT_EQ(serviceB, outB.get<Service::Tag::serviceWithMetadata>().service);
sp<IBinder> outBinderB;
EXPECT_TRUE(sm->getService("foo", &outBinderB).isOk());
EXPECT_EQ(serviceB, outBinderB);
@@ -195,10 +200,15 @@
Service out;
EXPECT_TRUE(sm->getService2("foo", &out).isOk());
- EXPECT_EQ(service, out.get<Service::Tag::binder>());
+ EXPECT_EQ(service, out.get<Service::Tag::serviceWithMetadata>().service);
sp<IBinder> outBinder;
EXPECT_TRUE(sm->getService("foo", &outBinder).isOk());
EXPECT_EQ(service, outBinder);
+
+ EXPECT_TRUE(sm->checkService2("foo", &out).isOk());
+ EXPECT_EQ(service, out.get<Service::Tag::serviceWithMetadata>().service);
+ EXPECT_TRUE(sm->checkService("foo", &outBinder).isOk());
+ EXPECT_EQ(service, outBinder);
}
TEST(GetService, NonExistant) {
@@ -206,7 +216,7 @@
Service out;
EXPECT_TRUE(sm->getService2("foo", &out).isOk());
- EXPECT_EQ(nullptr, out.get<Service::Tag::binder>());
+ EXPECT_EQ(nullptr, out.get<Service::Tag::serviceWithMetadata>().service);
sp<IBinder> outBinder;
EXPECT_TRUE(sm->getService("foo", &outBinder).isOk());
EXPECT_EQ(nullptr, outBinder);
@@ -227,7 +237,7 @@
Service out;
// returns nullptr but has OK status for legacy compatibility
EXPECT_TRUE(sm->getService2("foo", &out).isOk());
- EXPECT_EQ(nullptr, out.get<Service::Tag::binder>());
+ EXPECT_EQ(nullptr, out.get<Service::Tag::serviceWithMetadata>().service);
sp<IBinder> outBinder;
EXPECT_TRUE(sm->getService("foo", &outBinder).isOk());
EXPECT_EQ(nullptr, outBinder);
@@ -257,7 +267,7 @@
Service out;
EXPECT_TRUE(sm->getService2("foo", &out).isOk());
- EXPECT_EQ(service, out.get<Service::Tag::binder>());
+ EXPECT_EQ(service, out.get<Service::Tag::serviceWithMetadata>().service);
sp<IBinder> outBinder;
EXPECT_TRUE(sm->getService("foo", &outBinder).isOk());
EXPECT_EQ(service, outBinder);
@@ -289,7 +299,7 @@
Service out;
// returns nullptr but has OK status for legacy compatibility
EXPECT_TRUE(sm->getService2("foo", &out).isOk());
- EXPECT_EQ(nullptr, out.get<Service::Tag::binder>());
+ EXPECT_EQ(nullptr, out.get<Service::Tag::serviceWithMetadata>().service);
sp<IBinder> outBinder;
EXPECT_TRUE(sm->getService("foo", &outBinder).isOk());
EXPECT_EQ(nullptr, outBinder);
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index 0dda5e8..f320504 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -317,12 +317,24 @@
}
prebuilt_etc {
+ name: "android.hardware.telephony.satellite.prebuilt.xml",
+ src: "android.hardware.telephony.satellite.xml",
+ defaults: ["frameworks_native_data_etc_defaults"],
+}
+
+prebuilt_etc {
name: "android.hardware.telephony.ims.singlereg.prebuilt.xml",
src: "android.hardware.telephony.ims.singlereg.xml",
defaults: ["frameworks_native_data_etc_defaults"],
}
prebuilt_etc {
+ name: "android.hardware.telephony.messaging.prebuilt.xml",
+ src: "android.hardware.telephony.messaging.xml",
+ defaults: ["frameworks_native_data_etc_defaults"],
+}
+
+prebuilt_etc {
name: "android.hardware.thread_network.prebuilt.xml",
src: "android.hardware.thread_network.xml",
defaults: ["frameworks_native_data_etc_defaults"],
diff --git a/data/etc/android.hardware.bluetooth_le.channel_sounding.xml b/data/etc/android.hardware.bluetooth_le.channel_sounding.xml
new file mode 100644
index 0000000..f0ee5d9
--- /dev/null
+++ b/data/etc/android.hardware.bluetooth_le.channel_sounding.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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.
+-->
+<!-- Adds the feature indicating support for the BLE Channel sounding -->
+<permissions>
+ <feature name="android.hardware.bluetooth_le.channel_sounding" />
+</permissions>
diff --git a/data/etc/android.hardware.telephony.messaging.xml b/data/etc/android.hardware.telephony.messaging.xml
new file mode 100644
index 0000000..0e96123
--- /dev/null
+++ b/data/etc/android.hardware.telephony.messaging.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2025 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.
+-->
+
+<!-- Feature for devices with messaging. -->
+<permissions>
+ <feature name="android.hardware.telephony" />
+ <feature name="android.hardware.telephony.radio.access" />
+ <feature name="android.hardware.telephony.subscription" />
+ <feature name="android.hardware.telephony.messaging" />
+</permissions>
diff --git a/data/etc/android.hardware.vulkan.version-1_4.xml b/data/etc/android.hardware.vulkan.version-1_4.xml
new file mode 100644
index 0000000..010f6da
--- /dev/null
+++ b/data/etc/android.hardware.vulkan.version-1_4.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2024 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 has a Vulkan
+ driver that supports API version 1.4 (0x00404000) -->
+<permissions>
+ <feature name="android.hardware.vulkan.version" version="4210688" />
+</permissions>
diff --git a/data/etc/android.hardware.xr.input.controller.xml b/data/etc/android.hardware.xr.input.controller.xml
new file mode 100644
index 0000000..1fb8b41
--- /dev/null
+++ b/data/etc/android.hardware.xr.input.controller.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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 to indicate the device supports
+ input from XR controllers. -->
+<permissions>
+ <feature name="android.hardware.xr.input.controller" />
+</permissions>
diff --git a/data/etc/android.hardware.xr.input.eye_tracking.xml b/data/etc/android.hardware.xr.input.eye_tracking.xml
new file mode 100644
index 0000000..8c6c2ed
--- /dev/null
+++ b/data/etc/android.hardware.xr.input.eye_tracking.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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 to indicate the device supports
+ input from an XR user's eyes. -->
+<permissions>
+ <feature name="android.hardware.xr.input.eye_tracking" />
+</permissions>
diff --git a/data/etc/android.hardware.xr.input.hand_tracking.xml b/data/etc/android.hardware.xr.input.hand_tracking.xml
new file mode 100644
index 0000000..6de3bee
--- /dev/null
+++ b/data/etc/android.hardware.xr.input.hand_tracking.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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 to indicate the device supports
+ input from an XR user's hands. -->
+<permissions>
+ <feature name="android.hardware.xr.input.hand_tracking" />
+</permissions>
diff --git a/data/etc/android.software.xr.api.openxr-1_0.xml b/data/etc/android.software.xr.api.openxr-1_0.xml
new file mode 100644
index 0000000..71c4a94
--- /dev/null
+++ b/data/etc/android.software.xr.api.openxr-1_0.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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 to indicate the device has a runtime
+ that supports OpenXR 1.0 (0x00010000). -->
+<permissions>
+ <feature name="android.software.xr.api.openxr" version="65536" />
+</permissions>
diff --git a/data/etc/android.software.xr.api.openxr-1_1.xml b/data/etc/android.software.xr.api.openxr-1_1.xml
new file mode 100644
index 0000000..45c1065
--- /dev/null
+++ b/data/etc/android.software.xr.api.openxr-1_1.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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 to indicate the device has a runtime
+ that supports OpenXR 1.1 (0x00010001). -->
+<permissions>
+ <feature name="android.software.xr.api.openxr" version="65537" />
+</permissions>
diff --git a/data/etc/android.software.xr.api.openxr-1_2.xml b/data/etc/android.software.xr.api.openxr-1_2.xml
new file mode 100644
index 0000000..ba11b8d
--- /dev/null
+++ b/data/etc/android.software.xr.api.openxr-1_2.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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 to indicate the device has a runtime
+ that supports OpenXR 1.2 (0x00010002). -->
+<permissions>
+ <feature name="android.software.xr.api.openxr" version="65538" />
+</permissions>
diff --git a/data/etc/android.software.xr.api.spatial-1.xml b/data/etc/android.software.xr.api.spatial-1.xml
new file mode 100644
index 0000000..ce425aa
--- /dev/null
+++ b/data/etc/android.software.xr.api.spatial-1.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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 to indicate the device has a runtime
+ that supports Android XR Spatial APIs, version 1. -->
+<permissions>
+ <feature name="android.software.xr.api.spatial" version="1" />
+</permissions>
diff --git a/data/etc/go_handheld_core_hardware.xml b/data/etc/go_handheld_core_hardware.xml
index 8df7fdb..a092842 100644
--- a/data/etc/go_handheld_core_hardware.xml
+++ b/data/etc/go_handheld_core_hardware.xml
@@ -51,6 +51,9 @@
<!-- Feature to specify if the device supports adding device admins. -->
<feature name="android.software.device_admin" />
+ <!-- Feature to specify if the device support managed users. -->
+ <feature name="android.software.managed_users" />
+
<!-- Devices with all optimizations required to support VR Mode and
pass all CDD requirements for this feature may include
android.hardware.vr.high_performance -->
diff --git a/include/OWNERS b/include/OWNERS
index c98e87a..7f847e8 100644
--- a/include/OWNERS
+++ b/include/OWNERS
@@ -1,5 +1,4 @@
alecmouri@google.com
-alexeykuzmin@google.com
dangittik@google.com
jreck@google.com
lajos@google.com
diff --git a/include/android/OWNERS b/include/android/OWNERS
index fad8c1b..9dfa279 100644
--- a/include/android/OWNERS
+++ b/include/android/OWNERS
@@ -3,3 +3,11 @@
# Window manager
per-file surface_control_input_receiver.h = file:platform/frameworks/base:/services/core/java/com/android/server/wm/OWNERS
per-file input_transfer_token.h = file:platform/frameworks/base:/services/core/java/com/android/server/wm/OWNERS
+
+# CoGS
+per-file *luts* = file:platform/frameworks/base:/graphics/java/android/graphics/OWNERS
+
+# ADPF
+per-file performance_hint.h = file:platform/frameworks/base:/ADPF_OWNERS
+per-file system_health.h = file:platform/frameworks/base:/ADPF_OWNERS
+per-file thermal.h = file:platform/frameworks/base:/ADPF_OWNERS
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index bec3283..2622a01 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -318,7 +318,7 @@
/**
* Gets the token used by the platform to identify the frame timeline at the given \c index.
- * q
+ *
* Available since API level 33.
*
* \param index index of a frame timeline, in \f( [0, FrameTimelinesLength) \f). See
diff --git a/include/android/display_luts.h b/include/android/display_luts.h
new file mode 100644
index 0000000..eae2bfd
--- /dev/null
+++ b/include/android/display_luts.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+/**
+ * @addtogroup NativeActivity Native Activity
+ * @{
+ */
+
+/**
+ * @file display_luts.h
+ */
+#pragma once
+
+#include <inttypes.h>
+
+__BEGIN_DECLS
+
+/**
+ * The dimension of the lut
+ */
+enum ADisplayLuts_Dimension : int32_t {
+ ADISPLAYLUTS_ONE_DIMENSION = 1,
+ ADISPLAYLUTS_THREE_DIMENSION = 3,
+};
+typedef enum ADisplayLuts_Dimension ADisplayLuts_Dimension;
+
+/**
+ * The sampling key used by the lut
+ */
+enum ADisplayLuts_SamplingKey : int32_t {
+ ADISPLAYLUTS_SAMPLINGKEY_RGB = 0,
+ ADISPLAYLUTS_SAMPLINGKEY_MAX_RGB = 1,
+ ADISPLAYLUTS_SAMPLINGKEY_CIE_Y = 2,
+};
+typedef enum ADisplayLuts_SamplingKey ADisplayLuts_SamplingKey;
+
+/**
+ * Used to get and set display luts entry
+ */
+typedef struct ADisplayLutsEntry ADisplayLutsEntry;
+
+/**
+ * Used to get and set display luts
+ */
+typedef struct ADisplayLuts ADisplayLuts;
+
+/**
+ * Creates a \a ADisplayLutsEntry entry.
+ *
+ * You are responsible for mamanging the memory of the returned object.
+ * Always call \a ADisplayLutsEntry_destroy to release it after use.
+ *
+ * Functions like \a ADisplayLuts_set create their own copies of entries,
+ * therefore they don't take the ownership of the instance created by
+ * \a ADisplayLutsEntry_create.
+ *
+ * @param buffer The lut raw buffer. The function creates a copy of it and does not need to
+ * outlive the life of the ADisplayLutsEntry.
+ * @param length The length of lut raw buffer
+ * @param dimension The dimension of the lut. see \a ADisplayLuts_Dimension
+ * @param key The sampling key used by the lut. see \a ADisplayLuts_SamplingKey
+ * @return a new \a ADisplayLutsEntry instance.
+ */
+ADisplayLutsEntry* _Nonnull ADisplayLutsEntry_createEntry(float* _Nonnull buffer,
+ int32_t length, ADisplayLuts_Dimension dimension, ADisplayLuts_SamplingKey key)
+ __INTRODUCED_IN(36);
+
+/**
+ * Destroy the \a ADisplayLutsEntry instance.
+ *
+ * @param entry The entry to be destroyed
+ */
+void ADisplayLutsEntry_destroy(ADisplayLutsEntry* _Nullable entry) __INTRODUCED_IN(36);
+
+/**
+ * Gets the dimension of the entry.
+ *
+ * The function is only valid for the lifetime of the `entry`.
+ *
+ * @param entry The entry to query
+ * @return the dimension of the lut
+ */
+ADisplayLuts_Dimension ADisplayLutsEntry_getDimension(const ADisplayLutsEntry* _Nonnull entry)
+ __INTRODUCED_IN(36);
+
+/**
+ * Gets the size for each dimension of the entry.
+ *
+ * The function is only valid for the lifetime of the `entry`.
+ *
+ * @param entry The entry to query
+ * @return the size of each dimension of the lut
+ */
+int32_t ADisplayLutsEntry_getSize(const ADisplayLutsEntry* _Nonnull entry)
+ __INTRODUCED_IN(36);
+
+/**
+ * Gets the sampling key used by the entry.
+ *
+ * The function is only valid for the lifetime of the `entry`.
+ *
+ * @param entry The entry to query
+ * @return the sampling key used by the lut
+ */
+ADisplayLuts_SamplingKey ADisplayLutsEntry_getSamplingKey(const ADisplayLutsEntry* _Nonnull entry)
+ __INTRODUCED_IN(36);
+
+/**
+ * Gets the lut buffer of the entry.
+ *
+ * The function is only valid for the lifetime of the `entry`.
+ *
+ * @param entry The entry to query
+ * @return a pointer to the raw lut buffer
+ */
+const float* _Nonnull ADisplayLutsEntry_getBuffer(const ADisplayLutsEntry* _Nonnull entry)
+ __INTRODUCED_IN(36);
+
+/**
+ * Creates a \a ADisplayLuts instance.
+ *
+ * You are responsible for mamanging the memory of the returned object.
+ * Always call \a ADisplayLuts_destroy to release it after use. E.g., after calling
+ * the function \a ASurfaceTransaction_setLuts.
+ *
+ * @return a new \a ADisplayLuts instance
+ */
+ADisplayLuts* _Nonnull ADisplayLuts_create() __INTRODUCED_IN(36);
+
+/**
+ * Sets Luts in order to be applied.
+ *
+ * The function accepts a single 1D Lut, or a single 3D Lut or both 1D and 3D Lut in order.
+ * And the function will replace any previously set lut(s).
+ * If you want to clear the previously set lut(s), set `entries` to be nullptr,
+ * and `numEntries` will be internally ignored.
+ *
+ * @param luts the pointer of the \a ADisplayLuts instance
+ * @param entries the pointer of the array of lut entries to be applied
+ * @param numEntries the number of lut entries. The value should be either 1 or 2.
+ */
+void ADisplayLuts_setEntries(ADisplayLuts* _Nonnull luts,
+ ADisplayLutsEntry* _Nullable *_Nullable entries, int32_t numEntries) __INTRODUCED_IN(36);
+
+/**
+ * Deletes the \a ADisplayLuts instance.
+ *
+ * @param luts The luts to be destroyed
+ */
+void ADisplayLuts_destroy(ADisplayLuts* _Nullable luts) __INTRODUCED_IN(36);
+
+__END_DECLS
+
+/** @} */
\ No newline at end of file
diff --git a/include/android/input.h b/include/android/input.h
index ee98d7a..2f6c5b5 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -849,6 +849,7 @@
* Refer to the documentation on the MotionEvent class for descriptions of each button.
*/
enum {
+ // LINT.IfChange(AMOTION_EVENT_BUTTON)
/** primary */
AMOTION_EVENT_BUTTON_PRIMARY = 1 << 0,
/** secondary */
@@ -861,6 +862,7 @@
AMOTION_EVENT_BUTTON_FORWARD = 1 << 4,
AMOTION_EVENT_BUTTON_STYLUS_PRIMARY = 1 << 5,
AMOTION_EVENT_BUTTON_STYLUS_SECONDARY = 1 << 6,
+ // LINT.ThenChange(/frameworks/native/libs/input/rust/input.rs,/frameworks/native/services/inputflinger/tests/fuzzers/FuzzedInputStream.h)
};
/**
diff --git a/include/android/keycodes.h b/include/android/keycodes.h
index 79cdbca..495e0bd 100644
--- a/include/android/keycodes.h
+++ b/include/android/keycodes.h
@@ -843,6 +843,44 @@
AKEYCODE_EMOJI_PICKER = 317,
/** Take Screenshot */
AKEYCODE_SCREENSHOT = 318,
+ /** To start dictate to an input field */
+ AKEYCODE_DICTATE = 319,
+ /** AC New */
+ AKEYCODE_NEW = 320,
+ /** AC Close */
+ AKEYCODE_CLOSE = 321,
+ /** To toggle 'Do Not Disturb' mode */
+ AKEYCODE_DO_NOT_DISTURB = 322,
+ /** To Print */
+ AKEYCODE_PRINT = 323,
+ /** To Lock the screen */
+ AKEYCODE_LOCK = 324,
+ /** To toggle fullscreen mode (on the current application) */
+ AKEYCODE_FULLSCREEN = 325,
+ /** F13 key */
+ AKEYCODE_F13 = 326,
+ /** F14 key */
+ AKEYCODE_F14 = 327,
+ /** F15 key */
+ AKEYCODE_F15 = 328,
+ /** F16 key */
+ AKEYCODE_F16 = 329,
+ /** F17 key */
+ AKEYCODE_F17 = 330,
+ /** F18 key */
+ AKEYCODE_F18 = 331,
+ /** F19 key */
+ AKEYCODE_F19 = 332,
+ /** F20 key */
+ AKEYCODE_F20 = 333,
+ /** F21 key */
+ AKEYCODE_F21 = 334,
+ /** F22 key */
+ AKEYCODE_F22 = 335,
+ /** F23 key */
+ AKEYCODE_F23 = 336,
+ /** F24 key */
+ AKEYCODE_F24 = 337,
// NOTE: If you add a new keycode here you must also add it to several other files.
// Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/include/android/looper.h b/include/android/looper.h
index d80a366..409db84 100644
--- a/include/android/looper.h
+++ b/include/android/looper.h
@@ -90,20 +90,23 @@
ALOOPER_POLL_WAKE = -1,
/**
- * Result from ALooper_pollOnce() and ALooper_pollAll():
- * One or more callbacks were executed.
+ * Result from ALooper_pollOnce():
+ * One or more callbacks were executed. The poll may also have been
+ * explicitly woken by ALooper_wake().
*/
ALOOPER_POLL_CALLBACK = -2,
/**
* Result from ALooper_pollOnce() and ALooper_pollAll():
- * The timeout expired.
+ * The timeout expired. The poll may also have been explicitly woken by
+ * ALooper_wake().
*/
ALOOPER_POLL_TIMEOUT = -3,
/**
* Result from ALooper_pollOnce() and ALooper_pollAll():
- * An error occurred.
+ * An error occurred. The poll may also have been explicitly woken by
+ * ALooper_wake().
*/
ALOOPER_POLL_ERROR = -4,
};
@@ -182,10 +185,13 @@
* If the timeout is zero, returns immediately without blocking.
* If the timeout is negative, waits indefinitely until an event appears.
*
+ * **All return values may also imply ALOOPER_POLL_WAKE.** If you call this in a
+ * loop, you must treat all return values as if they also indicated
+ * ALOOPER_POLL_WAKE.
+ *
* Returns ALOOPER_POLL_WAKE if the poll was awoken using ALooper_wake() before
* the timeout expired and no callbacks were invoked and no other file
- * descriptors were ready. **All return values may also imply
- * ALOOPER_POLL_WAKE.**
+ * descriptors were ready.
*
* Returns ALOOPER_POLL_CALLBACK if one or more callbacks were invoked. The poll
* may also have been explicitly woken by ALooper_wake.
@@ -214,15 +220,15 @@
* data has been consumed or a file descriptor is available with no callback.
* This function will never return ALOOPER_POLL_CALLBACK.
*
- * This API cannot be used safely, but a safe alternative exists (see below). As
- * such, new builds will not be able to call this API and must migrate to the
- * safe API. Binary compatibility is preserved to support already-compiled apps.
+ * This API will not reliably respond to ALooper_wake. As such, this API is
+ * hidden and callers should migrate to ALooper_pollOnce. Binary compatibility
+ * is preserved to support already-compiled apps.
*
- * \bug ALooper_pollAll will not wake in response to ALooper_wake calls if it
+ * \bug ALooper_pollAll() will not wake in response to ALooper_wake() calls if it
* also handles another event at the same time.
*
- * \deprecated Calls to ALooper_pollAll should be replaced with
- * ALooper_pollOnce. If you call ALooper_pollOnce in a loop, you *must* treat
+ * \deprecated Calls to ALooper_pollAll() should be replaced with
+ * ALooper_pollOnce(). If you call ALooper_pollOnce() in a loop, you *must* treat
* all return values as if they also indicate ALOOPER_POLL_WAKE.
*/
int ALooper_pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData)
@@ -235,6 +241,8 @@
*
* This method can be called on any thread.
* This method returns immediately.
+ *
+ * \bug ALooper_pollAll() will not reliably wake in response to ALooper_wake().
*/
void ALooper_wake(ALooper* looper);
diff --git a/include/android/performance_hint.h b/include/android/performance_hint.h
index 3f32a5a..52dbb61 100644
--- a/include/android/performance_hint.h
+++ b/include/android/performance_hint.h
@@ -19,9 +19,23 @@
*
* APerformanceHint allows apps to create performance hint sessions for groups
* of threads, and provide hints to the system about the workload of those threads,
- * to help the system more accurately allocate power for them. It is the NDK
+ * to help the system more accurately allocate resources for them. It is the NDK
* counterpart to the Java PerformanceHintManager SDK API.
*
+ * This API is intended for periodic workloads, such as frame production. Clients are
+ * expected to create an instance of APerformanceHintManager, create a session with
+ * that, and then set a target duration for the session. Then, they can report the actual
+ * work duration at the end of each cycle to inform the framework about how long those
+ * workloads are taking. The framework will then compare the actual durations to the target
+ * duration and attempt to help the client reach a steady state under the target.
+ *
+ * Unlike reportActualWorkDuration, the "notifyWorkload..." hints are intended to be sent in
+ * advance of large changes in the workload, to prevent them from going over the target
+ * when there is a sudden, unforseen change. Their effects are intended to last for only
+ * one cycle, after which reportActualWorkDuration will have a chance to catch up.
+ * These hints should be used judiciously, only in cases where the workload is changing
+ * substantially. To enforce that, they are tracked using a per-app rate limiter to avoid
+ * excessive hinting and encourage clients to be mindful about when to send them.
* @{
*/
@@ -35,6 +49,7 @@
#define ANDROID_NATIVE_PERFORMANCE_HINT_H
#include <sys/cdefs.h>
+#include <jni.h>
/******************************************************************
*
@@ -52,16 +67,21 @@
* - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
*/
-#include <android/api-level.h>
#include <stdbool.h>
#include <stdint.h>
#include <unistd.h>
+#if !defined(__DEPRECATED_IN)
+#define __DEPRECATED_IN(__api_level, ...) __attribute__((__deprecated__))
+#endif
+
__BEGIN_DECLS
struct APerformanceHintManager;
struct APerformanceHintSession;
struct AWorkDuration;
+struct ANativeWindow;
+struct ASurfaceControl;
/**
* {@link AWorkDuration} is an opaque type that represents the breakdown of the
@@ -97,9 +117,24 @@
typedef struct APerformanceHintManager APerformanceHintManager;
/**
+ * An opaque type representing a handle to a performance hint session creation configuration.
+ * It is consumed by {@link APerformanceHint_createSessionUsingConfig}.
+ *
+ * A session creation config encapsulates the required information for creating a session. The only
+ * mandatory parameter is the set of TIDs, set using {@link ASessionCreationConfig_setTids}. Only
+ * parameters relevant to the session need to be set, and any unspecified functionality will be
+ * treated as unused on the session. Configurations without a valid set of TIDs, or which try to
+ * enable automatic timing without the graphics pipeline mode, are considered invalid.
+ *
+ * The caller may reuse this object and modify the settings in it to create additional sessions.
+ */
+typedef struct ASessionCreationConfig ASessionCreationConfig;
+
+/**
* An opaque type representing a handle to a performance hint session.
* A session can only be acquired from a {@link APerformanceHintManager}
- * with {@link APerformanceHint_createSession}. It must be
+ * with {@link APerformanceHint_createSession}
+ * or {@link APerformanceHint_createSessionUsingConfig}. It must be
* freed with {@link APerformanceHint_closeSession} after use.
*
* A Session represents a group of threads with an inter-related workload such that hints for
@@ -121,6 +156,9 @@
*/
typedef struct APerformanceHintSession APerformanceHintSession;
+typedef struct ANativeWindow ANativeWindow;
+typedef struct ASurfaceControl ASurfaceControl;
+
/**
* Acquire an instance of the performance hint manager.
*
@@ -139,7 +177,7 @@
* @param size The size of the list of threadIds.
* @param initialTargetWorkDurationNanos The target duration in nanoseconds for the new session.
* This must be positive if using the work duration API, or 0 otherwise.
- * @return APerformanceHintManager instance on success, nullptr on failure.
+ * @return APerformanceHintSession pointer on success, nullptr on failure.
*/
APerformanceHintSession* _Nullable APerformanceHint_createSession(
APerformanceHintManager* _Nonnull manager,
@@ -147,21 +185,62 @@
int64_t initialTargetWorkDurationNanos) __INTRODUCED_IN(__ANDROID_API_T__);
/**
+ * Creates a session using arguments from a corresponding {@link ASessionCreationConfig}.
+ *
+ * Note: when using graphics pipeline mode, using too many cumulative graphics pipeline threads is
+ * not a failure and will still create a session, but it will cause all graphics pipeline sessions
+ * to have undefined behavior and the method will return EBUSY.
+ *
+ * @param manager The performance hint manager instance.
+ * @param config The configuration struct containing required information
+ * to create a session.
+ * @param sessionOut A client-provided pointer, which will be set to the new APerformanceHintSession
+ * on success or EBUSY, and to nullptr on failure.
+ *
+ * @return 0 on success.
+ * EINVAL if the creation config is in an invalid state.
+ * EPIPE if communication failed.
+ * ENOTSUP if hint sessions are not supported, or if auto timing is enabled but unsupported.
+ * EBUSY if too many graphics pipeline threads are passed.
+ */
+int APerformanceHint_createSessionUsingConfig(
+ APerformanceHintManager* _Nonnull manager,
+ ASessionCreationConfig* _Nonnull config,
+ APerformanceHintSession * _Nullable * _Nonnull sessionOut) __INTRODUCED_IN(36);
+
+/**
* Get preferred update rate information for this device.
*
+ * @deprecated Client side rate limiting is not necessary, rate limiting is handled in the
+ * framework. If you were using this to check for hint session support, please use
+ * {@link APerformanceHint_isFeatureSupported} instead.
+ *
* @param manager The performance hint manager instance.
* @return the preferred update rate supported by device software.
*/
int64_t APerformanceHint_getPreferredUpdateRateNanos(
- APerformanceHintManager* _Nonnull manager) __INTRODUCED_IN(__ANDROID_API_T__);
+ APerformanceHintManager* _Nonnull manager)
+ __INTRODUCED_IN(__ANDROID_API_T__) __DEPRECATED_IN(36, "Client-side rate limiting is not"
+ " necessary, use APerformanceHint_isFeatureSupported for support checking.");
+
+/**
+ * Get maximum number of graphics pipieline threads per-app for this device.
+ *
+ * @param manager The performance hint manager instance.
+ * @return the maximum number of graphics pipeline threads supported by device.
+ */
+ int APerformanceHint_getMaxGraphicsPipelineThreadsCount(
+ APerformanceHintManager* _Nonnull manager) __INTRODUCED_IN(36);
/**
* Updates this session's target duration for each cycle of work.
*
* @param session The performance hint session instance to update.
- * @param targetDurationNanos The new desired duration in nanoseconds. This must be positive.
+ * @param targetDurationNanos The new desired duration in nanoseconds. This must be positive for the
+ * session to report work durations, and may be zero to disable this functionality.
+ *
* @return 0 on success.
- * EINVAL if targetDurationNanos is not positive.
+ * EINVAL if targetDurationNanos is less than zero.
* EPIPE if communication with the system service has failed.
*/
int APerformanceHint_updateTargetWorkDuration(
@@ -178,7 +257,7 @@
* @param actualDurationNanos The duration of time the thread group took to complete its last
* task in nanoseconds. This must be positive.
* @return 0 on success.
- * EINVAL if actualDurationNanos is not positive.
+ * EINVAL if actualDurationNanos is not positive or the target it not positive.
* EPIPE if communication with the system service has failed.
*/
int APerformanceHint_reportActualWorkDuration(
@@ -189,6 +268,9 @@
* Release the performance hint manager pointer acquired via
* {@link APerformanceHint_createSession}.
*
+ * This cannot be used to close a Java PerformanceHintManager.Session, as its
+ * lifecycle is tied to the object in the SDK.
+ *
* @param session The performance hint session instance to release.
*/
void APerformanceHint_closeSession(
@@ -198,15 +280,20 @@
* Set a list of threads to the performance hint session. This operation will replace
* the current list of threads with the given list of threads.
*
+ * Note: when using a session with the graphics pipeline mode enabled, using too many cumulative
+ * graphics pipeline threads is not a failure, but it will cause all graphics pipeline sessions to
+ * have undefined behavior and the method will return EBUSY.
+ *
* @param session The performance hint session instance to update.
* @param threadIds The list of threads to be associated with this session. They must be part of
* this app's thread group.
* @param size The size of the list of threadIds.
* @return 0 on success.
* EINVAL if the list of thread ids is empty or if any of the thread ids are not part of
- the thread group.
+ * the thread group.
* EPIPE if communication with the system service has failed.
* EPERM if any thread id doesn't belong to the application.
+ * EBUSY if too many graphics pipeline threads were passed.
*/
int APerformanceHint_setThreads(
APerformanceHintSession* _Nonnull session,
@@ -251,16 +338,196 @@
AWorkDuration* _Nonnull workDuration) __INTRODUCED_IN(__ANDROID_API_V__);
/**
+ * Informs the framework of an upcoming increase in the workload of this session.
+ * The user can specify whether the increase is expected to be on the CPU, GPU, or both.
+ *
+ * These hints should be sent shortly before the start of the cycle where the workload is going to
+ * change, or as early as possible during that cycle for maximum effect. Hints sent towards the end
+ * of the cycle may be interpreted as applying to the next cycle. Any unsupported hints will be
+ * silently dropped, to avoid the need for excessive support checking each time they are sent, and
+ * sending a hint for both CPU and GPU will count as two separate hints for the rate limiter. These
+ * hints should not be sent repeatedly for an ongoing expensive workload, as workload time reporting
+ * is intended to handle this.
+ *
+ * @param session The {@link APerformanceHintSession} instance to send a hint for.
+ * @param cpu Indicates if the workload increase is expected to affect the CPU.
+ * @param gpu Indicates if the workload increase is expected to affect the GPU.
+ * @param identifier A required string used to distinguish this specific hint, using utf-8 encoding.
+ * This string will only be held for the duration of the method, and can be discarded after.
+ *
+ * @return 0 on success.
+ * EBUSY if the hint was rate limited.
+ * EPIPE if communication with the system service has failed.
+ */
+int APerformanceHint_notifyWorkloadIncrease(
+ APerformanceHintSession* _Nonnull session,
+ bool cpu, bool gpu, const char* _Nonnull identifier) __INTRODUCED_IN(36);
+
+/**
+ * Informs the framework that the workload associated with this session is about to start, or that
+ * it is about to completely change, and that the system should discard any assumptions about its
+ * characteristics inferred from previous activity. The user can specify whether the reset is
+ * expected to affect the CPU, GPU, or both.
+ *
+ * These hints should be sent shortly before the start of the cycle where the workload is going to
+ * change, or as early as possible during that cycle for maximum effect. Hints sent towards the end
+ * of the cycle may be interpreted as applying to the next cycle. Any unsupported hints will be
+ * silently dropped, to avoid the need for excessive support checking each time they are sent, and
+ * sending a hint for both CPU and GPU will count as two separate hints for the rate limiter. These
+ * hints should not be sent repeatedly for an ongoing expensive workload, as workload time reporting
+ * is intended to handle this.
+ *
+ * @param session The {@link APerformanceHintSession} instance to send a hint for.
+ * @param cpu Indicates if the workload reset is expected to affect the CPU.
+ * @param gpu Indicates if the workload reset is expected to affect the GPU.
+ * @param identifier A required string used to distinguish this specific hint, using utf-8 encoding.
+ * This string will only be held for the duration of the method, and can be discarded after.
+ *
+ * @return 0 on success.
+ * EBUSY if the hint was rate limited.
+ * EPIPE if communication with the system service has failed.
+ */
+int APerformanceHint_notifyWorkloadReset(
+ APerformanceHintSession* _Nonnull session,
+ bool cpu, bool gpu, const char* _Nonnull identifier) __INTRODUCED_IN(36);
+
+/**
+ * Informs the framework of an upcoming one-off expensive workload cycle for a given session.
+ * This cycle will be treated as not representative of the workload as a whole, and it will be
+ * discarded the purposes of load tracking. The user can specify whether the workload spike is
+ * expected to be on the CPU, GPU, or both.
+ *
+ * These hints should be sent shortly before the start of the cycle where the workload is going to
+ * change, or as early as possible during that cycle for maximum effect. Hints sent towards the end
+ * of the cycle may be interpreted as applying to the next cycle. Any unsupported hints will be
+ * silently dropped, to avoid the need for excessive support checking each time they are sent, and
+ * sending a hint for both CPU and GPU will count as two separate hints for the rate limiter. These
+ * hints should not be sent repeatedly for an ongoing expensive workload, as workload time reporting
+ * is intended to handle this.
+ *
+ * @param session The {@link APerformanceHintSession} instance to send a hint for.
+ * @param cpu Indicates if the workload spike is expected to affect the CPU.
+ * @param gpu Indicates if the workload spike is expected to affect the GPU.
+ * @param identifier A required string used to distinguish this specific hint, using utf-8 encoding.
+ * This string will only be held for the duration of the method, and can be discarded after.
+ *
+ * @return 0 on success.
+ * EBUSY if the hint was rate limited.
+ * EPIPE if communication with the system service has failed.
+ */
+int APerformanceHint_notifyWorkloadSpike(
+ APerformanceHintSession* _Nonnull session,
+ bool cpu, bool gpu, const char* _Nonnull identifier) __INTRODUCED_IN(36);
+
+/**
+ * Associates a session with any {@link ASurfaceControl} or {@link ANativeWindow}
+ * instances managed by this session. Any previously associated objects that are not passed
+ * in again lose their association. Invalid or dead instances are ignored, and passing both
+ * lists as null drops all current associations.
+ *
+ * This method is primarily intended for sessions that manage the timing of an entire
+ * graphics pipeline end-to-end for frame pacing, such as those using the
+ * {@link ASessionCreationConfig_setGraphicsPipeline} API. However, any session directly
+ * or indirectly managing a graphics pipeline should still associate themselves with
+ * directly relevant ASurfaceControl or ANativeWindow instances for better optimization.
+ * Additionally, if the surface associated with a session changes, this method should be called
+ * again to re-create the association.
+ *
+ * To see any benefit from this method, the client must make sure they are updating the frame rate
+ * of attached surfaces using methods such as {@link ANativeWindow_setFrameRate}, or by updating
+ * any associated ASurfaceControls with transactions that have {ASurfaceTransaction_setFrameRate}.
+ *
+ * @param session The {@link APerformanceHintSession} instance to update.
+ * @param nativeWindows A pointer to a list of ANativeWindows associated with this session.
+ * nullptr can be passed to indicate there are no associated ANativeWindows.
+ * @param nativeWindowsSize The number of ANativeWindows in the list.
+ * @param surfaceControls A pointer to a list of ASurfaceControls associated with this session.
+ * nullptr can be passed to indicate there are no associated ASurfaceControls.
+ * @param surfaceControlsSize The number of ASurfaceControls in the list.
+ *
+ * @return 0 on success.
+ * EPIPE if communication has failed.
+ * ENOTSUP if this is not supported on the device.
+ */
+
+int APerformanceHint_setNativeSurfaces(APerformanceHintSession* _Nonnull session,
+ ANativeWindow* _Nonnull* _Nullable nativeWindows, size_t nativeWindowsSize,
+ ASurfaceControl* _Nonnull* _Nullable surfaceControls, size_t surfaceControlsSize)
+ __INTRODUCED_IN(36);
+
+/**
+ * This enum represents different aspects of performance hint functionality. These can be passed
+ * to {@link APerformanceHint_isFeatureSupported} to determine whether the device exposes support
+ * for that feature.
+ *
+ * Some of these features will not expose failure to the client if used when unsupported, to prevent
+ * the client from needing to worry about handling different logic for each possible support
+ * configuration. The exception to this is features with important user-facing side effects, such as
+ * {@link APERF_HINT_AUTO_CPU} and {@link APERF_HINT_AUTO_GPU} modes which expect the client not to
+ * report durations while they are active.
+ */
+typedef enum APerformanceHintFeature : int32_t {
+ /**
+ * This value represents all APerformanceHintSession functionality. Using the Performance Hint
+ * API at all if this is not enabled will likely result in either
+ * {@link APerformanceHintManager} or {@link APerformanceHintSession} failing to create, or the
+ * session having little to no benefit even if creation succeeds.
+ */
+ APERF_HINT_SESSIONS,
+
+ /**
+ * This value represents the power efficiency mode, as exposed by
+ * {@link ASessionCreationConfig_setPreferPowerEfficiency} and
+ * {@link APerformanceHint_setPreferPowerEfficiency}.
+ */
+ APERF_HINT_POWER_EFFICIENCY,
+
+ /**
+ * This value the ability for sessions to bind to surfaces using
+ * {@link APerformanceHint_setNativeSurfaces} or
+ * {@link ASessionCreationConfig_setNativeSurfaces}
+ */
+ APERF_HINT_SURFACE_BINDING,
+
+ /**
+ * This value represents the "graphics pipeline" mode, as exposed by
+ * {@link ASessionCreationConfig_setGraphicsPipeline}.
+ */
+ APERF_HINT_GRAPHICS_PIPELINE,
+
+ /**
+ * This value represents the automatic CPU timing feature, as exposed by
+ * {@link ASessionCreationConfig_setUseAutoTiming}.
+ */
+ APERF_HINT_AUTO_CPU,
+
+ /**
+ * This value represents the automatic GPU timing feature, as exposed by
+ * {@link ASessionCreationConfig_setUseAutoTiming}.
+ */
+ APERF_HINT_AUTO_GPU,
+} APerformanceHintFeature;
+
+/**
+ * Checks whether the device exposes support for a specific feature.
+ *
+ * @param feature The specific feature enum to check.
+ *
+ * @return false if unsupported, true if supported.
+ */
+bool APerformanceHint_isFeatureSupported(APerformanceHintFeature feature) __INTRODUCED_IN(36);
+
+/**
* Creates a new AWorkDuration. When the client finishes using {@link AWorkDuration}, it should
* call {@link AWorkDuration_release()} to destroy {@link AWorkDuration} and release all resources
* associated with it.
*
- * @return AWorkDuration on success and nullptr otherwise.
+ * @return AWorkDuration pointer.
*/
AWorkDuration* _Nonnull AWorkDuration_create() __INTRODUCED_IN(__ANDROID_API_V__);
/**
- * Destroys {@link AWorkDuration} and free all resources associated to it.
+ * Destroys a {@link AWorkDuration} and frees all resources associated with it.
*
* @param aWorkDuration The {@link AWorkDuration} created by calling {@link AWorkDuration_create()}
*/
@@ -309,6 +576,168 @@
void AWorkDuration_setActualGpuDurationNanos(AWorkDuration* _Nonnull aWorkDuration,
int64_t actualGpuDurationNanos) __INTRODUCED_IN(__ANDROID_API_V__);
+/**
+ * Return the APerformanceHintSession wrapped by a Java PerformanceHintManager.Session object.
+ *
+ * The Java session maintains ownership over the wrapped native session, so it cannot be closed
+ * using {@link APerformanceHint_closeSession}. The return value is valid until the Java object
+ * containing this value dies.
+ *
+ * The returned pointer is intended to be used by JNI calls to access native performance APIs using
+ * a Java hint session wrapper, and then immediately discarded. Using the pointer after the death of
+ * the Java container results in undefined behavior.
+ *
+ * @param env The Java environment where the PerformanceHintManager.Session lives.
+ * @param sessionObj The Java Session to unwrap.
+ *
+ * @return A pointer to the APerformanceHintManager that backs the Java Session.
+ */
+APerformanceHintSession* _Nonnull APerformanceHint_borrowSessionFromJava(
+ JNIEnv* _Nonnull env, jobject _Nonnull sessionObj) __INTRODUCED_IN(36);
+
+/*
+ * Creates a new ASessionCreationConfig.
+ *
+ * When the client finishes using {@link ASessionCreationConfig}, it should
+ * call {@link ASessionCreationConfig_release()} to destroy
+ * {@link ASessionCreationConfig} and release all resources
+ * associated with it.
+ *
+ * @return ASessionCreationConfig pointer.
+ */
+ASessionCreationConfig* _Nonnull ASessionCreationConfig_create()
+ __INTRODUCED_IN(36);
+
+/**
+ * Destroys a {@link ASessionCreationConfig} and frees all
+ * resources associated with it.
+ *
+ * @param config The {@link ASessionCreationConfig}
+ * created by calling {@link ASessionCreationConfig_create()}.
+ */
+void ASessionCreationConfig_release(
+ ASessionCreationConfig* _Nonnull config) __INTRODUCED_IN(36);
+
+/**
+ * Sets the tids to be associated with the session to be created.
+ *
+ * @param config The {@link ASessionCreationConfig}
+ * created by calling {@link ASessionCreationConfig_create()}
+ * @param tids The list of tids to be associated with this session. They must be part of
+ * this process' thread group.
+ * @param size The size of the list of tids.
+ */
+void ASessionCreationConfig_setTids(
+ ASessionCreationConfig* _Nonnull config,
+ const pid_t* _Nonnull tids, size_t size) __INTRODUCED_IN(36);
+
+/**
+ * Sets the initial target work duration in nanoseconds for the session to be created.
+ *
+ * @param config The {@link ASessionCreationConfig}
+ * created by calling {@link ASessionCreationConfig_create()}.
+ * @param targetWorkDurationNanos The parameter to specify a target duration in nanoseconds for the
+ * new session; this value must be positive to use the work duration API, and may be ignored
+ * otherwise or set to zero. Negative values are invalid.
+ */
+void ASessionCreationConfig_setTargetWorkDurationNanos(
+ ASessionCreationConfig* _Nonnull config,
+ int64_t targetWorkDurationNanos) __INTRODUCED_IN(36);
+
+/**
+ * Sets whether power efficiency mode will be enabled for the session.
+ * This tells the session that these threads can be
+ * safely scheduled to prefer power efficiency over performance.
+ *
+ * @param config The {@link ASessionCreationConfig}
+ * created by calling {@link ASessionCreationConfig_create()}.
+ * @param enabled Whether power efficiency mode will be enabled.
+ */
+void ASessionCreationConfig_setPreferPowerEfficiency(
+ ASessionCreationConfig* _Nonnull config, bool enabled) __INTRODUCED_IN(36);
+
+/**
+ * Sessions setting this hint are expected to time the critical path of
+ * graphics pipeline from end to end, with the total work duration
+ * representing the time from the start of frame production until the
+ * buffer is fully finished drawing.
+ *
+ * It should include any threads on the critical path of that pipeline,
+ * up to a limit accessible from {@link APerformanceHint_getMaxGraphicsPipelineThreadsCount()}.
+ *
+ * @param config The {@link ASessionCreationConfig}
+ * created by calling {@link ASessionCreationConfig_create()}.
+ * @param enabled Whether this session manages a graphics pipeline's critical path.
+ */
+void ASessionCreationConfig_setGraphicsPipeline(
+ ASessionCreationConfig* _Nonnull config, bool enabled) __INTRODUCED_IN(36);
+
+/**
+ * Associates the created session with any {@link ASurfaceControl} or {@link ANativeWindow}
+ * instances it will be managing. Invalid or dead instances are ignored.
+ *
+ * This method is primarily intended for sessions that manage the timing of an entire
+ * graphics pipeline end-to-end for frame pacing, such as those using the
+ * {@link ASessionCreationConfig_setGraphicsPipeline} API. However, any session directly
+ * or indirectly managing a graphics pipeline should still associate themselves with
+ * directly relevant ASurfaceControl or ANativeWindow instances for better optimization.
+ * Additionally, if the surface associated with a session changes, this method should be called
+ * again to re-create the association.
+ *
+ * To see any benefit from this method, the client must make sure they are updating the frame rate
+ * of attached surfaces using methods such as {@link ANativeWindow_setFrameRate}, or by updating
+ * any associated ASurfaceControls with transactions that have {ASurfaceTransaction_setFrameRate}.
+ *
+ *
+ * @param config The {@link ASessionCreationConfig}
+ * created by calling {@link ASessionCreationConfig_create()}.
+ * @param nativeWindows A pointer to a list of ANativeWindows associated with this session.
+ * nullptr can be passed to indicate there are no associated ANativeWindows.
+ * @param nativeWindowsSize The number of ANativeWindows in the list.
+ * @param surfaceControls A pointer to a list of ASurfaceControls associated with this session.
+ * nullptr can be passed to indicate there are no associated ASurfaceControls.
+ * @param surfaceControlsSize The number of ASurfaceControls in the list.
+ */
+void ASessionCreationConfig_setNativeSurfaces(
+ ASessionCreationConfig* _Nonnull config,
+ ANativeWindow* _Nonnull* _Nullable nativeWindows, size_t nativeWindowsSize,
+ ASurfaceControl* _Nonnull* _Nullable surfaceControls, size_t surfaceControlsSize)
+ __INTRODUCED_IN(36);
+
+/**
+ * Enable automatic timing mode for sessions using the GRAPHICS_PIPELINE API with an attached
+ * surface. In this mode, sessions do not need to report timing data for the CPU, GPU, or both
+ * depending on the configuration. To use this mode, sessions should set a native surface
+ * using {@ASessionCreationConfig_setNativeSurfaces}, enable graphics pipeline mode with
+ * {@link ASessionCreationConfig_setGraphicsPipeline()}, and then call this method to set whether
+ * automatic timing is desired for the CPU, GPU, or both. Trying to enable this without also
+ * enabling the graphics pipeline mode will cause session creation to fail.
+ *
+ * It is still be beneficial to set an accurate target time, as this may help determine
+ * timing information for some workloads where there is less information available from
+ * the framework, such as games. Additionally, reported CPU durations will be ignored
+ * while automatic CPU timing is enabled, and similarly GPU durations will be ignored
+ * when automatic GPU timing is enabled. When both are enabled, the entire
+ * {@link APerformanceHint_reportActualWorkDuration} call will be ignored, and the session will be
+ * managed completely automatically.
+ *
+ * If the client is manually controlling their frame rate for those surfaces, then they must make
+ * sure they are updating the frame rate with {@link ANativeWindow_setFrameRate}, or updating any
+ * associated ASurfaceControls with transactions that have {ASurfaceTransaction_setFrameRate} set.
+ *
+ * The user of this API should ensure this feature is supported by checking
+ * {@link APERF_HINT_AUTO_CPU} and {@link APERF_HINT_AUTO_GPU} with
+ * {@link APerformanceHint_isFeatureSupported} and falling back to manual timing if it is not.
+ * Trying to use automatic timing when it is unsupported will cause session creation to fail.
+ *
+ * @param config The {@link ASessionCreationConfig}
+ * created by calling {@link ASessionCreationConfig_create()}.
+ * @param cpu Whether to enable automatic timing for the CPU for this session.
+ * @param gpu Whether to enable automatic timing for the GPU for this session.
+ */
+void ASessionCreationConfig_setUseAutoTiming(
+ ASessionCreationConfig* _Nonnull config, bool cpu, bool gpu) __INTRODUCED_IN(36);
+
__END_DECLS
#endif // ANDROID_NATIVE_PERFORMANCE_HINT_H
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index 8d61e77..6323333 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -28,6 +28,7 @@
#include <sys/cdefs.h>
+#include <android/display_luts.h>
#include <android/choreographer.h>
#include <android/data_space.h>
#include <android/hardware_buffer.h>
@@ -713,6 +714,23 @@
__INTRODUCED_IN(__ANDROID_API_V__);
/**
+ * Sets the Lut(s) to be applied for the layer.
+ *
+ * The function makes a deep copy of the provided `luts`.
+ * Any modifications made to the `luts` object after calling this function
+ * will not affect the Lut(s) applied to the layer.
+ *
+ * @param surface_control The layer where Lut(s) is being applied
+ * @param luts The Lut(s) to be applied
+ *
+ * Available since API level 36.
+ */
+void ASurfaceTransaction_setLuts(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control,
+ const struct ADisplayLuts* _Nullable luts)
+ __INTRODUCED_IN(36);
+
+/**
* Same as ASurfaceTransaction_setFrameRateWithChangeStrategy(transaction, surface_control,
* frameRate, compatibility, ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS).
*
diff --git a/include/android/surface_control_input_receiver.h b/include/android/surface_control_input_receiver.h
index f0503f6..59d3a31 100644
--- a/include/android/surface_control_input_receiver.h
+++ b/include/android/surface_control_input_receiver.h
@@ -39,11 +39,11 @@
*
* \param motionEvent The motion event. This must be released with AInputEvent_release.
*
+ * \return true if the event is handled by the client, false otherwise.
* Available since API level 35.
*/
typedef bool (*AInputReceiver_onMotionEvent)(void *_Null_unspecified context,
- AInputEvent *_Nonnull motionEvent)
- __INTRODUCED_IN(__ANDROID_API_V__);
+ AInputEvent *_Nonnull motionEvent);
/**
* The AInputReceiver_onKeyEvent callback is invoked when the registered input channel receives
* a key event.
@@ -53,11 +53,12 @@
*
* \param keyEvent The key event. This must be released with AInputEvent_release.
*
+ * \return true if the event is handled by the client, false otherwise. System may generate
+ * a fallback key event if the event is not handled.
* Available since API level 35.
*/
typedef bool (*AInputReceiver_onKeyEvent)(void *_Null_unspecified context,
- AInputEvent *_Nonnull keyEvent)
- __INTRODUCED_IN(__ANDROID_API_V__);
+ AInputEvent *_Nonnull keyEvent);
typedef struct AInputReceiverCallbacks AInputReceiverCallbacks;
diff --git a/include/android/system_health.h b/include/android/system_health.h
new file mode 100644
index 0000000..bdb1413
--- /dev/null
+++ b/include/android/system_health.h
@@ -0,0 +1,447 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+/**
+* @defgroup SystemHealth
+*
+ * SystemHealth provides access to data about how various system resources are used by applications.
+ *
+ * CPU/GPU headroom APIs are designed to be best used by applications with consistent and intense
+ * workload such as games to query the remaining capacity headroom over a short period and perform
+ * optimization accordingly. Due to the nature of the fast job scheduling and frequency scaling of
+ * CPU and GPU, the headroom by nature will have "TOCTOU" problem which makes it less suitable for
+ * apps with inconsistent or low workload to take any useful action but simply monitoring. And to
+ * avoid oscillation it's not recommended to adjust workload too frequent (on each polling request)
+ * or too aggressively. As the headroom calculation is more based on reflecting past history usage
+ * than predicting future capacity. Take game as an example, if the API returns CPU headroom of 0 in
+ * one scenario (especially if it's constant across multiple calls), or some value significantly
+ * smaller than other scenarios, then it can reason that the recent performance result is more CPU
+ * bottlenecked. Then reducing the CPU workload intensity can help reserve some headroom to handle
+ * the load variance better, which can result in less frame drops or smooth FPS value. On the other
+ * hand, if the API returns large CPU headroom constantly, the app can be more confident to increase
+ * the workload and expect higher possibility of device meeting its performance expectation.
+ * App can also use thermal APIs to read the current thermal status and headroom first, then poll
+ * the CPU and GPU headroom if the device is (about to) getting thermal throttled. If the CPU/GPU
+ * headrooms provide enough significance such as one valued at 0 while the other at 100, then it can
+ * be used to infer that reducing CPU workload could be more efficient to cool down the device.
+ * There is a caveat that the power controller may scale down the frequency of the CPU and GPU due
+ * to thermal and other reasons, which can result in a higher than usual percentage usage of the
+ * capacity.
+ *
+* @{
+*/
+
+/**
+ * @file system_health.h
+ */
+
+#ifndef _ANDROID_SYSTEM_HEALTH_H
+#define _ANDROID_SYSTEM_HEALTH_H
+
+#include <sys/cdefs.h>
+
+/******************************************************************
+ *
+ * IMPORTANT NOTICE:
+ *
+ * This file is part of Android's set of stable system headers
+ * exposed by the Android NDK (Native Development Kit).
+ *
+ * Third-party source AND binary code relies on the definitions
+ * here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
+ *
+ * - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
+ * - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
+ * - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
+ * - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
+ */
+
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Params used to customize the calculation of CPU headroom.
+ *
+ * Also see {@link ASystemHealth_getCpuHeadroom}.
+ */
+typedef struct ACpuHeadroomParams ACpuHeadroomParams;
+
+/**
+ * Params used to customize the calculation of GPU headroom.
+ *
+ * Also see {@link ASystemHealth_getGpuHeadroom}.
+ */
+typedef struct AGpuHeadroomParams AGpuHeadroomParams;
+
+typedef enum ACpuHeadroomCalculationType : int32_t {
+ /**
+ * The headroom calculation type bases on minimum value over a specified window.
+ * Introduced in API level 36.
+ */
+ ACPU_HEADROOM_CALCULATION_TYPE_MIN = 0,
+ /**
+ * The headroom calculation type bases on average value over a specified window.
+ * Introduced in API level 36.
+ */
+ ACPU_HEADROOM_CALCULATION_TYPE_AVERAGE = 1,
+} ACpuHeadroomCalculationType;
+
+typedef enum AGpuHeadroomCalculationType : int32_t {
+ /**
+ * The headroom calculation type bases on minimum value over a specified window.
+ * Introduced in API level 36.
+ */
+ AGPU_HEADROOM_CALCULATION_TYPE_MIN = 0,
+ /**
+ * The headroom calculation type bases on average value over a specified window.
+ * Introduced in API level 36.
+ */
+ AGPU_HEADROOM_CALCULATION_TYPE_AVERAGE = 1,
+} AGpuHeadroomCalculationType;
+
+/**
+ * Sets the CPU headroom calculation window size in milliseconds.
+ *
+ * Available since API level 36.
+ *
+ * @param params The params to be set.
+ * @param windowMillis The window size in milliseconds ranges from
+ * {@link ASystemHealth_getCpuHeadroomCalculationWindowRange}. The smaller the
+ * window size, the larger fluctuation in the headroom value should be expected.
+ * The default value can be retrieved from the
+ * {@link #ACpuHeadroomParams_getCalculationWindowMillis} if not set. The device
+ * will try to use the closest feasible window size to this param.
+ */
+void ACpuHeadroomParams_setCalculationWindowMillis(ACpuHeadroomParams *_Nonnull params,
+ int windowMillis)
+__INTRODUCED_IN(36);
+
+/**
+ * Gets the CPU headroom calculation window size in milliseconds.
+ *
+ * This will return the default value chosen by the device if not set.
+ *
+ * Available since API level 36.
+ *
+ * @param params The params to read from.
+ * @return This will return the default value chosen by the device if the params is not set.
+ */
+int ACpuHeadroomParams_getCalculationWindowMillis(ACpuHeadroomParams* _Nonnull params)
+__INTRODUCED_IN(36);
+
+/**
+ * Sets the GPU headroom calculation window size in milliseconds.
+ *
+ * Available since API level 36.
+ *
+ * @param params The params to be set.
+ * @param windowMillis The window size in milliseconds ranges from
+ * {@link ASystemHealth_getGpuHeadroomCalculationWindowRange}. The smaller the
+ * window size, the larger fluctuation in the headroom value should be expected.
+ * The default value can be retrieved from the
+ * {@link #AGpuHeadroomParams_getCalculationWindowMillis} if not set. The device
+ * will try to use the closest feasible window size to this param.
+ */
+void AGpuHeadroomParams_setCalculationWindowMillis(AGpuHeadroomParams* _Nonnull params,
+ int windowMillis)
+__INTRODUCED_IN(36);
+
+/**
+ * Gets the GPU headroom calculation window size in milliseconds.
+ *
+ * This will return the default value chosen by the device if not set.
+ *
+ * Available since API level 36.
+ *
+ * @param params The params to read from.
+ * @return This will return the default value chosen by the device if the params is not set.
+ */
+int AGpuHeadroomParams_getCalculationWindowMillis(AGpuHeadroomParams* _Nonnull params)
+__INTRODUCED_IN(36);
+
+/**
+ * Sets the CPU headroom calculation type in {@link ACpuHeadroomParams}.
+ *
+ * Available since API level 36.
+ *
+ * @param params The params to be set.
+ * @param calculationType The headroom calculation type.
+ */
+void ACpuHeadroomParams_setCalculationType(ACpuHeadroomParams* _Nonnull params,
+ ACpuHeadroomCalculationType calculationType)
+__INTRODUCED_IN(36);
+
+/**
+ * Gets the CPU headroom calculation type in {@link ACpuHeadroomParams}.
+ *
+ * This will return the default value chosen by the device if not set.
+ *
+ * Available since API level 36.
+ *
+ * @param params The params to read from.
+ * @return The headroom calculation type.
+ */
+ACpuHeadroomCalculationType
+ACpuHeadroomParams_getCalculationType(ACpuHeadroomParams* _Nonnull params)
+__INTRODUCED_IN(36);
+
+/**
+ * Sets the GPU headroom calculation type in {@link AGpuHeadroomParams}.
+ *
+ * Available since API level 36.
+ *
+ * @param params The params to be set.
+ * @param calculationType The headroom calculation type.
+ */
+void AGpuHeadroomParams_setCalculationType(AGpuHeadroomParams* _Nonnull params,
+ AGpuHeadroomCalculationType calculationType)
+__INTRODUCED_IN(36);
+
+/**
+ * Gets the GPU headroom calculation type in {@link AGpuHeadroomParams}.
+ *
+ * This will return the default value chosen by the device if not set.
+ *
+ * Available since API level 36.
+ *
+ * @param params The params to read from.
+ * @return The headroom calculation type.
+ */
+AGpuHeadroomCalculationType
+AGpuHeadroomParams_getCalculationType(AGpuHeadroomParams* _Nonnull params)
+__INTRODUCED_IN(36);
+
+/**
+ * Sets the thread TIDs to track in {@link ACpuHeadroomParams}.
+ *
+ * The TIDs should belong to the same of the process that will make the headroom call. And they
+ * should not have different core affinity.
+ *
+ * If not set or set to empty, the headroom will be based on the PID of the process making the call.
+ *
+ * Available since API level 36.
+ *
+ * @param params The params to be set.
+ * @param tids Non-null array of TIDs, where maximum size can be read from
+ * {@link ASystemHealth_getMaxCpuHeadroomTidsSize}.
+ * @param tidsSize The size of the tids array.
+ */
+void ACpuHeadroomParams_setTids(ACpuHeadroomParams* _Nonnull params, const int* _Nonnull tids,
+ size_t tidsSize)
+__INTRODUCED_IN(36);
+
+/**
+ * Creates a new instance of {@link ACpuHeadroomParams}.
+ *
+ * When the client finishes using {@link ACpuHeadroomParams},
+ * {@link ACpuHeadroomParams_destroy} must be called to destroy
+ * and free up the resources associated with {@link ACpuHeadroomParams}.
+ *
+ * Available since API level 36.
+ *
+ * @return A new instance of {@link ACpuHeadroomParams}.
+ */
+ACpuHeadroomParams* _Nonnull ACpuHeadroomParams_create(void)
+__INTRODUCED_IN(36);
+
+/**
+ * Creates a new instance of {@link AGpuHeadroomParams}.
+ *
+ * When the client finishes using {@link AGpuHeadroomParams},
+ * {@link AGpuHeadroomParams_destroy} must be called to destroy
+ * and free up the resources associated with {@link AGpuHeadroomParams}.
+ *
+ * Available since API level 36.
+ *
+ * @return A new instance of {@link AGpuHeadroomParams}.
+ */
+AGpuHeadroomParams* _Nonnull AGpuHeadroomParams_create(void)
+__INTRODUCED_IN(36);
+
+/**
+ * Deletes the {@link ACpuHeadroomParams} instance.
+ *
+ * Available since API level 36.
+ *
+ * @param params The params to be deleted.
+ */
+void ACpuHeadroomParams_destroy(ACpuHeadroomParams* _Nullable params)
+__INTRODUCED_IN(36);
+
+/**
+ * Deletes the {@link AGpuHeadroomParams} instance.
+ *
+ * Available since API level 36.
+ *
+ * @param params The params to be deleted.
+ */
+void AGpuHeadroomParams_destroy(AGpuHeadroomParams* _Nullable params)
+__INTRODUCED_IN(36);
+
+/**
+ * Gets the maximum number of TIDs this device supports for getting CPU headroom.
+ *
+ * See {@link ACpuHeadroomParams_setTids}.
+ *
+ * Available since API level 36.
+ *
+ * @param outSize Non-null output pointer to the max size.
+ * @return 0 on success.
+ * ENOTSUP if the CPU headroom API is unsupported.
+ */
+int ASystemHealth_getMaxCpuHeadroomTidsSize(size_t* _Nonnull outSize);
+
+/**
+ * Gets the range of the calculation window size for CPU headroom.
+ *
+ * In API version 36, the range will be a superset of [50, 10000].
+ *
+ * Available since API level 36.
+ *
+ * @param outMinMillis Non-null output pointer to be set to the minimum window size in milliseconds.
+ * @param outMaxMillis Non-null output pointer to be set to the maximum window size in milliseconds.
+ * @return 0 on success.
+ * ENOTSUP if API is unsupported.
+ */
+int ASystemHealth_getCpuHeadroomCalculationWindowRange(int32_t* _Nonnull outMinMillis,
+ int32_t* _Nonnull outMaxMillis)
+__INTRODUCED_IN(36);
+
+/**
+ * Gets the range of the calculation window size for GPU headroom.
+ *
+ * In API version 36, the range will be a superset of [50, 10000].
+ *
+ * Available since API level 36.
+ *
+ * @param outMinMillis Non-null output pointer to be set to the minimum window size in milliseconds.
+ * @param outMaxMillis Non-null output pointer to be set to the maximum window size in milliseconds.
+ * @return 0 on success.
+ * ENOTSUP if API is unsupported.
+ */
+int ASystemHealth_getGpuHeadroomCalculationWindowRange(int32_t* _Nonnull outMinMillis,
+ int32_t* _Nonnull outMaxMillis)
+__INTRODUCED_IN(36);
+
+/**
+ * Provides an estimate of available CPU capacity headroom of the device.
+ *
+ * The value can be used by the calling application to determine if the workload was CPU bound and
+ * then take action accordingly to ensure that the workload can be completed smoothly. It can also
+ * be used with the thermal status and headroom to determine if reducing the CPU bound workload can
+ * help reduce the device temperature to avoid thermal throttling.
+ *
+ * If the params are valid, each call will perform at least one synchronous binder transaction that
+ * can take more than 1ms. So it's not recommended to call or wait for this on critical threads.
+ * Some devices may implement this as an on-demand API with lazy initialization, so the caller
+ * should expect higher latency when making the first call (especially with non-default params)
+ * since app starts or after changing params, as the device may need to change its data collection.
+ *
+ * Available since API level 36.
+ *
+ * @param params The params to customize the CPU headroom calculation, or nullptr to use default.
+ * @param outHeadroom Non-null output pointer to a single float, which will be set to the CPU
+ * headroom value. The value will be a single value or `Float.NaN` if it's
+ * temporarily unavailable due to server error or not enough user CPU workload.
+ * Each valid value ranges from [0, 100], where 0 indicates no more cpu resources
+ * can be granted.
+ * @return 0 on success.
+ * EPIPE if failed to get the CPU headroom.
+ * EPERM if the TIDs do not belong to the same process.
+ * ENOTSUP if API or requested params is unsupported.
+ */
+int ASystemHealth_getCpuHeadroom(const ACpuHeadroomParams* _Nullable params,
+ float* _Nonnull outHeadroom)
+__INTRODUCED_IN(36);
+
+/**
+ * Provides an estimate of available GPU capacity headroom of the device.
+ *
+ * The value can be used by the calling application to determine if the workload was GPU bound and
+ * then take action accordingly to ensure that the workload can be completed smoothly. It can also
+ * be used with the thermal status and headroom to determine if reducing the GPU bound workload can
+ * help reduce the device temperature to avoid thermal throttling.
+ *
+ * If the params are valid, each call will perform at least one synchronous binder transaction that
+ * can take more than 1ms. So it's not recommended to call or wait for this on critical threads.
+ * Some devices may implement this as an on-demand API with lazy initialization, so the caller
+ * should expect higher latency when making the first call (especially with non-default params)
+ * since app starts or after changing params, as the device may need to change its data collection.
+ *
+ * Available since API level 36
+ *
+ * @param params The params to customize the GPU headroom calculation, or nullptr to use default
+ * @param outHeadroom Non-null output pointer to a single float, which will be set to the GPU
+ * headroom value. The value will be a single value or `Float.NaN` if it's
+ * temporarily unavailable.
+ * Each valid value ranges from [0, 100], where 0 indicates no more gpu resources
+ * can be granted.
+ * @return 0 on success.
+ * EPIPE if failed to get the GPU headroom.
+ * ENOTSUP if API or requested params is unsupported.
+ */
+int ASystemHealth_getGpuHeadroom(const AGpuHeadroomParams* _Nullable params,
+ float* _Nonnull outHeadroom)
+__INTRODUCED_IN(36);
+
+/**
+ * Gets minimum polling interval for calling {@link ASystemHealth_getCpuHeadroom} in milliseconds.
+ *
+ * The {@link ASystemHealth_getCpuHeadroom} API may return cached result if called more frequently
+ * than the interval.
+ *
+ * Available since API level 36.
+ *
+ * @param outMinIntervalMillis Non-null output pointer to a int64_t, which
+ * will be set to the minimum polling interval in milliseconds.
+ * @return 0 on success.
+ * ENOTSUP if API is unsupported.
+ */
+int ASystemHealth_getCpuHeadroomMinIntervalMillis(int64_t* _Nonnull outMinIntervalMillis)
+__INTRODUCED_IN(36);
+
+/**
+ * Gets minimum polling interval for calling {@link ASystemHealth_getGpuHeadroom} in milliseconds.
+ *
+ * The {@link ASystemHealth_getGpuHeadroom} API may return cached result if called more frequently
+ * than the interval.
+ *
+ * Available since API level 36.
+ *
+ * @param outMinIntervalMillis Non-null output pointer to a int64_t, which
+ * will be set to the minimum polling interval in milliseconds.
+ * @return 0 on success.
+ * ENOTSUP if API is unsupported.
+ */
+int ASystemHealth_getGpuHeadroomMinIntervalMillis(int64_t* _Nonnull outMinIntervalMillis)
+__INTRODUCED_IN(36);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _ANDROID_SYSTEM_HEALTH_H
+
+/** @} */
diff --git a/include/android/thermal.h b/include/android/thermal.h
index 7f9d2ed..e5d46b5 100644
--- a/include/android/thermal.h
+++ b/include/android/thermal.h
@@ -140,45 +140,47 @@
* Available since API level 30.
*
* @param manager The manager instance to use to query the thermal status.
- * Acquired via {@link AThermal_acquireManager}.
+ * Acquired via {@link AThermal_acquireManager}.
*
* @return current thermal status, ATHERMAL_STATUS_ERROR on failure.
*/
AThermalStatus
-AThermal_getCurrentThermalStatus(AThermalManager* _Nonnull manager) __INTRODUCED_IN(30);
+AThermal_getCurrentThermalStatus(AThermalManager *_Nonnull manager) __INTRODUCED_IN(30);
/**
- * Register the thermal status listener for thermal status change.
+ * Register a thermal status listener for thermal status change.
*
* Available since API level 30.
*
* @param manager The manager instance to use to register.
- * Acquired via {@link AThermal_acquireManager}.
- * @param callback The callback function to be called when thermal status updated.
+ * Acquired via {@link AThermal_acquireManager}.
+ * @param callback The callback function to be called on system binder thread pool when thermal
+ * status updated.
* @param data The data pointer to be passed when callback is called.
*
* @return 0 on success
* EINVAL if the listener and data pointer were previously added and not removed.
- * EPERM if the required permission is not held.
- * EPIPE if communication with the system service has failed.
+ * EPIPE if communication with the system service has failed, the listener will not get
+ * removed and this call should be retried
*/
-int AThermal_registerThermalStatusListener(AThermalManager* _Nonnull manager,
+int AThermal_registerThermalStatusListener(AThermalManager *_Nonnull manager,
AThermal_StatusCallback _Nullable callback,
void* _Nullable data) __INTRODUCED_IN(30);
/**
- * Unregister the thermal status listener previously resgistered.
+ * Unregister a thermal status listener previously registered.
+ *
+ * No subsequent invocations of the callback will occur after this function returns successfully.
*
* Available since API level 30.
*
* @param manager The manager instance to use to unregister.
- * Acquired via {@link AThermal_acquireManager}.
- * @param callback The callback function to be called when thermal status updated.
+ * Acquired via {@link AThermal_acquireManager}.
+ * @param callback The callback function that was previously registered.
* @param data The data pointer to be passed when callback is called.
*
* @return 0 on success
* EINVAL if the listener and data pointer were not previously added.
- * EPERM if the required permission is not held.
* EPIPE if communication with the system service has failed.
*/
int AThermal_unregisterThermalStatusListener(AThermalManager* _Nonnull manager,
@@ -254,7 +256,7 @@
* The headroom threshold is used to interpret the possible thermal throttling status based on
* the headroom prediction. For example, if the headroom threshold for
* {@link ATHERMAL_STATUS_LIGHT} is 0.7, and a headroom prediction in 10s returns 0.75
- * (or {@code AThermal_getThermalHeadroom(10)=0.75}), one can expect that in 10 seconds the system
+ * (or `AThermal_getThermalHeadroom(10)=0.75}`, one can expect that in 10 seconds the system
* could be in lightly throttled state if the workload remains the same. The app can consider
* taking actions according to the nearest throttling status the difference between the headroom and
* the threshold.
@@ -262,24 +264,30 @@
* For new devices it's guaranteed to have a single sensor, but for older devices with multiple
* sensors reporting different threshold values, the minimum threshold is taken to be conservative
* on predictions. Thus, when reading real-time headroom, it's not guaranteed that a real-time value
- * of 0.75 (or {@code AThermal_getThermalHeadroom(0)}=0.75) exceeding the threshold of 0.7 above
+ * of 0.75 (or `AThermal_getThermalHeadroom(0)=0.75`) exceeding the threshold of 0.7 above
* will always come with lightly throttled state
- * (or {@code AThermal_getCurrentThermalStatus()=ATHERMAL_STATUS_LIGHT}) but it can be lower
- * (or {@code AThermal_getCurrentThermalStatus()=ATHERMAL_STATUS_NONE}).
+ * (or `AThermal_getCurrentThermalStatus()=ATHERMAL_STATUS_LIGHT`) but it can be lower
+ * (or `AThermal_getCurrentThermalStatus()=ATHERMAL_STATUS_NONE`).
* While it's always guaranteed that the device won't be throttled heavier than the unmet
* threshold's state, so a real-time headroom of 0.75 will never come with
* {@link #ATHERMAL_STATUS_MODERATE} but always lower, and 0.65 will never come with
* {@link ATHERMAL_STATUS_LIGHT} but {@link #ATHERMAL_STATUS_NONE}.
* <p>
- * The returned list of thresholds is cached on first successful query and owned by the thermal
- * manager, which will not change between calls to this function. The caller should only need to
- * free the manager with {@link AThermal_releaseManager}.
+ * Starting in Android 16, this polling API may return different results when called depending on
+ * the device. The new headroom listener API {@link #AThermal_HeadroomCallback} can be used to
+ * detect headroom thresholds changes.
+ * <p>
+ * Before API level 36 the returned list of thresholds is cached on first successful query and owned
+ * by the thermal manager, which will not change between calls to this function. The caller should
+ * only need to free the manager with {@link AThermal_releaseManager}.
+ * <p>
*
* @param manager The manager instance to use.
* Acquired via {@link AThermal_acquireManager}.
* @param outThresholds non-null output pointer to null AThermalHeadroomThreshold pointer, which
- * will be set to the cached array of thresholds if thermal thresholds are supported
- * by the system or device, otherwise nullptr or unmodified.
+ * will be set to a new array of thresholds if thermal thresholds are supported
+ * by the system or device, otherwise nullptr or unmodified. The client should
+ * clean up the thresholds by array-deleting the threshold pointer.
* @param size non-null output pointer whose value will be set to the size of the threshold array
* or 0 if it's not supported.
* @return 0 on success
@@ -292,6 +300,71 @@
* _Nullable outThresholds,
size_t* _Nonnull size) __INTRODUCED_IN(35);
+/**
+ * Prototype of the function that is called when thermal headroom or thresholds changes.
+ * It's passed the updated thermal headroom and thresholds as parameters, as well as the
+ * pointer provided by the client that registered a callback.
+ *
+ * @param data The data pointer to be passed when callback is called.
+ * @param headroom The current non-negative normalized headroom value, also see
+ * {@link AThermal_getThermalHeadroom}.
+ * @param forecastHeadroom The forecasted non-negative normalized headroom value, also see
+ * {@link AThermal_getThermalHeadroom}.
+ * @param forecastSeconds The seconds used for the forecast by the system.
+ * @param thresholds The current headroom thresholds. The thresholds pointer will be a constant
+ * shared across all callbacks registered from the same process, and it will be
+ * destroyed after all the callbacks are finished. If the client intents to
+ * persist the values, it should make a copy of it during the callback.
+ * @param thresholdsCount The count of thresholds.
+ */
+typedef void (*AThermal_HeadroomCallback)(void *_Nullable data,
+ float headroom,
+ float forecastHeadroom,
+ int forecastSeconds,
+ const AThermalHeadroomThreshold* _Nullable thresholds,
+ size_t thresholdsCount);
+
+/**
+ * Register a thermal headroom listener for thermal headroom or thresholds change.
+ *
+ * Available since API level 36.
+ *
+ * @param manager The manager instance to use to register.
+ * Acquired via {@link AThermal_acquireManager}.
+ * @param callback The callback function to be called on system binder thread pool when thermal
+ * headroom or thresholds update.
+ * @param data The data pointer to be passed when callback is called.
+ *
+ * @return 0 on success
+ * EINVAL if the listener and data pointer were previously added and not removed.
+ * EPIPE if communication with the system service has failed.
+ */
+int AThermal_registerThermalHeadroomListener(AThermalManager* _Nonnull manager,
+ AThermal_HeadroomCallback _Nullable callback,
+ void* _Nullable data) __INTRODUCED_IN(36);
+
+/**
+ * Unregister a thermal headroom listener previously registered.
+ *
+ * No subsequent invocations of the callback will occur after this function returns successfully.
+ *
+ * Available since API level 36.
+ *
+ * @param manager The manager instance to use to unregister.
+ * Acquired via {@link AThermal_acquireManager}.
+ * @param callback The callback function that was previously registered.
+ * @param data The data pointer that was previously registered.
+ *
+ * @return 0 on success
+ * EINVAL if the listener and data pointer were not previously added.
+ * EPIPE if communication with the system service has failed, the listener will not get
+ * removed and this call should be retried
+ */
+
+int AThermal_unregisterThermalHeadroomListener(AThermalManager* _Nonnull manager,
+ AThermal_HeadroomCallback _Nullable callback,
+ void* _Nullable data) __INTRODUCED_IN(36);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/audiomanager/AudioManager.h b/include/audiomanager/AudioManager.h
index 917d9a7..203623d 100644
--- a/include/audiomanager/AudioManager.h
+++ b/include/audiomanager/AudioManager.h
@@ -22,6 +22,7 @@
// must be kept in sync with definitions in AudioPlaybackConfiguration.java
#define PLAYER_PIID_INVALID -1
+// TODO (b/309532236) remove manual IAudioManager impl in favor of AIDL.
typedef enum {
PLAYER_TYPE_SLES_AUDIOPLAYER_BUFFERQUEUE = 11,
PLAYER_TYPE_SLES_AUDIOPLAYER_URI_FD = 12,
@@ -60,6 +61,7 @@
PLAYER_MUTE_CLIENT_VOLUME = (1 << 4),
PLAYER_MUTE_VOLUME_SHAPER = (1 << 5),
PLAYER_MUTE_PORT_VOLUME = (1 << 6),
+ PLAYER_MUTE_OP_AUDIO_CONTROL = (1 << 7),
};
struct mute_state_t {
@@ -77,6 +79,8 @@
bool muteFromVolumeShaper = false;
/** Flag used when volume is muted by port volume. */
bool muteFromPortVolume = false;
+ /** Flag used when volume is muted by audio control op. */
+ bool muteFromOpAudioControl = false;
explicit operator int() const
{
@@ -87,6 +91,7 @@
result |= muteFromClientVolume * PLAYER_MUTE_CLIENT_VOLUME;
result |= muteFromVolumeShaper * PLAYER_MUTE_VOLUME_SHAPER;
result |= muteFromPortVolume * PLAYER_MUTE_PORT_VOLUME;
+ result |= muteFromOpAudioControl * PLAYER_MUTE_OP_AUDIO_CONTROL;
return result;
}
diff --git a/include/audiomanager/IAudioManager.h b/include/audiomanager/IAudioManager.h
index 0b7e16b..b0641b8 100644
--- a/include/audiomanager/IAudioManager.h
+++ b/include/audiomanager/IAudioManager.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_IAUDIOMANAGER_H
#define ANDROID_IAUDIOMANAGER_H
+#include <android/media/IAudioManagerNative.h>
#include <audiomanager/AudioManager.h>
#include <utils/Errors.h>
#include <binder/IInterface.h>
@@ -34,20 +35,23 @@
// These transaction IDs must be kept in sync with the method order from
// IAudioService.aidl.
enum {
- TRACK_PLAYER = IBinder::FIRST_CALL_TRANSACTION,
- PLAYER_ATTRIBUTES = IBinder::FIRST_CALL_TRANSACTION + 1,
- PLAYER_EVENT = IBinder::FIRST_CALL_TRANSACTION + 2,
- RELEASE_PLAYER = IBinder::FIRST_CALL_TRANSACTION + 3,
- TRACK_RECORDER = IBinder::FIRST_CALL_TRANSACTION + 4,
- RECORDER_EVENT = IBinder::FIRST_CALL_TRANSACTION + 5,
- RELEASE_RECORDER = IBinder::FIRST_CALL_TRANSACTION + 6,
- PLAYER_SESSION_ID = IBinder::FIRST_CALL_TRANSACTION + 7,
- PORT_EVENT = IBinder::FIRST_CALL_TRANSACTION + 8,
- PERMISSION_UPDATE_BARRIER = IBinder::FIRST_CALL_TRANSACTION + 9,
+ GET_NATIVE_INTERFACE = IBinder::FIRST_CALL_TRANSACTION,
+ TRACK_PLAYER = IBinder::FIRST_CALL_TRANSACTION + 1,
+ PLAYER_ATTRIBUTES = IBinder::FIRST_CALL_TRANSACTION + 2,
+ PLAYER_EVENT = IBinder::FIRST_CALL_TRANSACTION + 3,
+ RELEASE_PLAYER = IBinder::FIRST_CALL_TRANSACTION + 4,
+ TRACK_RECORDER = IBinder::FIRST_CALL_TRANSACTION + 5,
+ RECORDER_EVENT = IBinder::FIRST_CALL_TRANSACTION + 6,
+ RELEASE_RECORDER = IBinder::FIRST_CALL_TRANSACTION + 7,
+ PLAYER_SESSION_ID = IBinder::FIRST_CALL_TRANSACTION + 8,
+ PORT_EVENT = IBinder::FIRST_CALL_TRANSACTION + 9,
+ PERMISSION_UPDATE_BARRIER = IBinder::FIRST_CALL_TRANSACTION + 10,
};
DECLARE_META_INTERFACE(AudioManager)
+ virtual sp<media::IAudioManagerNative> getNativeInterface() = 0;
+
// The parcels created by these methods must be kept in sync with the
// corresponding methods from IAudioService.aidl and objects it imports.
virtual audio_unique_id_t trackPlayer(player_type_t playerType, audio_usage_t usage,
@@ -56,7 +60,7 @@
/*oneway*/ virtual status_t playerAttributes(audio_unique_id_t piid, audio_usage_t usage,
audio_content_type_t content)= 0;
/*oneway*/ virtual status_t playerEvent(audio_unique_id_t piid, player_state_t event,
- audio_port_handle_t eventId) = 0;
+ const std::vector<audio_port_handle_t>& eventIds) = 0;
/*oneway*/ virtual status_t releasePlayer(audio_unique_id_t piid) = 0;
virtual audio_unique_id_t trackRecorder(const sp<IBinder>& recorder) = 0;
/*oneway*/ virtual status_t recorderEvent(audio_unique_id_t riid, recorder_state_t event) = 0;
diff --git a/include/audiomanager/OWNERS b/include/audiomanager/OWNERS
index 2bd527c..58257ba 100644
--- a/include/audiomanager/OWNERS
+++ b/include/audiomanager/OWNERS
@@ -1,2 +1,3 @@
+atneya@google.com
elaurent@google.com
jmtrivi@google.com
diff --git a/include/ftl/finalizer.h b/include/ftl/finalizer.h
new file mode 100644
index 0000000..0251957
--- /dev/null
+++ b/include/ftl/finalizer.h
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2024 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 <cstddef>
+
+#include <functional>
+#include <type_traits>
+#include <utility>
+
+#include <ftl/function.h>
+
+namespace android::ftl {
+
+// An RAII wrapper that invokes a function object as a finalizer when destroyed.
+//
+// The function object must take no arguments, and must return void. If the function object needs
+// any context for the call, it must store it itself, for example with a lambda capture.
+//
+// The stored function object will be called once (unless canceled via the `cancel()` member
+// function) at the first of:
+//
+// - The Finalizer instance is destroyed.
+// - `operator()` is used to invoke the contained function.
+// - The Finalizer instance is move-assigned a new value. The function being replaced will be
+// invoked, and the replacement will be stored to be called later.
+//
+// The intent with this class is to keep cleanup code next to the code that requires that
+// cleanup be performed.
+//
+// bool read_file(std::string filename) {
+// FILE* f = fopen(filename.c_str(), "rb");
+// if (f == nullptr) return false;
+// const auto cleanup = ftl::Finalizer([f]() { fclose(f); });
+// // fread(...), etc
+// return true;
+// }
+//
+// The `FinalFunction` template argument to Finalizer<FinalFunction> allows a polymorphic function
+// type for storing the finalization function, such as `std::function` or `ftl::Function`.
+//
+// For convenience, this header defines a few useful aliases for using those types.
+//
+// - `FinalizerStd`, an alias for `Finalizer<std::function<void()>>`
+// - `FinalizerFtl`, an alias for `Finalizer<ftl::Function<void()>>`
+// - `FinalizerFtl1`, an alias for `Finalizer<ftl::Function<void(), 1>>`
+// - `FinalizerFtl2`, an alias for `Finalizer<ftl::Function<void(), 2>>`
+// - `FinalizerFtl3`, an alias for `Finalizer<ftl::Function<void(), 3>>`
+//
+// Clients of this header are free to define other aliases they need.
+//
+// A Finalizer that uses a polymorphic function type can be returned from a function call and/or
+// stored as member data (to be destroyed along with the containing class).
+//
+// auto register(Observer* observer) -> ftl::FinalizerStd<void()> {
+// const auto id = observers.add(observer);
+// return ftl::Finalizer([id]() { observers.remove(id); });
+// }
+//
+// {
+// const auto _ = register(observer);
+// // do the things that required the registered observer.
+// }
+// // the observer is removed.
+//
+// Cautions:
+//
+// 1. When a Finalizer is stored as member data, you will almost certainly want that cleanup to
+// happen first, before the rest of the other member data is destroyed. For safety you should
+// assume that the finalization function will access that data directly or indirectly.
+//
+// This means that Finalizers should be defined last, after all other normal member data in a
+// class.
+//
+// class MyClass {
+// public:
+// bool initialize() {
+// ready_ = true;
+// cleanup_ = ftl::Finalizer([this]() { ready_ = false; });
+// return true;
+// }
+//
+// bool ready_ = false;
+//
+// // Finalizers should be last so other class members can be accessed before being
+// // destroyed.
+// ftl::FinalizerStd<void()> cleanup_;
+// };
+//
+// 2. Care must be taken to use `ftl::Finalizer()` when constructing locally from a lambda. If you
+// forget to do so, you are just creating a lambda that won't be automatically invoked!
+//
+// const auto bad = [&counter](){ ++counter; }; // Just a lambda instance
+// const auto good = ftl::Finalizer([&counter](){ ++counter; });
+//
+template <typename FinalFunction>
+class Finalizer final {
+ // requires(std::is_invocable_r_v<void, FinalFunction>)
+ static_assert(std::is_invocable_r_v<void, FinalFunction>);
+
+ public:
+ // A default constructed Finalizer does nothing when destroyed.
+ // requires(std::is_default_constructible_v<FinalFunction>)
+ constexpr Finalizer() = default;
+
+ // Constructs a Finalizer from a function object.
+ // requires(std::is_invocable_v<F>)
+ template <typename F, typename = std::enable_if_t<std::is_invocable_v<F>>>
+ [[nodiscard]] explicit constexpr Finalizer(F&& function)
+ : Finalizer(std::forward<F>(function), false) {}
+
+ constexpr ~Finalizer() { maybe_invoke(); }
+
+ // Disallow copying.
+ Finalizer(const Finalizer& that) = delete;
+ auto operator=(const Finalizer& that) = delete;
+
+ // Move construction
+ // requires(std::is_move_constructible_v<FinalFunction>)
+ [[nodiscard]] constexpr Finalizer(Finalizer&& that)
+ : Finalizer(std::move(that.function_), std::exchange(that.canceled_, true)) {}
+
+ // Implicit conversion move construction
+ // requires(!std::is_same_v<Finalizer, Finalizer<F>>)
+ template <typename F, typename = std::enable_if_t<!std::is_same_v<Finalizer, Finalizer<F>>>>
+ // NOLINTNEXTLINE(google-explicit-constructor, cppcoreguidelines-rvalue-reference-param-not-moved)
+ [[nodiscard]] constexpr Finalizer(Finalizer<F>&& that)
+ : Finalizer(std::move(that.function_), std::exchange(that.canceled_, true)) {}
+
+ // Move assignment
+ // requires(std::is_move_assignable_v<FinalFunction>)
+ constexpr auto operator=(Finalizer&& that) -> Finalizer& {
+ maybe_invoke();
+
+ function_ = std::move(that.function_);
+ canceled_ = std::exchange(that.canceled_, true);
+
+ return *this;
+ }
+
+ // Implicit conversion move assignment
+ // requires(!std::is_same_v<Finalizer, Finalizer<F>>)
+ template <typename F, typename = std::enable_if_t<!std::is_same_v<Finalizer, Finalizer<F>>>>
+ // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
+ constexpr auto operator=(Finalizer<F>&& that) -> Finalizer& {
+ *this = Finalizer(std::move(that.function_), std::exchange(that.canceled_, true));
+ return *this;
+ }
+
+ // Cancels the final function, preventing it from being invoked.
+ constexpr void cancel() {
+ canceled_ = true;
+ maybe_nullify_function();
+ }
+
+ // Invokes the final function now, if not already invoked.
+ constexpr void operator()() { maybe_invoke(); }
+
+ private:
+ template <typename>
+ friend class Finalizer;
+
+ template <typename F, typename = std::enable_if_t<std::is_invocable_v<F>>>
+ [[nodiscard]] explicit constexpr Finalizer(F&& function, bool canceled)
+ : function_(std::forward<F>(function)), canceled_(canceled) {}
+
+ constexpr void maybe_invoke() {
+ if (!std::exchange(canceled_, true)) {
+ std::invoke(function_);
+ maybe_nullify_function();
+ }
+ }
+
+ constexpr void maybe_nullify_function() {
+ // Sets function_ to nullptr if that is supported for the backing type.
+ if constexpr (std::is_assignable_v<FinalFunction, nullptr_t>) {
+ function_ = nullptr;
+ }
+ }
+
+ FinalFunction function_;
+ bool canceled_ = true;
+};
+
+template <typename F>
+Finalizer(F&&) -> Finalizer<std::decay_t<F>>;
+
+// A standard alias for using `std::function` as the polymorphic function type.
+using FinalizerStd = Finalizer<std::function<void()>>;
+
+// Helpful aliases for using `ftl::Function` as the polymorphic function type.
+using FinalizerFtl = Finalizer<Function<void()>>;
+using FinalizerFtl1 = Finalizer<Function<void(), 1>>;
+using FinalizerFtl2 = Finalizer<Function<void(), 2>>;
+using FinalizerFtl3 = Finalizer<Function<void(), 3>>;
+
+} // namespace android::ftl
\ No newline at end of file
diff --git a/include/ftl/flags.h b/include/ftl/flags.h
index dbe3148..a2a22eb 100644
--- a/include/ftl/flags.h
+++ b/include/ftl/flags.h
@@ -22,6 +22,7 @@
#include <bitset>
#include <cstdint>
#include <iterator>
+#include <initializer_list>
#include <string>
#include <type_traits>
@@ -40,6 +41,7 @@
public:
constexpr Flags(F f) : mFlags(static_cast<U>(f)) {}
+ constexpr Flags(std::initializer_list<F> fs) : mFlags(combine(fs)) {}
constexpr Flags() : mFlags(0) {}
constexpr Flags(const Flags<F>& f) : mFlags(f.mFlags) {}
@@ -197,6 +199,14 @@
private:
U mFlags;
+ static constexpr U combine(std::initializer_list<F> fs) {
+ U result = 0;
+ for (const F f : fs) {
+ result |= static_cast<U>(f);
+ }
+ return result;
+ }
+
static void appendFlag(std::string& str, const std::string_view& flag, bool& first) {
if (first) {
first = false;
diff --git a/include/ftl/ignore.h b/include/ftl/ignore.h
new file mode 100644
index 0000000..1468fa2
--- /dev/null
+++ b/include/ftl/ignore.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2025 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
+
+namespace android::ftl {
+
+// An alternative to `std::ignore` that makes it easy to ignore multiple values.
+//
+// Examples:
+//
+// void ftl_ignore_multiple(int arg1, const char* arg2, std::string arg3) {
+// // When invoked, all the arguments are ignored.
+// ftl::ignore(arg1, arg2, arg3);
+// }
+//
+// void ftl_ignore_single(int arg) {
+// // It can be used like std::ignore to ignore a single value
+// ftl::ignore = arg;
+// }
+//
+inline constexpr struct {
+ // NOLINTNEXTLINE(misc-unconventional-assign-operator, readability-named-parameter)
+ constexpr auto operator=(auto&&) const -> decltype(*this) { return *this; }
+ // NOLINTNEXTLINE(readability-named-parameter)
+ constexpr void operator()(auto&&...) const {}
+} ignore;
+
+} // namespace android::ftl
\ No newline at end of file
diff --git a/include/ftl/small_map.h b/include/ftl/small_map.h
index 83d5967..96d35cd 100644
--- a/include/ftl/small_map.h
+++ b/include/ftl/small_map.h
@@ -234,6 +234,12 @@
//
bool erase(const key_type& key) { return erase(key, begin()); }
+ // Removes a mapping.
+ //
+ // The last() and end() iterators, as well as those to the erased mapping, are invalidated.
+ //
+ void erase(iterator it) { map_.unstable_erase(it); }
+
// Removes all mappings.
//
// All iterators are invalidated.
diff --git a/include/input/AccelerationCurve.h b/include/input/AccelerationCurve.h
index 0cf648a..8a4a5d4 100644
--- a/include/input/AccelerationCurve.h
+++ b/include/input/AccelerationCurve.h
@@ -46,4 +46,15 @@
std::vector<AccelerationCurveSegment> createAccelerationCurveForPointerSensitivity(
int32_t sensitivity);
+/*
+ * Creates a flat acceleration curve for disabling pointer acceleration.
+ *
+ * This method generates a single AccelerationCurveSegment with specific values
+ * to effectively disable acceleration for both mice and touchpads.
+ * A flat acceleration curve ensures a constant gain, meaning that the output
+ * velocity is directly proportional to the input velocity, resulting in
+ * a 1:1 movement ratio between the input device and the on-screen pointer.
+ */
+std::vector<AccelerationCurveSegment> createFlatAccelerationCurve(int32_t sensitivity);
+
} // namespace android
diff --git a/include/input/BlockingQueue.h b/include/input/BlockingQueue.h
index f848c82..6e32de6 100644
--- a/include/input/BlockingQueue.h
+++ b/include/input/BlockingQueue.h
@@ -16,6 +16,7 @@
#pragma once
+#include <input/PrintTools.h>
#include <condition_variable>
#include <functional>
#include <list>
@@ -126,11 +127,21 @@
* Primary used for debugging.
* Does not block.
*/
- size_t size() {
+ size_t size() const {
std::scoped_lock lock(mLock);
return mQueue.size();
}
+ bool empty() const {
+ std::scoped_lock lock(mLock);
+ return mQueue.empty();
+ }
+
+ std::string dump(std::string (*toString)(const T&) = constToString) const {
+ std::scoped_lock lock(mLock);
+ return dumpContainer(mQueue, toString);
+ }
+
private:
const std::optional<size_t> mCapacity;
/**
@@ -140,7 +151,7 @@
/**
* Lock for accessing and waiting on elements.
*/
- std::mutex mLock;
+ mutable std::mutex mLock;
std::list<T> mQueue GUARDED_BY(mLock);
};
diff --git a/include/input/CoordinateFilter.h b/include/input/CoordinateFilter.h
new file mode 100644
index 0000000..8f2e605
--- /dev/null
+++ b/include/input/CoordinateFilter.h
@@ -0,0 +1,54 @@
+/**
+ * Copyright 2024 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 <chrono>
+
+#include <input/Input.h>
+#include <input/OneEuroFilter.h>
+
+namespace android {
+
+/**
+ * Pair of OneEuroFilters that independently filter X and Y coordinates. Both filters share the same
+ * constructor's parameters. The minimum cutoff frequency is the base cutoff frequency, that is, the
+ * resulting cutoff frequency in the absence of signal's speed. Likewise, beta is a scaling factor
+ * of the signal's speed that sets how much the signal's speed contributes to the resulting cutoff
+ * frequency. The adaptive cutoff frequency criterion is f_c = f_c_min + β|̇x_filtered|
+ */
+class CoordinateFilter {
+public:
+ explicit CoordinateFilter(float minCutoffFreq, float beta);
+
+ /**
+ * Filters in place only the AXIS_X and AXIS_Y fields from coords. Each call to filter must
+ * provide a timestamp strictly greater than the timestamp of the previous call. The first time
+ * this method is invoked no filtering takes place. Subsequent calls do overwrite `coords` with
+ * filtered data.
+ *
+ * @param timestamp The timestamps at which to filter. It must be greater than the one passed in
+ * the previous call.
+ * @param coords Coordinates to be overwritten by the corresponding filtered coordinates.
+ */
+ void filter(std::chrono::nanoseconds timestamp, PointerCoords& coords);
+
+private:
+ OneEuroFilter mXFilter;
+ OneEuroFilter mYFilter;
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/include/input/DisplayTopologyGraph.h b/include/input/DisplayTopologyGraph.h
new file mode 100644
index 0000000..3ae865a
--- /dev/null
+++ b/include/input/DisplayTopologyGraph.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2024 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 <ftl/enum.h>
+#include <ui/LogicalDisplayId.h>
+
+#include <cinttypes>
+#include <unordered_map>
+#include <vector>
+
+namespace android {
+
+/**
+ * The edge of the current display, where adjacent display is attached to.
+ */
+enum class DisplayTopologyPosition : int32_t {
+ LEFT = 0,
+ TOP = 1,
+ RIGHT = 2,
+ BOTTOM = 3,
+
+ ftl_last = BOTTOM
+};
+
+/**
+ * Directed edge in the graph of adjacent displays.
+ */
+struct DisplayTopologyAdjacentDisplay {
+ ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID;
+ // Position of the adjacent display, relative to the source display.
+ DisplayTopologyPosition position;
+ // The offset in DP of the adjacent display, relative to the source display.
+ float offsetDp;
+};
+
+/**
+ * Directed Graph representation of Display Topology.
+ */
+struct DisplayTopologyGraph {
+ ui::LogicalDisplayId primaryDisplayId = ui::LogicalDisplayId::INVALID;
+ std::unordered_map<ui::LogicalDisplayId, std::vector<DisplayTopologyAdjacentDisplay>> graph;
+ std::unordered_map<ui::LogicalDisplayId, int> displaysDensity;
+};
+
+} // namespace android
diff --git a/include/input/Input.h b/include/input/Input.h
index a8684bd..002b3a7 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -92,11 +92,23 @@
static_cast<int32_t>(android::os::MotionEventFlag::NO_FOCUS_CHANGE),
/**
- * This event was generated or modified by accessibility service.
+ * This event was injected from some AccessibilityService, which may be either an
+ * Accessibility Tool OR a service using that API for purposes other than assisting users
+ * with disabilities.
*/
AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT =
static_cast<int32_t>(android::os::MotionEventFlag::IS_ACCESSIBILITY_EVENT),
+ /**
+ * This event was injected from an AccessibilityService with the
+ * AccessibilityServiceInfo#isAccessibilityTool property set to true. These services (known as
+ * "Accessibility Tools") are used to assist users with disabilities, so events from these
+ * services should be able to reach all Views including Views which set
+ * View#isAccessibilityDataSensitive to true.
+ */
+ AMOTION_EVENT_FLAG_INJECTED_FROM_ACCESSIBILITY_TOOL =
+ static_cast<int32_t>(android::os::MotionEventFlag::INJECTED_FROM_ACCESSIBILITY_TOOL),
+
AMOTION_EVENT_FLAG_TARGET_ACCESSIBILITY_FOCUS =
static_cast<int32_t>(android::os::MotionEventFlag::TARGET_ACCESSIBILITY_FOCUS),
@@ -294,6 +306,8 @@
NONE = AINPUT_KEYBOARD_TYPE_NONE,
NON_ALPHABETIC = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC,
ALPHABETIC = AINPUT_KEYBOARD_TYPE_ALPHABETIC,
+ ftl_first = NONE,
+ ftl_last = ALPHABETIC,
};
bool isStylusToolType(ToolType toolType);
@@ -302,6 +316,19 @@
bool isStylusEvent(uint32_t source, const std::vector<PointerProperties>& properties);
+bool isStylusHoverEvent(uint32_t source, const std::vector<PointerProperties>& properties,
+ int32_t action);
+
+bool isFromMouse(uint32_t source, ToolType tooltype);
+
+bool isFromTouchpad(uint32_t source, ToolType tooltype);
+
+bool isFromDrawingTablet(uint32_t source, ToolType tooltype);
+
+bool isHoverAction(int32_t action);
+
+bool isMouseOrTouchpad(uint32_t sources);
+
/*
* Flags that flow alongside events in the input dispatch system to help with certain
* policy decisions such as waking from device sleep.
@@ -345,6 +372,9 @@
POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY =
android::os::IInputConstants::POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
+ POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY_TOOL =
+ android::os::IInputConstants::POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY_TOOL,
+
/* These flags are set by the input dispatcher. */
// Indicates that the input event was injected.
@@ -994,6 +1024,15 @@
std::vector<PointerProperties> mPointerProperties;
std::vector<nsecs_t> mSampleEventTimes;
std::vector<PointerCoords> mSamplePointerCoords;
+
+private:
+ /**
+ * Create a human-readable string representation of the event's data for debugging purposes.
+ *
+ * Unlike operator<<, this method does not assume that the event data is valid or consistent, or
+ * call any accessor methods that might themselves call safeDump in the case of invalid data.
+ */
+ std::string safeDump() const;
};
std::ostream& operator<<(std::ostream& out, const MotionEvent& event);
diff --git a/include/input/InputConsumerNoResampling.h b/include/input/InputConsumerNoResampling.h
index 228347d..70d00d1 100644
--- a/include/input/InputConsumerNoResampling.h
+++ b/include/input/InputConsumerNoResampling.h
@@ -141,7 +141,7 @@
}
private:
- std::function<int(int events)> mCallback;
+ const std::function<int(int events)> mCallback;
};
sp<LooperEventCallback> mCallback;
/**
@@ -211,16 +211,17 @@
* `consumeBatchedInputEvents`.
*/
std::map<DeviceId, std::queue<InputMessage>> mBatches;
+
/**
- * Creates a MotionEvent by consuming samples from the provided queue. If one message has
- * eventTime > adjustedFrameTime, all subsequent messages in the queue will be skipped. It is
- * assumed that messages are queued in chronological order. In other words, only events that
- * occurred prior to the adjustedFrameTime will be consumed.
- * @param requestedFrameTime the time up to which to consume events.
- * @param messages the queue of messages to consume from
+ * Creates a MotionEvent by consuming samples from the provided queue. Consumes all messages
+ * with eventTime <= requestedFrameTime - resampleLatency, where `resampleLatency` is latency
+ * introduced by the resampler. Assumes that messages are queued in chronological order.
+ * @param requestedFrameTime The time up to which consume messages, as given by the inequality
+ * above. If std::nullopt, everything in messages will be consumed.
+ * @param messages the queue of messages to consume from.
*/
std::pair<std::unique_ptr<MotionEvent>, std::optional<uint32_t>> createBatchedMotionEvent(
- const nsecs_t requestedFrameTime, std::queue<InputMessage>& messages);
+ const std::optional<nsecs_t> requestedFrameTime, std::queue<InputMessage>& messages);
/**
* Consumes the batched input events, optionally allowing the caller to specify a device id
diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h
index 1a48239..ea1e4ae 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -111,12 +111,12 @@
};
enum class InputDeviceSensorAccuracy : int32_t {
- ACCURACY_NONE = 0,
- ACCURACY_LOW = 1,
- ACCURACY_MEDIUM = 2,
- ACCURACY_HIGH = 3,
+ NONE = 0,
+ LOW = 1,
+ MEDIUM = 2,
+ HIGH = 3,
- ftl_last = ACCURACY_HIGH,
+ ftl_last = HIGH,
};
enum class InputDeviceSensorReportingMode : int32_t {
@@ -131,8 +131,9 @@
PLAYER_ID = 1,
KEYBOARD_BACKLIGHT = 2,
KEYBOARD_MIC_MUTE = 3,
+ KEYBOARD_VOLUME_MUTE = 4,
- ftl_last = KEYBOARD_MIC_MUTE
+ ftl_last = KEYBOARD_VOLUME_MUTE
};
enum class InputDeviceLightCapability : uint32_t {
@@ -266,6 +267,7 @@
public:
InputDeviceInfo();
InputDeviceInfo(const InputDeviceInfo& other);
+ InputDeviceInfo& operator=(const InputDeviceInfo& other);
~InputDeviceInfo();
struct MotionRange {
@@ -315,13 +317,11 @@
inline const InputDeviceViewBehavior& getViewBehavior() const { return mViewBehavior; }
- inline void setKeyCharacterMap(const std::shared_ptr<KeyCharacterMap> value) {
- mKeyCharacterMap = value;
+ inline void setKeyCharacterMap(std::unique_ptr<KeyCharacterMap> value) {
+ mKeyCharacterMap = std::move(value);
}
- inline const std::shared_ptr<KeyCharacterMap> getKeyCharacterMap() const {
- return mKeyCharacterMap;
- }
+ inline const KeyCharacterMap* getKeyCharacterMap() const { return mKeyCharacterMap.get(); }
inline void setVibrator(bool hasVibrator) { mHasVibrator = hasVibrator; }
inline bool hasVibrator() const { return mHasVibrator; }
@@ -364,7 +364,7 @@
std::optional<KeyboardLayoutInfo> mKeyboardLayoutInfo;
uint32_t mSources;
int32_t mKeyboardType;
- std::shared_ptr<KeyCharacterMap> mKeyCharacterMap;
+ std::unique_ptr<KeyCharacterMap> mKeyCharacterMap;
std::optional<InputDeviceUsiVersion> mUsiVersion;
ui::LogicalDisplayId mAssociatedDisplayId{ui::LogicalDisplayId::INVALID};
bool mEnabled;
diff --git a/include/input/InputFlags.h b/include/input/InputFlags.h
new file mode 100644
index 0000000..4b42f77
--- /dev/null
+++ b/include/input/InputFlags.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2025 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
+
+namespace android {
+
+class InputFlags {
+public:
+ /**
+ * Check if connected displays feature is enabled, either via the feature flag or settings
+ * override.
+ */
+ static bool connectedDisplaysCursorEnabled();
+
+ /**
+ * Check if both connectedDisplaysCursor and associatedDisplayCursorBugfix is enabled.
+ */
+ static bool connectedDisplaysCursorAndAssociatedDisplayCursorBugfixEnabled();
+};
+
+} // namespace android
diff --git a/include/input/InputVerifier.h b/include/input/InputVerifier.h
index 14dd463..7d3fb46 100644
--- a/include/input/InputVerifier.h
+++ b/include/input/InputVerifier.h
@@ -47,9 +47,10 @@
InputVerifier(const std::string& name);
android::base::Result<void> processMovement(int32_t deviceId, int32_t source, int32_t action,
- uint32_t pointerCount,
+ int32_t actionButton, uint32_t pointerCount,
const PointerProperties* pointerProperties,
- const PointerCoords* pointerCoords, int32_t flags);
+ const PointerCoords* pointerCoords, int32_t flags,
+ int32_t buttonState);
void resetDevice(int32_t deviceId);
diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h
index 7ea34c2..0a9e74f 100644
--- a/include/input/KeyCharacterMap.h
+++ b/include/input/KeyCharacterMap.h
@@ -72,7 +72,7 @@
};
/* Loads a key character map from a file. */
- static base::Result<std::shared_ptr<KeyCharacterMap>> load(const std::string& filename,
+ static base::Result<std::unique_ptr<KeyCharacterMap>> load(const std::string& filename,
Format format);
/* Loads a key character map from its string contents. */
diff --git a/include/input/OneEuroFilter.h b/include/input/OneEuroFilter.h
new file mode 100644
index 0000000..bdd82b2
--- /dev/null
+++ b/include/input/OneEuroFilter.h
@@ -0,0 +1,101 @@
+/**
+ * Copyright 2024 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 <chrono>
+#include <optional>
+
+#include <input/Input.h>
+
+namespace android {
+
+/**
+ * Low pass filter with adaptive low pass frequency based on the signal's speed. The signal's cutoff
+ * frequency is determined by f_c = f_c_min + β|̇x_filtered|. Refer to
+ * https://dl.acm.org/doi/10.1145/2207676.2208639 for details on how the filter works and how to
+ * tune it.
+ */
+class OneEuroFilter {
+public:
+ /**
+ * Default cutoff frequency of the filtered signal's speed. 1.0 Hz is the value in the filter's
+ * paper.
+ */
+ static constexpr float kDefaultSpeedCutoffFreq = 1.0;
+
+ OneEuroFilter() = delete;
+
+ explicit OneEuroFilter(float minCutoffFreq, float beta,
+ float speedCutoffFreq = kDefaultSpeedCutoffFreq);
+
+ OneEuroFilter(const OneEuroFilter&) = delete;
+ OneEuroFilter& operator=(const OneEuroFilter&) = delete;
+ OneEuroFilter(OneEuroFilter&&) = delete;
+ OneEuroFilter& operator=(OneEuroFilter&&) = delete;
+
+ /**
+ * Returns the filtered value of rawPosition. Each call to filter must provide a timestamp
+ * strictly greater than the timestamp of the previous call. The first time the method is
+ * called, it returns the value of rawPosition. Any subsequent calls provide a filtered value.
+ *
+ * @param timestamp The timestamp at which to filter. It must be strictly greater than the one
+ * provided in the previous call.
+ * @param rawPosition Position to be filtered.
+ */
+ float filter(std::chrono::nanoseconds timestamp, float rawPosition);
+
+private:
+ /**
+ * Minimum cutoff frequency. This is the constant term in the adaptive cutoff frequency
+ * criterion. Units are Hertz.
+ */
+ const float mMinCutoffFreq;
+
+ /**
+ * Slope of the cutoff frequency criterion. This is the term scaling the absolute value of the
+ * filtered signal's speed. Units are 1 / position.
+ */
+ const float mBeta;
+
+ /**
+ * Cutoff frequency of the signal's speed. This is the cutoff frequency applied to the filtering
+ * of the signal's speed. Units are Hertz.
+ */
+ const float mSpeedCutoffFreq;
+
+ /**
+ * The timestamp from the previous call.
+ */
+ std::optional<std::chrono::nanoseconds> mPrevTimestamp;
+
+ /**
+ * The raw position from the previous call.
+ */
+ std::optional<float> mPrevRawPosition;
+
+ /**
+ * The filtered velocity from the previous call. Units are position per nanosecond.
+ */
+ std::optional<float> mPrevFilteredVelocity;
+
+ /**
+ * The filtered position from the previous call.
+ */
+ std::optional<float> mPrevFilteredPosition;
+};
+
+} // namespace android
diff --git a/include/input/PrintTools.h b/include/input/PrintTools.h
index 3470be4..71c215f 100644
--- a/include/input/PrintTools.h
+++ b/include/input/PrintTools.h
@@ -19,13 +19,18 @@
#include <bitset>
#include <map>
#include <optional>
-#include <set>
+#include <ranges>
#include <sstream>
#include <string>
#include <vector>
namespace android {
+namespace internal {
+template <typename T>
+concept Container = std::ranges::range<T>;
+}
+
template <size_t N>
std::string bitsetToString(const std::bitset<N>& bitset) {
if (bitset.none()) {
@@ -72,10 +77,12 @@
/**
* Convert a set of integral types to string.
*/
-template <typename T>
-std::string dumpSet(const std::set<T>& v, std::string (*toString)(const T&) = constToString) {
+template <internal::Container T>
+std::string dumpContainer(
+ const T& container,
+ std::string (*toString)(const std::ranges::range_value_t<T>&) = constToString) {
std::string out;
- for (const T& entry : v) {
+ for (const auto& entry : container) {
out += out.empty() ? "{" : ", ";
out += toString(entry);
}
diff --git a/include/input/Resampler.h b/include/input/Resampler.h
index 47519c2..1550977 100644
--- a/include/input/Resampler.h
+++ b/include/input/Resampler.h
@@ -16,10 +16,16 @@
#pragma once
+#include <array>
#include <chrono>
+#include <iterator>
+#include <map>
#include <optional>
#include <vector>
+#include <android-base/logging.h>
+#include <ftl/mixins.h>
+#include <input/CoordinateFilter.h>
#include <input/Input.h>
#include <input/InputTransport.h>
#include <input/RingBuffer.h>
@@ -79,13 +85,127 @@
PointerCoords coords;
};
+ /**
+ * Container that stores pointers as an associative array, supporting O(1) lookup by pointer id,
+ * as well as forward iteration in the order in which the pointer or pointers were inserted in
+ * the container. PointerMap has a maximum capacity equal to MAX_POINTERS.
+ */
+ class PointerMap {
+ public:
+ struct PointerId : ftl::DefaultConstructible<PointerId, int32_t>,
+ ftl::Equatable<PointerId> {
+ using DefaultConstructible::DefaultConstructible;
+ };
+
+ /**
+ * Custom iterator to enable use of range-based for loops.
+ */
+ template <typename T>
+ class iterator {
+ public:
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = T;
+ using difference_type = std::ptrdiff_t;
+ using pointer = T*;
+ using reference = T&;
+
+ explicit iterator(pointer element) : mElement{element} {}
+
+ friend bool operator==(const iterator& lhs, const iterator& rhs) {
+ return lhs.mElement == rhs.mElement;
+ }
+
+ friend bool operator!=(const iterator& lhs, const iterator& rhs) {
+ return !(lhs == rhs);
+ }
+
+ iterator operator++() {
+ ++mElement;
+ return *this;
+ }
+
+ reference operator*() const { return *mElement; }
+
+ private:
+ pointer mElement;
+ };
+
+ PointerMap() {
+ idToIndex.fill(std::nullopt);
+ for (Pointer& pointer : pointers) {
+ pointer.properties.clear();
+ pointer.coords.clear();
+ }
+ }
+
+ /**
+ * Forward iterators to traverse the pointers in `pointers`. The order of the pointers is
+ * determined by the order in which they were inserted (not by id).
+ */
+ iterator<Pointer> begin() { return iterator<Pointer>{&pointers[0]}; }
+
+ iterator<const Pointer> begin() const { return iterator<const Pointer>{&pointers[0]}; }
+
+ iterator<Pointer> end() { return iterator<Pointer>{&pointers[nextPointerIndex]}; }
+
+ iterator<const Pointer> end() const {
+ return iterator<const Pointer>{&pointers[nextPointerIndex]};
+ }
+
+ /**
+ * Inserts the given pointer into the PointerMap. Precondition: The current number of
+ * contained pointers must be less than MAX_POINTERS when this function is called. It
+ * fatally logs if the user tries to insert more than MAX_POINTERS, or if pointer id is out
+ * of bounds.
+ */
+ void insert(const Pointer& pointer) {
+ LOG_IF(FATAL, nextPointerIndex >= pointers.size())
+ << "Cannot insert more than " << MAX_POINTERS << " in PointerMap.";
+ LOG_IF(FATAL, (pointer.properties.id < 0) || (pointer.properties.id > MAX_POINTER_ID))
+ << "Invalid pointer id.";
+ idToIndex[pointer.properties.id] = std::optional<size_t>{nextPointerIndex};
+ pointers[nextPointerIndex] = pointer;
+ ++nextPointerIndex;
+ }
+
+ /**
+ * Returns the pointer associated with the provided id if it exists.
+ * Otherwise, std::nullopt is returned.
+ */
+ std::optional<Pointer> find(PointerId id) const {
+ const int32_t idValue = ftl::to_underlying(id);
+ LOG_IF(FATAL, (idValue < 0) || (idValue > MAX_POINTER_ID)) << "Invalid pointer id.";
+ const std::optional<size_t> index = idToIndex[idValue];
+ return index.has_value() ? std::optional{pointers[*index]} : std::nullopt;
+ }
+
+ private:
+ /**
+ * The index at which a pointer is inserted in `pointers`. Likewise, it represents the
+ * number of pointers in PointerMap.
+ */
+ size_t nextPointerIndex{0};
+
+ /**
+ * Sequentially stores pointers. Each pointer's position is determined by the value of
+ * nextPointerIndex at insertion time.
+ */
+ std::array<Pointer, MAX_POINTERS + 1> pointers;
+
+ /**
+ * Maps each pointer id to its associated index in pointers. If no pointer with the id
+ * exists in pointers, the mapped value is std::nullopt.
+ */
+ std::array<std::optional<size_t>, MAX_POINTER_ID + 1> idToIndex;
+ };
+
struct Sample {
std::chrono::nanoseconds eventTime;
- std::vector<Pointer> pointers;
+ PointerMap pointerMap;
std::vector<PointerCoords> asPointerCoords() const {
std::vector<PointerCoords> pointersCoords;
- for (const Pointer& pointer : pointers) {
+ for (const Pointer& pointer : pointerMap) {
pointersCoords.push_back(pointer.coords);
}
return pointersCoords;
@@ -100,13 +220,12 @@
RingBuffer<Sample> mLatestSamples{/*capacity=*/2};
/**
- * Latest sample in mLatestSamples after resampling motion event. Used to compare if a pointer
- * does not move between samples.
+ * Latest sample in mLatestSamples after resampling motion event.
*/
std::optional<Sample> mLastRealSample;
/**
- * Latest prediction. Used to overwrite motion event samples if a set of conditions is met.
+ * Latest prediction. That is, the latest extrapolated sample.
*/
std::optional<Sample> mPreviousPrediction;
@@ -134,12 +253,12 @@
bool canInterpolate(const InputMessage& futureSample) const;
/**
- * Returns a sample interpolated between the latest sample of mLatestSamples and futureSample,
+ * Returns a sample interpolated between the latest sample of mLatestSamples and futureMessage,
* if the conditions from canInterpolate are satisfied. Otherwise, returns nullopt.
* mLatestSamples must have at least one sample when attemptInterpolation is called.
*/
std::optional<Sample> attemptInterpolation(std::chrono::nanoseconds resampleTime,
- const InputMessage& futureSample) const;
+ const InputMessage& futureMessage) const;
/**
* Checks if there are necessary conditions to extrapolate. That is, there are at least two
@@ -156,7 +275,8 @@
std::optional<Sample> attemptExtrapolation(std::chrono::nanoseconds resampleTime) const;
/**
- * Iterates through motion event samples, and calls overwriteStillPointers on each sample.
+ * Iterates through motion event samples, and replaces real coordinates with resampled
+ * coordinates to avoid jerkiness in certain conditions.
*/
void overwriteMotionEventSamples(MotionEvent& motionEvent) const;
@@ -174,4 +294,44 @@
inline static void addSampleToMotionEvent(const Sample& sample, MotionEvent& motionEvent);
};
+
+/**
+ * Resampler that first applies the LegacyResampler resampling algorithm, then independently filters
+ * the X and Y coordinates with a pair of One Euro filters.
+ */
+class FilteredLegacyResampler final : public Resampler {
+public:
+ /**
+ * Creates a resampler, using the given minCutoffFreq and beta to instantiate its One Euro
+ * filters.
+ */
+ explicit FilteredLegacyResampler(float minCutoffFreq, float beta);
+
+ void resampleMotionEvent(std::chrono::nanoseconds requestedFrameTime, MotionEvent& motionEvent,
+ const InputMessage* futureMessage) override;
+
+ std::chrono::nanoseconds getResampleLatency() const override;
+
+private:
+ LegacyResampler mResampler;
+
+ /**
+ * Minimum cutoff frequency of the value's low pass filter. Refer to OneEuroFilter class for a
+ * more detailed explanation.
+ */
+ const float mMinCutoffFreq;
+
+ /**
+ * Scaling factor of the adaptive cutoff frequency criterion. Refer to OneEuroFilter class for a
+ * more detailed explanation.
+ */
+ const float mBeta;
+
+ /*
+ * Note: an associative array with constant insertion and lookup times would be more efficient.
+ * When this was implemented, there was no container with these properties.
+ */
+ std::map<int32_t /*pointerId*/, CoordinateFilter> mFilteredPointers;
+};
+
} // namespace android
diff --git a/include/powermanager/OWNERS b/include/powermanager/OWNERS
new file mode 100644
index 0000000..9f40e27
--- /dev/null
+++ b/include/powermanager/OWNERS
@@ -0,0 +1 @@
+file:platform/frameworks/base:/ADPF_OWNERS
\ No newline at end of file
diff --git a/include/powermanager/PowerHalController.h b/include/powermanager/PowerHalController.h
index 7e0bd5b..f4f4d5e 100644
--- a/include/powermanager/PowerHalController.h
+++ b/include/powermanager/PowerHalController.h
@@ -72,6 +72,7 @@
virtual HalResult<aidl::android::hardware::power::ChannelConfig> getSessionChannel(
int tgid, int uid) override;
virtual HalResult<void> closeSessionChannel(int tgid, int uid) override;
+ virtual HalResult<aidl::android::hardware::power::SupportInfo> getSupportInfo() override;
private:
std::mutex mConnectedHalMutex;
diff --git a/include/powermanager/PowerHalWrapper.h b/include/powermanager/PowerHalWrapper.h
index 6e347a9..4290182 100644
--- a/include/powermanager/PowerHalWrapper.h
+++ b/include/powermanager/PowerHalWrapper.h
@@ -63,6 +63,7 @@
virtual HalResult<aidl::android::hardware::power::ChannelConfig> getSessionChannel(int tgid,
int uid) = 0;
virtual HalResult<void> closeSessionChannel(int tgid, int uid) = 0;
+ virtual HalResult<aidl::android::hardware::power::SupportInfo> getSupportInfo() = 0;
};
// Empty Power HAL wrapper that ignores all api calls.
@@ -85,6 +86,7 @@
HalResult<aidl::android::hardware::power::ChannelConfig> getSessionChannel(int tgid,
int uid) override;
HalResult<void> closeSessionChannel(int tgid, int uid) override;
+ HalResult<aidl::android::hardware::power::SupportInfo> getSupportInfo() override;
protected:
virtual const char* getUnsupportedMessage();
@@ -170,6 +172,7 @@
HalResult<aidl::android::hardware::power::ChannelConfig> getSessionChannel(int tgid,
int uid) override;
HalResult<void> closeSessionChannel(int tgid, int uid) override;
+ HalResult<aidl::android::hardware::power::SupportInfo> getSupportInfo() override;
protected:
const char* getUnsupportedMessage() override;
diff --git a/include/private/OWNERS b/include/private/OWNERS
new file mode 100644
index 0000000..db3ae48
--- /dev/null
+++ b/include/private/OWNERS
@@ -0,0 +1,4 @@
+# ADPF
+per-file thermal_private.h = file:platform/frameworks/base:/ADPF_OWNERS
+per-file performance_hint_private.h = file:platform/frameworks/base:/ADPF_OWNERS
+per-file system_health_private.h = file:platform/frameworks/base:/ADPF_OWNERS
diff --git a/include/private/display_luts_private.h b/include/private/display_luts_private.h
new file mode 100644
index 0000000..c347a0c
--- /dev/null
+++ b/include/private/display_luts_private.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2024 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 <android/display_luts.h>
+#include <stdint.h>
+#include <vector>
+#include <utils/RefBase.h>
+
+using namespace android;
+
+__BEGIN_DECLS
+
+struct ADisplayLutsEntry_buffer {
+ std::vector<float> data;
+};
+
+struct ADisplayLutsEntry_properties {
+ ADisplayLuts_Dimension dimension;
+ int32_t size;
+ ADisplayLuts_SamplingKey samplingKey;
+};
+
+struct ADisplayLutsEntry: public RefBase {
+ struct ADisplayLutsEntry_buffer buffer;
+ struct ADisplayLutsEntry_properties properties;
+ ADisplayLutsEntry() {}
+
+ // copy constructor
+ ADisplayLutsEntry(const ADisplayLutsEntry& other) :
+ buffer(other.buffer),
+ properties(other.properties) {}
+
+ // copy operator
+ ADisplayLutsEntry& operator=(const ADisplayLutsEntry& other) {
+ if (this != &other) { // Protect against self-assignment
+ buffer = other.buffer;
+ properties = other.properties;
+ }
+ return *this;
+ }
+};
+
+struct ADisplayLuts: public RefBase {
+ int32_t totalBufferSize;
+ std::vector<int32_t> offsets;
+ std::vector<sp<ADisplayLutsEntry>> entries;
+
+ ADisplayLuts() : totalBufferSize(0) {}
+};
+
+__END_DECLS
\ No newline at end of file
diff --git a/include/private/performance_hint_private.h b/include/private/performance_hint_private.h
index e5eee34..a468313 100644
--- a/include/private/performance_hint_private.h
+++ b/include/private/performance_hint_private.h
@@ -74,6 +74,20 @@
* baseline to prepare for an arbitrary load, and must wake up if inactive.
*/
GPU_LOAD_RESET = 7,
+
+ /**
+ * This hint indicates an upcoming CPU workload that is abnormally large and
+ * not representative of the workload. This should be used for rare, one-time
+ * operations and should be ignored by any load tracking or session hysteresis.
+ */
+ CPU_LOAD_SPIKE = 8,
+
+ /**
+ * This hint indicates an upcoming GPU workload that is abnormally large and
+ * not representative of the workload. This should be used for rare, one-time
+ * operations and should be ignored by any load tracking or session hysteresis.
+ */
+ GPU_LOAD_SPIKE = 9,
};
// Allows access to PowerHAL's SessionTags without needing to import its AIDL
@@ -83,6 +97,7 @@
HWUI = 2,
GAME = 3,
APP = 4,
+ SYSUI = 5,
};
/**
@@ -107,12 +122,48 @@
APerformanceHintSession* APerformanceHint_createSessionInternal(APerformanceHintManager* manager,
const int32_t* threadIds, size_t size,
int64_t initialTargetWorkDurationNanos, SessionTag tag);
+/**
+ * Creates a session using ASessionCreationConfig
+ */
+int APerformanceHint_createSessionUsingConfigInternal(
+ APerformanceHintManager* manager,
+ ASessionCreationConfig* config,
+ APerformanceHintSession** sessionOut,
+ SessionTag tag);
+
+/**
+ * Creates a session from the Java SDK implementation
+ */
+APerformanceHintSession* APerformanceHint_createSessionFromJava(APerformanceHintManager* manager,
+ const int32_t* threadIds, size_t size,
+ int64_t initialTargetWorkDurationNanos);
+
+/**
+ * Special method for Java SDK implementation to kill sessions
+ */
+void APerformanceHint_closeSessionFromJava(APerformanceHintSession* session);
/**
* Forces FMQ to be enabled or disabled, for testing only.
*/
void APerformanceHint_setUseFMQForTesting(bool enabled);
+/**
+ * Get the rate limiter properties for testing.
+ */
+void APerformanceHint_getRateLimiterPropertiesForTesting(
+ int32_t* maxLoadHintsPerInterval, int64_t* loadHintInterval);
+
+/*
+ * Forces the "new load hint" flag to be disabled for testing.
+ */
+void APerformanceHint_setUseNewLoadHintBehaviorForTesting(bool newBehavior);
+
+/*
+ * Forces the graphics pipeline flag to be enabled or disabled, for testing only.
+ */
+void APerformanceHint_setUseGraphicsPipelineForTesting(bool enabled);
+
__END_DECLS
#endif // ANDROID_PRIVATE_NATIVE_PERFORMANCE_HINT_PRIVATE_H
diff --git a/libs/binder/trusty/ndk/include/android/llndk-versioning.h b/include/private/system_health_private.h
similarity index 67%
copy from libs/binder/trusty/ndk/include/android/llndk-versioning.h
copy to include/private/system_health_private.h
index e955a34..05a5a06 100644
--- a/libs/binder/trusty/ndk/include/android/llndk-versioning.h
+++ b/include/private/system_health_private.h
@@ -13,7 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#pragma once
-// TODO(b/349936395): set to true for Trusty
-#define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) (false)
+#ifndef ANDROID_PRIVATE_NATIVE_SYSTEM_HEALTH_H
+#define ANDROID_PRIVATE_NATIVE_SYSTEM_HEALTH_H
+
+#include <stdint.h>
+
+__BEGIN_DECLS
+
+/**
+ * For testing only.
+ */
+void ASystemHealth_setIHintManagerForTesting(void* iManager);
+
+__END_DECLS
+
+#endif // ANDROID_PRIVATE_NATIVE_SYSTEM_HEALTH_H
+
diff --git a/libs/attestation/OWNERS b/libs/attestation/OWNERS
index 4dbb0ea..76811f2 100644
--- a/libs/attestation/OWNERS
+++ b/libs/attestation/OWNERS
@@ -1,2 +1 @@
-chaviw@google.com
-svv@google.com
\ No newline at end of file
+svv@google.com
diff --git a/libs/battery/LongArrayMultiStateCounter.cpp b/libs/battery/LongArrayMultiStateCounter.cpp
index 125cfaf..334d84b 100644
--- a/libs/battery/LongArrayMultiStateCounter.cpp
+++ b/libs/battery/LongArrayMultiStateCounter.cpp
@@ -21,59 +21,138 @@
namespace android {
namespace battery {
+Uint64ArrayRW::Uint64ArrayRW(const Uint64Array ©) : Uint64Array(copy.size()) {
+ if (mSize != 0 && copy.data() != nullptr) {
+ mData = new uint64_t[mSize];
+ memcpy(mData, copy.data(), mSize * sizeof(uint64_t));
+ } else {
+ mData = nullptr;
+ }
+}
+
+uint64_t *Uint64ArrayRW::dataRW() {
+ if (mData == nullptr) {
+ mData = new uint64_t[mSize];
+ memset(mData, 0, mSize * sizeof(uint64_t));
+ }
+ return mData;
+}
+
+Uint64ArrayRW &Uint64ArrayRW::operator=(const Uint64Array &t) {
+ if (t.size() != mSize) {
+ delete[] mData;
+ mSize = t.size();
+ mData = nullptr;
+ }
+ if (mSize != 0) {
+ if (t.data() != nullptr) {
+ if (mData == nullptr) {
+ mData = new uint64_t[mSize];
+ }
+ memcpy(mData, t.data(), mSize * sizeof(uint64_t));
+ } else {
+ delete[] mData;
+ mData = nullptr;
+ }
+ }
+ return *this;
+}
+
+std::ostream &operator<<(std::ostream &os, const Uint64Array &v) {
+ os << "{";
+ const uint64_t *data = v.data();
+ if (data != nullptr) {
+ bool first = true;
+ for (size_t i = 0; i < v.size(); i++) {
+ if (!first) {
+ os << ", ";
+ }
+ os << data[i];
+ first = false;
+ }
+ }
+ os << "}";
+ return os;
+}
+
+// Convenience constructor for tests
+Uint64ArrayRW::Uint64ArrayRW(std::initializer_list<uint64_t> init) : Uint64Array(init.size()) {
+ mData = new uint64_t[mSize];
+ memcpy(mData, init.begin(), mSize * sizeof(uint64_t));
+}
+
+// Used in tests only.
+bool Uint64Array::operator==(const Uint64Array &other) const {
+ if (size() != other.size()) {
+ return false;
+ }
+ const uint64_t* thisData = data();
+ const uint64_t* thatData = other.data();
+ for (size_t i = 0; i < mSize; i++) {
+ const uint64_t v1 = thisData != nullptr ? thisData[i] : 0;
+ const uint64_t v2 = thatData != nullptr ? thatData[i] : 0;
+ if (v1 != v2) {
+ return false;
+ }
+ }
+ return true;
+}
+
template <>
-bool LongArrayMultiStateCounter::delta(const std::vector<uint64_t>& previousValue,
- const std::vector<uint64_t>& newValue,
- std::vector<uint64_t>* outValue) const {
+void LongArrayMultiStateCounter::add(Uint64ArrayRW *value1, const Uint64Array &value2,
+ const uint64_t numerator, const uint64_t denominator) const {
+ const uint64_t* data2 = value2.data();
+ if (data2 == nullptr) {
+ return;
+ }
+
+ uint64_t* data1 = value1->dataRW();
+ size_t size = value2.size();
+ if (numerator != denominator) {
+ for (size_t i = 0; i < size; i++) {
+ // The caller ensures that denominator != 0
+ data1[i] += data2[i] * numerator / denominator;
+ }
+ } else {
+ for (size_t i = 0; i < size; i++) {
+ data1[i] += data2[i];
+ }
+ }
+}
+
+template<>
+bool LongArrayMultiStateCounter::delta(const Uint64ArrayRW &previousValue,
+ const Uint64Array &newValue, Uint64ArrayRW *outValue) const {
size_t size = previousValue.size();
if (newValue.size() != size) {
- ALOGE("Incorrect array size: %d, should be %d", (int)newValue.size(), (int)size);
+ ALOGE("Incorrect array size: %d, should be %d", (int) newValue.size(), (int) size);
+ return false;
+ }
+ if (outValue->size() != size) {
+ ALOGE("Incorrect outValue size: %d, should be %d", (int) outValue->size(), (int) size);
return false;
}
bool is_delta_valid = true;
- for (int i = size - 1; i >= 0; i--) {
- if (newValue[i] >= previousValue[i]) {
- (*outValue)[i] = newValue[i] - previousValue[i];
- } else {
- (*outValue)[i] = 0;
+ const uint64_t *prevData = previousValue.data();
+ const uint64_t *newData = newValue.data();
+ uint64_t *outData = outValue->dataRW();
+ for (size_t i = 0; i < size; i++) {
+ if (prevData == nullptr) {
+ if (newData == nullptr) {
+ outData[i] = 0;
+ } else {
+ outData[i] = newData[i];
+ }
+ } else if (newData == nullptr || newData[i] < prevData[i]) {
+ outData[i] = 0;
is_delta_valid = false;
+ } else {
+ outData[i] = newData[i] - prevData[i];
}
}
return is_delta_valid;
}
-template <>
-void LongArrayMultiStateCounter::add(std::vector<uint64_t>* value1,
- const std::vector<uint64_t>& value2, const uint64_t numerator,
- const uint64_t denominator) const {
- if (numerator != denominator) {
- for (int i = value2.size() - 1; i >= 0; i--) {
- // The caller ensures that denominator != 0
- (*value1)[i] += value2[i] * numerator / denominator;
- }
- } else {
- for (int i = value2.size() - 1; i >= 0; i--) {
- (*value1)[i] += value2[i];
- }
- }
-}
-
-template <>
-std::string LongArrayMultiStateCounter::valueToString(const std::vector<uint64_t>& v) const {
- std::stringstream s;
- s << "{";
- bool first = true;
- for (uint64_t n : v) {
- if (!first) {
- s << ", ";
- }
- s << n;
- first = false;
- }
- s << "}";
- return s.str();
-}
-
} // namespace battery
} // namespace android
diff --git a/libs/battery/LongArrayMultiStateCounter.h b/libs/battery/LongArrayMultiStateCounter.h
index f3439f6..e00c968 100644
--- a/libs/battery/LongArrayMultiStateCounter.h
+++ b/libs/battery/LongArrayMultiStateCounter.h
@@ -23,7 +23,66 @@
namespace android {
namespace battery {
-typedef MultiStateCounter<std::vector<uint64_t>> LongArrayMultiStateCounter;
+/**
+ * Wrapper for an array of uint64's.
+ */
+class Uint64Array {
+ protected:
+ size_t mSize;
+
+ public:
+ Uint64Array() : Uint64Array(0) {}
+
+ Uint64Array(size_t size) : mSize(size) {}
+
+ virtual ~Uint64Array() {}
+
+ size_t size() const { return mSize; }
+
+ /**
+ * Returns the wrapped array.
+ *
+ * Nullable! Null should be interpreted the same as an array of zeros
+ */
+ virtual const uint64_t *data() const { return nullptr; }
+
+ friend std::ostream &operator<<(std::ostream &os, const Uint64Array &v);
+
+ // Test API
+ bool operator==(const Uint64Array &other) const;
+};
+
+/**
+ * Mutable version of Uint64Array.
+ */
+class Uint64ArrayRW: public Uint64Array {
+ uint64_t* mData;
+
+public:
+ Uint64ArrayRW() : Uint64ArrayRW(0) {}
+
+ Uint64ArrayRW(size_t size) : Uint64Array(size), mData(nullptr) {}
+
+ Uint64ArrayRW(const Uint64Array ©);
+
+ // Need an explicit copy constructor. In the initialization context C++ does not understand that
+ // a Uint64ArrayRW is a Uint64Array.
+ Uint64ArrayRW(const Uint64ArrayRW ©) : Uint64ArrayRW((const Uint64Array &) copy) {}
+
+ // Test API
+ Uint64ArrayRW(std::initializer_list<uint64_t> init);
+
+ ~Uint64ArrayRW() override { delete[] mData; }
+
+ const uint64_t *data() const override { return mData; }
+
+ // NonNull. Will initialize the wrapped array if it is null.
+ uint64_t *dataRW();
+
+ Uint64ArrayRW &operator=(const Uint64Array &t);
+};
+
+typedef MultiStateCounter<Uint64ArrayRW, Uint64Array> LongArrayMultiStateCounter;
} // namespace battery
} // namespace android
diff --git a/libs/battery/LongArrayMultiStateCounterTest.cpp b/libs/battery/LongArrayMultiStateCounterTest.cpp
index e4e6b2a..1c74e3f 100644
--- a/libs/battery/LongArrayMultiStateCounterTest.cpp
+++ b/libs/battery/LongArrayMultiStateCounterTest.cpp
@@ -24,25 +24,25 @@
class LongArrayMultiStateCounterTest : public testing::Test {};
TEST_F(LongArrayMultiStateCounterTest, stateChange) {
- LongArrayMultiStateCounter testCounter(2, std::vector<uint64_t>(4));
- testCounter.updateValue(std::vector<uint64_t>({0, 0, 0, 0}), 1000);
+ LongArrayMultiStateCounter testCounter(2, Uint64Array(4));
+ testCounter.updateValue(Uint64ArrayRW({0, 0, 0, 0}), 1000);
testCounter.setState(0, 1000);
testCounter.setState(1, 2000);
- testCounter.updateValue(std::vector<uint64_t>({100, 200, 300, 400}), 3000);
+ testCounter.updateValue(Uint64ArrayRW({100, 200, 300, 400}), 3000);
// Time was split in half between the two states, so the counts will be split 50:50 too
- EXPECT_EQ(std::vector<uint64_t>({50, 100, 150, 200}), testCounter.getCount(0));
- EXPECT_EQ(std::vector<uint64_t>({50, 100, 150, 200}), testCounter.getCount(1));
+ EXPECT_EQ(Uint64ArrayRW({50, 100, 150, 200}), testCounter.getCount(0));
+ EXPECT_EQ(Uint64ArrayRW({50, 100, 150, 200}), testCounter.getCount(1));
}
TEST_F(LongArrayMultiStateCounterTest, accumulation) {
- LongArrayMultiStateCounter testCounter(2, std::vector<uint64_t>(4));
- testCounter.updateValue(std::vector<uint64_t>({0, 0, 0, 0}), 1000);
+ LongArrayMultiStateCounter testCounter(2, Uint64Array(4));
+ testCounter.updateValue(Uint64ArrayRW({0, 0, 0, 0}), 1000);
testCounter.setState(0, 1000);
testCounter.setState(1, 2000);
- testCounter.updateValue(std::vector<uint64_t>({100, 200, 300, 400}), 3000);
+ testCounter.updateValue(Uint64ArrayRW({100, 200, 300, 400}), 3000);
testCounter.setState(0, 4000);
- testCounter.updateValue(std::vector<uint64_t>({200, 300, 400, 500}), 8000);
+ testCounter.updateValue(Uint64ArrayRW({200, 300, 400, 500}), 8000);
// The first delta is split 50:50:
// 0: {50, 100, 150, 200}
@@ -50,16 +50,16 @@
// The second delta is split 4:1
// 0: {80, 80, 80, 80}
// 1: {20, 20, 20, 20}
- EXPECT_EQ(std::vector<uint64_t>({130, 180, 230, 280}), testCounter.getCount(0));
- EXPECT_EQ(std::vector<uint64_t>({70, 120, 170, 220}), testCounter.getCount(1));
+ EXPECT_EQ(Uint64ArrayRW({130, 180, 230, 280}), testCounter.getCount(0));
+ EXPECT_EQ(Uint64ArrayRW({70, 120, 170, 220}), testCounter.getCount(1));
}
TEST_F(LongArrayMultiStateCounterTest, toString) {
- LongArrayMultiStateCounter testCounter(2, std::vector<uint64_t>(4));
- testCounter.updateValue(std::vector<uint64_t>({0, 0, 0, 0}), 1000);
+ LongArrayMultiStateCounter testCounter(2, Uint64Array(4));
+ testCounter.updateValue(Uint64ArrayRW({0, 0, 0, 0}), 1000);
testCounter.setState(0, 1000);
testCounter.setState(1, 2000);
- testCounter.updateValue(std::vector<uint64_t>({100, 200, 300, 400}), 3000);
+ testCounter.updateValue(Uint64ArrayRW({100, 200, 300, 400}), 3000);
EXPECT_STREQ("[0: {50, 100, 150, 200}, 1: {50, 100, 150, 200}] updated: 3000 currentState: 1",
testCounter.toString().c_str());
diff --git a/libs/battery/MultiStateCounter.h b/libs/battery/MultiStateCounter.h
index 04b7186..fadc4ff 100644
--- a/libs/battery/MultiStateCounter.h
+++ b/libs/battery/MultiStateCounter.h
@@ -35,12 +35,12 @@
typedef uint16_t state_t;
-template <class T>
+template <class T, class V>
class MultiStateCounter {
- uint16_t stateCount;
+ const uint16_t stateCount;
+ const V emptyValue;
state_t currentState;
time_t lastStateChangeTimestamp;
- T emptyValue;
T lastValue;
time_t lastUpdateTimestamp;
T deltaValue;
@@ -54,7 +54,7 @@
State* states;
public:
- MultiStateCounter(uint16_t stateCount, const T& emptyValue);
+ MultiStateCounter(uint16_t stateCount, const V& emptyValue);
virtual ~MultiStateCounter();
@@ -66,35 +66,35 @@
* Copies the current state and accumulated times-in-state from the source. Resets
* the accumulated value.
*/
- void copyStatesFrom(const MultiStateCounter<T>& source);
+ void copyStatesFrom(const MultiStateCounter<T, V> &source);
- void setValue(state_t state, const T& value);
+ void setValue(state_t state, const V& value);
/**
* Updates the value by distributing the delta from the previously set value
* among states according to their respective time-in-state.
* Returns the delta from the previously set value.
*/
- const T& updateValue(const T& value, time_t timestamp);
+ const V& updateValue(const V& value, time_t timestamp);
/**
* Updates the value by distributing the specified increment among states according
* to their respective time-in-state.
*/
- void incrementValue(const T& increment, time_t timestamp);
+ void incrementValue(const V& increment, time_t timestamp);
/**
* Adds the specified increment to the value for the current state, without affecting
* the last updated value or timestamp. Ignores partial time-in-state: the entirety of
* the increment is given to the current state.
*/
- void addValue(const T& increment);
+ void addValue(const V& increment);
void reset();
uint16_t getStateCount();
- const T& getCount(state_t state);
+ const V& getCount(state_t state);
std::string toString();
@@ -104,27 +104,25 @@
* Returns true iff the combination of previousValue and newValue is valid
* (newValue >= prevValue)
*/
- bool delta(const T& previousValue, const T& newValue, T* outValue) const;
+ bool delta(const T& previousValue, const V& newValue, T* outValue) const;
/**
* Adds value2 to value1 and stores the result in value1. Denominator is
* guaranteed to be non-zero.
*/
- void add(T* value1, const T& value2, const uint64_t numerator,
+ void add(T* value1, const V& value2, const uint64_t numerator,
const uint64_t denominator) const;
-
- std::string valueToString(const T& value) const;
};
// ---------------------- MultiStateCounter Implementation -------------------------
// Since MultiStateCounter is a template, the implementation must be inlined.
-template <class T>
-MultiStateCounter<T>::MultiStateCounter(uint16_t stateCount, const T& emptyValue)
+template <class T, class V>
+MultiStateCounter<T, V>::MultiStateCounter(uint16_t stateCount, const V& emptyValue)
: stateCount(stateCount),
+ emptyValue(emptyValue),
currentState(0),
lastStateChangeTimestamp(-1),
- emptyValue(emptyValue),
lastValue(emptyValue),
lastUpdateTimestamp(-1),
deltaValue(emptyValue),
@@ -136,13 +134,13 @@
}
}
-template <class T>
-MultiStateCounter<T>::~MultiStateCounter() {
+template <class T, class V>
+MultiStateCounter<T, V>::~MultiStateCounter() {
delete[] states;
};
-template <class T>
-void MultiStateCounter<T>::setEnabled(bool enabled, time_t timestamp) {
+template <class T, class V>
+void MultiStateCounter<T, V>::setEnabled(bool enabled, time_t timestamp) {
if (enabled == isEnabled) {
return;
}
@@ -167,8 +165,8 @@
}
}
-template <class T>
-void MultiStateCounter<T>::setState(state_t state, time_t timestamp) {
+template <class T, class V>
+void MultiStateCounter<T, V>::setState(state_t state, time_t timestamp) {
if (isEnabled && lastStateChangeTimestamp >= 0 && lastUpdateTimestamp >= 0) {
// If the update arrived out-of-order, just push back the timestamp to
// avoid having the situation where timeInStateSinceUpdate > timeSinceUpdate
@@ -198,8 +196,8 @@
lastStateChangeTimestamp = timestamp;
}
-template <class T>
-void MultiStateCounter<T>::copyStatesFrom(const MultiStateCounter<T>& source) {
+template <class T, class V>
+void MultiStateCounter<T, V>::copyStatesFrom(const MultiStateCounter<T, V>& source) {
if (stateCount != source.stateCount) {
ALOGE("State count mismatch: %u vs. %u\n", stateCount, source.stateCount);
return;
@@ -214,14 +212,14 @@
lastUpdateTimestamp = source.lastUpdateTimestamp;
}
-template <class T>
-void MultiStateCounter<T>::setValue(state_t state, const T& value) {
+template <class T, class V>
+void MultiStateCounter<T, V>::setValue(state_t state, const V& value) {
states[state].counter = value;
}
-template <class T>
-const T& MultiStateCounter<T>::updateValue(const T& value, time_t timestamp) {
- T* returnValue = &emptyValue;
+template <class T, class V>
+const V& MultiStateCounter<T, V>::updateValue(const V& value, time_t timestamp) {
+ const V* returnValue = &emptyValue;
// If the counter is disabled, we ignore the update, except when the counter got disabled after
// the previous update, in which case we still need to pick up the residual delta.
@@ -250,8 +248,8 @@
}
} else {
std::stringstream str;
- str << "updateValue is called with a value " << valueToString(value)
- << ", which is lower than the previous value " << valueToString(lastValue)
+ str << "updateValue is called with a value " << value
+ << ", which is lower than the previous value " << lastValue
<< "\n";
ALOGE("%s", str.str().c_str());
@@ -276,23 +274,25 @@
return *returnValue;
}
-template <class T>
-void MultiStateCounter<T>::incrementValue(const T& increment, time_t timestamp) {
+template <class T, class V>
+void MultiStateCounter<T, V>::incrementValue(const V& increment, time_t timestamp) {
+// T newValue;
+// newValue = lastValue; // Copy assignment, not initialization.
T newValue = lastValue;
add(&newValue, increment, 1 /* numerator */, 1 /* denominator */);
updateValue(newValue, timestamp);
}
-template <class T>
-void MultiStateCounter<T>::addValue(const T& value) {
+template <class T, class V>
+void MultiStateCounter<T, V>::addValue(const V& value) {
if (!isEnabled) {
return;
}
add(&states[currentState].counter, value, 1 /* numerator */, 1 /* denominator */);
}
-template <class T>
-void MultiStateCounter<T>::reset() {
+template <class T, class V>
+void MultiStateCounter<T, V>::reset() {
lastStateChangeTimestamp = -1;
lastUpdateTimestamp = -1;
for (int i = 0; i < stateCount; i++) {
@@ -301,25 +301,26 @@
}
}
-template <class T>
-uint16_t MultiStateCounter<T>::getStateCount() {
+template <class T, class V>
+uint16_t MultiStateCounter<T, V>::getStateCount() {
return stateCount;
}
-template <class T>
-const T& MultiStateCounter<T>::getCount(state_t state) {
+template <class T, class V>
+const V& MultiStateCounter<T, V>::getCount(state_t state) {
return states[state].counter;
}
-template <class T>
-std::string MultiStateCounter<T>::toString() {
+template <class T, class V>
+std::string MultiStateCounter<T, V>::toString() {
std::stringstream str;
+// str << "LAST VALUE: " << valueToString(lastValue);
str << "[";
for (int i = 0; i < stateCount; i++) {
if (i != 0) {
str << ", ";
}
- str << i << ": " << valueToString(states[i].counter);
+ str << i << ": " << states[i].counter;
if (states[i].timeInStateSinceUpdate > 0) {
str << " timeInStateSinceUpdate: " << states[i].timeInStateSinceUpdate;
}
diff --git a/libs/battery/MultiStateCounterTest.cpp b/libs/battery/MultiStateCounterTest.cpp
index a51a38a..589b7fe 100644
--- a/libs/battery/MultiStateCounterTest.cpp
+++ b/libs/battery/MultiStateCounterTest.cpp
@@ -21,7 +21,7 @@
namespace android {
namespace battery {
-typedef MultiStateCounter<double> DoubleMultiStateCounter;
+typedef MultiStateCounter<double, double> DoubleMultiStateCounter;
template <>
bool DoubleMultiStateCounter::delta(const double& previousValue, const double& newValue,
@@ -41,11 +41,6 @@
}
}
-template <>
-std::string DoubleMultiStateCounter::valueToString(const double& v) const {
- return std::to_string(v);
-}
-
class MultiStateCounterTest : public testing::Test {};
TEST_F(MultiStateCounterTest, constructor) {
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 6903cb5..ea5343a 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -269,6 +269,7 @@
"-Wzero-as-null-pointer-constant",
"-Wreorder-init-list",
"-Wunused-const-variable",
+ "-Wunused-result",
"-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION",
"-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
// Hide symbols by default and set the BUILDING_LIBBINDER macro so that
@@ -456,6 +457,28 @@
}
soong_config_module_type {
+ name: "libbinder_remove_cache_static_list_config",
+ module_type: "cc_defaults",
+ config_namespace: "libbinder",
+ bool_variables: ["release_libbinder_remove_cache_static_list"],
+ properties: [
+ "cflags",
+ ],
+}
+
+libbinder_remove_cache_static_list_config {
+ name: "libbinder_remove_cache_static_list_flag",
+ soong_config_variables: {
+ release_libbinder_remove_cache_static_list: {
+ cflags: ["-DLIBBINDER_REMOVE_CACHE_STATIC_LIST"],
+ conditions_default: {
+ cflags: ["-DNO_LIBBINDER_REMOVE_CACHE_STATIC_LIST"],
+ },
+ },
+ },
+}
+
+soong_config_module_type {
name: "libbinder_client_cache_config",
module_type: "cc_defaults",
config_namespace: "libbinder",
@@ -477,9 +500,35 @@
},
}
+soong_config_module_type {
+ name: "libbinder_addservice_cache_config",
+ module_type: "cc_defaults",
+ config_namespace: "libbinder",
+ bool_variables: ["release_libbinder_addservice_cache"],
+ properties: [
+ "cflags",
+ ],
+}
+
+libbinder_addservice_cache_config {
+ name: "libbinder_addservice_cache_flag",
+ soong_config_variables: {
+ release_libbinder_addservice_cache: {
+ cflags: ["-DLIBBINDER_ADDSERVICE_CACHE"],
+ conditions_default: {
+ cflags: ["-DNO_LIBBINDER_ADDSERVICE_CACHE"],
+ },
+ },
+ },
+}
+
cc_defaults {
name: "libbinder_kernel_defaults",
- defaults: ["libbinder_client_cache_flag"],
+ defaults: [
+ "libbinder_client_cache_flag",
+ "libbinder_addservice_cache_flag",
+ "libbinder_remove_cache_static_list_flag",
+ ],
srcs: [
"BufferedTextOutput.cpp",
"BackendUnifiedServiceManager.cpp",
@@ -778,6 +827,7 @@
// so we restrict its visibility to the Trusty-specific packages.
visibility: [
":__subpackages__",
+ "//hardware/interfaces/security/see:__subpackages__",
"//system/core/trusty:__subpackages__",
"//vendor:__subpackages__",
],
@@ -801,6 +851,7 @@
"aidl/android/os/IServiceCallback.aidl",
"aidl/android/os/IServiceManager.aidl",
"aidl/android/os/Service.aidl",
+ "aidl/android/os/ServiceWithMetadata.aidl",
"aidl/android/os/ServiceDebugInfo.aidl",
],
path: "aidl",
@@ -829,6 +880,7 @@
backend: {
rust: {
apex_available: [
+ "//apex_available:platform",
"com.android.virt",
],
enabled: true,
@@ -871,13 +923,16 @@
symbol_file: "libbinder_rpc_unstable.map.txt",
},
+ header_abi_checker: {
+ enabled: false,
+ },
+
// This library is intentionally limited to these targets, and it will be removed later.
// Do not expand the visibility.
visibility: [
":__subpackages__",
"//packages/modules/Virtualization:__subpackages__",
"//device/google/cuttlefish/shared/minidroid:__subpackages__",
- "//system/software_defined_vehicle:__subpackages__",
"//visibility:any_system_partition",
],
}
diff --git a/libs/binder/BackendUnifiedServiceManager.cpp b/libs/binder/BackendUnifiedServiceManager.cpp
index 52b485a..7c0319a 100644
--- a/libs/binder/BackendUnifiedServiceManager.cpp
+++ b/libs/binder/BackendUnifiedServiceManager.cpp
@@ -15,7 +15,9 @@
*/
#include "BackendUnifiedServiceManager.h"
+#include <android-base/strings.h>
#include <android/os/IAccessor.h>
+#include <android/os/IServiceManager.h>
#include <binder/RpcSession.h>
#if defined(__BIONIC__) && !defined(__ANDROID_VNDK__)
@@ -30,8 +32,24 @@
constexpr bool kUseCache = false;
#endif
+#ifdef LIBBINDER_ADDSERVICE_CACHE
+constexpr bool kUseCacheInAddService = true;
+#else
+constexpr bool kUseCacheInAddService = false;
+#endif
+
+#ifdef LIBBINDER_REMOVE_CACHE_STATIC_LIST
+constexpr bool kRemoveStaticList = true;
+#else
+constexpr bool kRemoveStaticList = false;
+#endif
+
using AidlServiceManager = android::os::IServiceManager;
-using IAccessor = android::os::IAccessor;
+using android::os::IAccessor;
+using binder::Status;
+
+static const char* kUnsupportedOpNoServiceManager =
+ "Unsupported operation without a kernel binder servicemanager process";
static const char* kStaticCachableList[] = {
// go/keep-sorted start
@@ -39,10 +57,14 @@
"account",
"activity",
"alarm",
+ "android.frameworks.stats.IStats/default",
"android.system.keystore2.IKeystoreService/default",
"appops",
"audio",
+ "autofill",
+ "batteryproperties",
"batterystats",
+ "biometic",
"carrier_config",
"connectivity",
"content",
@@ -58,6 +80,7 @@
"jobscheduler",
"legacy_permission",
"location",
+ "lock_settings",
"media.extractor",
"media.metrics",
"media.player",
@@ -78,15 +101,19 @@
"phone",
"platform_compat",
"power",
+ "processinfo",
"role",
+ "sensitive_content_protection_service",
"sensorservice",
"statscompanion",
"telephony.registry",
"thermalservice",
"time_detector",
+ "tracing.proxy",
"trust",
"uimode",
"user",
+ "vibrator",
"virtualdevice",
"virtualdevice_native",
"webviewupdate",
@@ -94,13 +121,22 @@
// go/keep-sorted end
};
+os::ServiceWithMetadata createServiceWithMetadata(const sp<IBinder>& service, bool isLazyService) {
+ os::ServiceWithMetadata out = os::ServiceWithMetadata();
+ out.service = service;
+ out.isLazyService = isLazyService;
+ return out;
+}
+
bool BinderCacheWithInvalidation::isClientSideCachingEnabled(const std::string& serviceName) {
- if (ProcessState::self()->getThreadPoolMaxTotalThreadCount() <= 0) {
+ sp<ProcessState> self = ProcessState::selfOrNull();
+ if (!self || self->getThreadPoolMaxTotalThreadCount() <= 0) {
ALOGW("Thread Pool max thread count is 0. Cannot cache binder as linkToDeath cannot be "
"implemented. serviceName: %s",
serviceName.c_str());
return false;
}
+ if (kRemoveStaticList) return true;
for (const char* name : kStaticCachableList) {
if (name == serviceName) {
return true;
@@ -109,19 +145,51 @@
return false;
}
-binder::Status BackendUnifiedServiceManager::updateCache(const std::string& serviceName,
- const os::Service& service) {
+Status BackendUnifiedServiceManager::updateCache(const std::string& serviceName,
+ const os::Service& service) {
if (!kUseCache) {
- return binder::Status::ok();
+ return Status::ok();
}
- if (service.getTag() == os::Service::Tag::binder) {
- sp<IBinder> binder = service.get<os::Service::Tag::binder>();
- if (binder && mCacheForGetService->isClientSideCachingEnabled(serviceName) &&
- binder->isBinderAlive()) {
- return mCacheForGetService->setItem(serviceName, binder);
- }
+
+ if (service.getTag() == os::Service::Tag::serviceWithMetadata) {
+ auto serviceWithMetadata = service.get<os::Service::Tag::serviceWithMetadata>();
+ return updateCache(serviceName, serviceWithMetadata.service,
+ serviceWithMetadata.isLazyService);
}
- return binder::Status::ok();
+ return Status::ok();
+}
+
+Status BackendUnifiedServiceManager::updateCache(const std::string& serviceName,
+ const sp<IBinder>& binder, bool isServiceLazy) {
+ std::string traceStr;
+ // Don't cache if service is lazy
+ if (kRemoveStaticList && isServiceLazy) {
+ return Status::ok();
+ }
+ if (atrace_is_tag_enabled(ATRACE_TAG_AIDL)) {
+ traceStr = "BinderCacheWithInvalidation::updateCache : " + serviceName;
+ }
+ binder::ScopedTrace aidlTrace(ATRACE_TAG_AIDL, traceStr.c_str());
+ if (!binder) {
+ binder::ScopedTrace
+ aidlTrace(ATRACE_TAG_AIDL,
+ "BinderCacheWithInvalidation::updateCache failed: binder_null");
+ } else if (!binder->isBinderAlive()) {
+ binder::ScopedTrace aidlTrace(ATRACE_TAG_AIDL,
+ "BinderCacheWithInvalidation::updateCache failed: "
+ "isBinderAlive_false");
+ }
+ // If we reach here with kRemoveStaticList=true then we know service isn't lazy
+ else if (mCacheForGetService->isClientSideCachingEnabled(serviceName)) {
+ binder::ScopedTrace aidlTrace(ATRACE_TAG_AIDL,
+ "BinderCacheWithInvalidation::updateCache successful");
+ return mCacheForGetService->setItem(serviceName, binder);
+ } else {
+ binder::ScopedTrace aidlTrace(ATRACE_TAG_AIDL,
+ "BinderCacheWithInvalidation::updateCache failed: "
+ "caching_not_enabled");
+ }
+ return Status::ok();
}
bool BackendUnifiedServiceManager::returnIfCached(const std::string& serviceName,
@@ -132,7 +200,7 @@
sp<IBinder> item = mCacheForGetService->getItem(serviceName);
// TODO(b/363177618): Enable caching for binders which are always null.
if (item != nullptr && item->isBinderAlive()) {
- *_out = os::Service::make<os::Service::Tag::binder>(item);
+ *_out = createServiceWithMetadata(item, false);
return true;
}
return false;
@@ -143,25 +211,25 @@
mCacheForGetService = std::make_shared<BinderCacheWithInvalidation>();
}
-sp<AidlServiceManager> BackendUnifiedServiceManager::getImpl() {
- return mTheRealServiceManager;
-}
-
-binder::Status BackendUnifiedServiceManager::getService(const ::std::string& name,
- sp<IBinder>* _aidl_return) {
+Status BackendUnifiedServiceManager::getService(const ::std::string& name,
+ sp<IBinder>* _aidl_return) {
os::Service service;
- binder::Status status = getService2(name, &service);
- *_aidl_return = service.get<os::Service::Tag::binder>();
+ Status status = getService2(name, &service);
+ if (status.isOk()) {
+ *_aidl_return = service.get<os::Service::Tag::serviceWithMetadata>().service;
+ }
return status;
}
-binder::Status BackendUnifiedServiceManager::getService2(const ::std::string& name,
- os::Service* _out) {
+Status BackendUnifiedServiceManager::getService2(const ::std::string& name, os::Service* _out) {
if (returnIfCached(name, _out)) {
- return binder::Status::ok();
+ return Status::ok();
}
os::Service service;
- binder::Status status = mTheRealServiceManager->getService2(name, &service);
+ Status status = Status::ok();
+ if (mTheRealServiceManager) {
+ status = mTheRealServiceManager->getService2(name, &service);
+ }
if (status.isOk()) {
status = toBinderService(name, service, _out);
@@ -172,14 +240,26 @@
return status;
}
-binder::Status BackendUnifiedServiceManager::checkService(const ::std::string& name,
- os::Service* _out) {
+Status BackendUnifiedServiceManager::checkService(const ::std::string& name,
+ sp<IBinder>* _aidl_return) {
+ os::Service service;
+ Status status = checkService2(name, &service);
+ if (status.isOk()) {
+ *_aidl_return = service.get<os::Service::Tag::serviceWithMetadata>().service;
+ }
+ return status;
+}
+
+Status BackendUnifiedServiceManager::checkService2(const ::std::string& name, os::Service* _out) {
os::Service service;
if (returnIfCached(name, _out)) {
- return binder::Status::ok();
+ return Status::ok();
}
- binder::Status status = mTheRealServiceManager->checkService(name, &service);
+ Status status = Status::ok();
+ if (mTheRealServiceManager) {
+ status = mTheRealServiceManager->checkService2(name, &service);
+ }
if (status.isOk()) {
status = toBinderService(name, service, _out);
if (status.isOk()) {
@@ -189,18 +269,19 @@
return status;
}
-binder::Status BackendUnifiedServiceManager::toBinderService(const ::std::string& name,
- const os::Service& in,
- os::Service* _out) {
+Status BackendUnifiedServiceManager::toBinderService(const ::std::string& name,
+ const os::Service& in, os::Service* _out) {
switch (in.getTag()) {
- case os::Service::Tag::binder: {
- if (in.get<os::Service::Tag::binder>() == nullptr) {
+ case os::Service::Tag::serviceWithMetadata: {
+ auto serviceWithMetadata = in.get<os::Service::Tag::serviceWithMetadata>();
+ if (serviceWithMetadata.service == nullptr) {
// failed to find a service. Check to see if we have any local
// injected Accessors for this service.
os::Service accessor;
- binder::Status status = getInjectedAccessor(name, &accessor);
+ Status status = getInjectedAccessor(name, &accessor);
if (!status.isOk()) {
- *_out = os::Service::make<os::Service::Tag::binder>(nullptr);
+ *_out = os::Service::make<os::Service::Tag::serviceWithMetadata>(
+ createServiceWithMetadata(nullptr, false));
return status;
}
if (accessor.getTag() == os::Service::Tag::accessor &&
@@ -214,19 +295,20 @@
}
*_out = in;
- return binder::Status::ok();
+ return Status::ok();
}
case os::Service::Tag::accessor: {
sp<IBinder> accessorBinder = in.get<os::Service::Tag::accessor>();
sp<IAccessor> accessor = interface_cast<IAccessor>(accessorBinder);
if (accessor == nullptr) {
ALOGE("Service#accessor doesn't have accessor. VM is maybe starting...");
- *_out = os::Service::make<os::Service::Tag::binder>(nullptr);
- return binder::Status::ok();
+ *_out = os::Service::make<os::Service::Tag::serviceWithMetadata>(
+ createServiceWithMetadata(nullptr, false));
+ return Status::ok();
}
auto request = [=] {
os::ParcelFileDescriptor fd;
- binder::Status ret = accessor->addConnection(&fd);
+ Status ret = accessor->addConnection(&fd);
if (ret.isOk()) {
return base::unique_fd(fd.release());
} else {
@@ -239,11 +321,12 @@
if (status != OK) {
ALOGE("Failed to set up preconnected binder RPC client: %s",
statusToString(status).c_str());
- return binder::Status::fromStatusT(status);
+ return Status::fromStatusT(status);
}
session->setSessionSpecificRoot(accessorBinder);
- *_out = os::Service::make<os::Service::Tag::binder>(session->getRootObject());
- return binder::Status::ok();
+ *_out = os::Service::make<os::Service::Tag::serviceWithMetadata>(
+ createServiceWithMetadata(session->getRootObject(), false));
+ return Status::ok();
}
default: {
LOG_ALWAYS_FATAL("Unknown service type: %d", in.getTag());
@@ -251,64 +334,159 @@
}
}
-binder::Status BackendUnifiedServiceManager::addService(const ::std::string& name,
- const sp<IBinder>& service,
- bool allowIsolated, int32_t dumpPriority) {
- return mTheRealServiceManager->addService(name, service, allowIsolated, dumpPriority);
+Status BackendUnifiedServiceManager::addService(const ::std::string& name,
+ const sp<IBinder>& service, bool allowIsolated,
+ int32_t dumpPriority) {
+ if (mTheRealServiceManager) {
+ Status status =
+ mTheRealServiceManager->addService(name, service, allowIsolated, dumpPriority);
+ // mEnableAddServiceCache is true by default.
+ if (kUseCacheInAddService && mEnableAddServiceCache && status.isOk()) {
+ return updateCache(name, service,
+ dumpPriority & android::os::IServiceManager::FLAG_IS_LAZY_SERVICE);
+ }
+ return status;
+ }
+ return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
+ kUnsupportedOpNoServiceManager);
}
-binder::Status BackendUnifiedServiceManager::listServices(
- int32_t dumpPriority, ::std::vector<::std::string>* _aidl_return) {
- return mTheRealServiceManager->listServices(dumpPriority, _aidl_return);
+Status BackendUnifiedServiceManager::listServices(int32_t dumpPriority,
+ ::std::vector<::std::string>* _aidl_return) {
+ Status status = Status::ok();
+ if (mTheRealServiceManager) {
+ status = mTheRealServiceManager->listServices(dumpPriority, _aidl_return);
+ }
+ if (!status.isOk()) return status;
+
+ appendInjectedAccessorServices(_aidl_return);
+
+ return status;
}
-binder::Status BackendUnifiedServiceManager::registerForNotifications(
+Status BackendUnifiedServiceManager::registerForNotifications(
const ::std::string& name, const sp<os::IServiceCallback>& callback) {
- return mTheRealServiceManager->registerForNotifications(name, callback);
+ if (mTheRealServiceManager) {
+ return mTheRealServiceManager->registerForNotifications(name, callback);
+ }
+ return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
+ kUnsupportedOpNoServiceManager);
}
-binder::Status BackendUnifiedServiceManager::unregisterForNotifications(
+Status BackendUnifiedServiceManager::unregisterForNotifications(
const ::std::string& name, const sp<os::IServiceCallback>& callback) {
- return mTheRealServiceManager->unregisterForNotifications(name, callback);
+ if (mTheRealServiceManager) {
+ return mTheRealServiceManager->unregisterForNotifications(name, callback);
+ }
+ return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
+ kUnsupportedOpNoServiceManager);
}
-binder::Status BackendUnifiedServiceManager::isDeclared(const ::std::string& name,
- bool* _aidl_return) {
- return mTheRealServiceManager->isDeclared(name, _aidl_return);
+Status BackendUnifiedServiceManager::isDeclared(const ::std::string& name, bool* _aidl_return) {
+ Status status = Status::ok();
+ if (mTheRealServiceManager) {
+ status = mTheRealServiceManager->isDeclared(name, _aidl_return);
+ }
+ if (!status.isOk()) return status;
+
+ if (!*_aidl_return) {
+ forEachInjectedAccessorService([&](const std::string& instance) {
+ if (name == instance) {
+ *_aidl_return = true;
+ }
+ });
+ }
+
+ return status;
}
-binder::Status BackendUnifiedServiceManager::getDeclaredInstances(
+Status BackendUnifiedServiceManager::getDeclaredInstances(
const ::std::string& iface, ::std::vector<::std::string>* _aidl_return) {
- return mTheRealServiceManager->getDeclaredInstances(iface, _aidl_return);
+ Status status = Status::ok();
+ if (mTheRealServiceManager) {
+ status = mTheRealServiceManager->getDeclaredInstances(iface, _aidl_return);
+ }
+ if (!status.isOk()) return status;
+
+ forEachInjectedAccessorService([&](const std::string& instance) {
+ // Declared instances have the format
+ // <interface>/instance like foo.bar.ISomething/instance
+ // If it does not have that format, consider the instance to be ""
+ std::string_view name(instance);
+ if (base::ConsumePrefix(&name, iface + "/")) {
+ _aidl_return->emplace_back(name);
+ } else if (iface == instance) {
+ _aidl_return->push_back("");
+ }
+ });
+
+ return status;
}
-binder::Status BackendUnifiedServiceManager::updatableViaApex(
+Status BackendUnifiedServiceManager::updatableViaApex(
const ::std::string& name, ::std::optional<::std::string>* _aidl_return) {
- return mTheRealServiceManager->updatableViaApex(name, _aidl_return);
+ if (mTheRealServiceManager) {
+ return mTheRealServiceManager->updatableViaApex(name, _aidl_return);
+ }
+ return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
+ kUnsupportedOpNoServiceManager);
}
-binder::Status BackendUnifiedServiceManager::getUpdatableNames(
- const ::std::string& apexName, ::std::vector<::std::string>* _aidl_return) {
- return mTheRealServiceManager->getUpdatableNames(apexName, _aidl_return);
+Status BackendUnifiedServiceManager::getUpdatableNames(const ::std::string& apexName,
+ ::std::vector<::std::string>* _aidl_return) {
+ if (mTheRealServiceManager) {
+ return mTheRealServiceManager->getUpdatableNames(apexName, _aidl_return);
+ }
+ return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
+ kUnsupportedOpNoServiceManager);
}
-binder::Status BackendUnifiedServiceManager::getConnectionInfo(
+Status BackendUnifiedServiceManager::getConnectionInfo(
const ::std::string& name, ::std::optional<os::ConnectionInfo>* _aidl_return) {
- return mTheRealServiceManager->getConnectionInfo(name, _aidl_return);
+ if (mTheRealServiceManager) {
+ return mTheRealServiceManager->getConnectionInfo(name, _aidl_return);
+ }
+ return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
+ kUnsupportedOpNoServiceManager);
}
-binder::Status BackendUnifiedServiceManager::registerClientCallback(
+Status BackendUnifiedServiceManager::registerClientCallback(
const ::std::string& name, const sp<IBinder>& service,
const sp<os::IClientCallback>& callback) {
- return mTheRealServiceManager->registerClientCallback(name, service, callback);
+ if (mTheRealServiceManager) {
+ return mTheRealServiceManager->registerClientCallback(name, service, callback);
+ }
+ return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
+ kUnsupportedOpNoServiceManager);
}
-binder::Status BackendUnifiedServiceManager::tryUnregisterService(const ::std::string& name,
- const sp<IBinder>& service) {
- return mTheRealServiceManager->tryUnregisterService(name, service);
+Status BackendUnifiedServiceManager::tryUnregisterService(const ::std::string& name,
+ const sp<IBinder>& service) {
+ if (mTheRealServiceManager) {
+ return mTheRealServiceManager->tryUnregisterService(name, service);
+ }
+ return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
+ kUnsupportedOpNoServiceManager);
}
-binder::Status BackendUnifiedServiceManager::getServiceDebugInfo(
+Status BackendUnifiedServiceManager::getServiceDebugInfo(
::std::vector<os::ServiceDebugInfo>* _aidl_return) {
- return mTheRealServiceManager->getServiceDebugInfo(_aidl_return);
+ if (mTheRealServiceManager) {
+ return mTheRealServiceManager->getServiceDebugInfo(_aidl_return);
+ }
+ return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
+ kUnsupportedOpNoServiceManager);
}
[[clang::no_destroy]] static std::once_flag gUSmOnce;
[[clang::no_destroy]] static sp<BackendUnifiedServiceManager> gUnifiedServiceManager;
+static bool hasOutOfProcessServiceManager() {
+#ifndef BINDER_WITH_KERNEL_IPC
+ return false;
+#else
+#if defined(__BIONIC__) && !defined(__ANDROID_VNDK__)
+ return android::base::GetBoolProperty("servicemanager.installed", true);
+#else
+ return true;
+#endif
+#endif // BINDER_WITH_KERNEL_IPC
+}
+
sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager() {
std::call_once(gUSmOnce, []() {
#if defined(__BIONIC__) && !defined(__ANDROID_VNDK__)
- /* wait for service manager */ {
+ /* wait for service manager */
+ if (hasOutOfProcessServiceManager()) {
using std::literals::chrono_literals::operator""s;
using android::base::WaitForProperty;
while (!WaitForProperty("servicemanager.ready", "true", 1s)) {
@@ -318,7 +496,7 @@
#endif
sp<AidlServiceManager> sm = nullptr;
- while (sm == nullptr) {
+ while (hasOutOfProcessServiceManager() && sm == nullptr) {
sm = interface_cast<AidlServiceManager>(
ProcessState::self()->getContextObject(nullptr));
if (sm == nullptr) {
diff --git a/libs/binder/BackendUnifiedServiceManager.h b/libs/binder/BackendUnifiedServiceManager.h
index 47b2ec9..c14f280 100644
--- a/libs/binder/BackendUnifiedServiceManager.h
+++ b/libs/binder/BackendUnifiedServiceManager.h
@@ -18,6 +18,7 @@
#include <android/os/BnServiceManager.h>
#include <android/os/IServiceManager.h>
#include <binder/IPCThreadState.h>
+#include <binder/Trace.h>
#include <map>
#include <memory>
@@ -59,6 +60,12 @@
}
bool removeItem(const std::string& key, const sp<IBinder>& who) {
+ std::string traceStr;
+ uint64_t tag = ATRACE_TAG_AIDL;
+ if (atrace_is_tag_enabled(tag)) {
+ traceStr = "BinderCacheWithInvalidation::removeItem " + key;
+ }
+ binder::ScopedTrace aidlTrace(tag, traceStr.c_str());
std::lock_guard<std::mutex> lock(mCacheMutex);
if (auto it = mCache.find(key); it != mCache.end()) {
if (it->second.service == who) {
@@ -81,14 +88,24 @@
if (item->localBinder() == nullptr) {
status_t status = item->linkToDeath(deathRecipient);
if (status != android::OK) {
+ std::string traceStr;
+ uint64_t tag = ATRACE_TAG_AIDL;
+ if (atrace_is_tag_enabled(tag)) {
+ traceStr =
+ "BinderCacheWithInvalidation::setItem Failed LinkToDeath for service " +
+ key + " : " + std::to_string(status);
+ }
+ binder::ScopedTrace aidlTrace(tag, traceStr.c_str());
+
ALOGE("Failed to linkToDeath binder for service %s. Error: %d", key.c_str(),
status);
return binder::Status::fromStatusT(status);
}
}
+ binder::ScopedTrace aidlTrace(ATRACE_TAG_AIDL,
+ "BinderCacheWithInvalidation::setItem Successfully Cached");
std::lock_guard<std::mutex> lock(mCacheMutex);
- Entry entry = {.service = item, .deathRecipient = deathRecipient};
- mCache[key] = entry;
+ mCache[key] = {.service = item, .deathRecipient = deathRecipient};
return binder::Status::ok();
}
@@ -103,10 +120,10 @@
public:
explicit BackendUnifiedServiceManager(const sp<os::IServiceManager>& impl);
- sp<os::IServiceManager> getImpl();
binder::Status getService(const ::std::string& name, sp<IBinder>* _aidl_return) override;
binder::Status getService2(const ::std::string& name, os::Service* out) override;
- binder::Status checkService(const ::std::string& name, os::Service* out) override;
+ binder::Status checkService(const ::std::string& name, sp<IBinder>* _aidl_return) override;
+ binder::Status checkService2(const ::std::string& name, os::Service* out) override;
binder::Status addService(const ::std::string& name, const sp<IBinder>& service,
bool allowIsolated, int32_t dumpPriority) override;
binder::Status listServices(int32_t dumpPriority,
@@ -130,22 +147,30 @@
const sp<IBinder>& service) override;
binder::Status getServiceDebugInfo(::std::vector<os::ServiceDebugInfo>* _aidl_return) override;
+ void enableAddServiceCache(bool value) { mEnableAddServiceCache = value; }
// for legacy ABI
const String16& getInterfaceDescriptor() const override {
return mTheRealServiceManager->getInterfaceDescriptor();
}
private:
+ bool mEnableAddServiceCache = true;
std::shared_ptr<BinderCacheWithInvalidation> mCacheForGetService;
sp<os::IServiceManager> mTheRealServiceManager;
binder::Status toBinderService(const ::std::string& name, const os::Service& in,
os::Service* _out);
binder::Status updateCache(const std::string& serviceName, const os::Service& service);
+ binder::Status updateCache(const std::string& serviceName, const sp<IBinder>& binder,
+ bool isLazyService);
bool returnIfCached(const std::string& serviceName, os::Service* _out);
};
sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager();
android::binder::Status getInjectedAccessor(const std::string& name, android::os::Service* service);
+void appendInjectedAccessorServices(std::vector<std::string>* list);
+// Do not call any other service manager APIs that might take the accessor
+// mutex because this will be holding it!
+void forEachInjectedAccessorService(const std::function<void(const std::string&)>& f);
} // namespace android
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 53bd08d..bc7ae37 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -38,6 +38,7 @@
#endif
#include "BuildFlags.h"
+#include "Constants.h"
#include "OS.h"
#include "RpcState.h"
@@ -70,8 +71,6 @@
constexpr bool kEnableRecording = false;
#endif
-// Log any reply transactions for which the data exceeds this size
-#define LOG_REPLIES_OVER_SIZE (300 * 1024)
// ---------------------------------------------------------------------------
IBinder::IBinder()
@@ -288,7 +287,7 @@
// for below objects
RpcMutex mLock;
std::set<sp<RpcServerLink>> mRpcServerLinks;
- BpBinder::ObjectManager mObjects;
+ BpBinder::ObjectManager mObjectMgr;
unique_fd mRecordingFd;
};
@@ -412,7 +411,7 @@
// In case this is being transacted on in the same process.
if (reply != nullptr) {
reply->setDataPosition(0);
- if (reply->dataSize() > LOG_REPLIES_OVER_SIZE) {
+ if (reply->dataSize() > binder::kLogTransactionsOverBytes) {
ALOGW("Large reply transaction of %zu bytes, interface descriptor %s, code %d",
reply->dataSize(), String8(getInterfaceDescriptor()).c_str(), code);
}
@@ -468,7 +467,7 @@
LOG_ALWAYS_FATAL_IF(!e, "no memory");
RpcMutexUniqueLock _l(e->mLock);
- return e->mObjects.attach(objectID, object, cleanupCookie, func);
+ return e->mObjectMgr.attach(objectID, object, cleanupCookie, func);
}
void* BBinder::findObject(const void* objectID) const
@@ -477,7 +476,7 @@
if (!e) return nullptr;
RpcMutexUniqueLock _l(e->mLock);
- return e->mObjects.find(objectID);
+ return e->mObjectMgr.find(objectID);
}
void* BBinder::detachObject(const void* objectID) {
@@ -485,7 +484,7 @@
if (!e) return nullptr;
RpcMutexUniqueLock _l(e->mLock);
- return e->mObjects.detach(objectID);
+ return e->mObjectMgr.detach(objectID);
}
void BBinder::withLock(const std::function<void()>& doWithLock) {
@@ -501,7 +500,7 @@
Extras* e = getOrCreateExtras();
LOG_ALWAYS_FATAL_IF(!e, "no memory");
RpcMutexUniqueLock _l(e->mLock);
- return e->mObjects.lookupOrCreateWeak(objectID, make, makeArgs);
+ return e->mObjectMgr.lookupOrCreateWeak(objectID, make, makeArgs);
}
BBinder* BBinder::localBinder()
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 3758b65..c13e0f9 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -28,6 +28,7 @@
#include <stdio.h>
#include "BuildFlags.h"
+#include "Constants.h"
#include "file.h"
//#undef ALOGV
@@ -63,9 +64,6 @@
static constexpr uint32_t kBinderProxyCountWarnInterval = 5000;
-// Log any transactions for which the data exceeds this size
-#define LOG_TRANSACTIONS_OVER_SIZE (300 * 1024)
-
enum {
LIMIT_REACHED_MASK = 0x80000000, // A flag denoting that the limit has been reached
WARNING_REACHED_MASK = 0x40000000, // A flag denoting that the warning has been reached
@@ -78,7 +76,16 @@
BpBinder::ObjectManager::~ObjectManager()
{
- kill();
+ const size_t N = mObjects.size();
+ ALOGV("Killing %zu objects in manager %p", N, this);
+ for (auto i : mObjects) {
+ const entry_t& e = i.second;
+ if (e.func != nullptr) {
+ e.func(i.first, e.object, e.cleanupCookie);
+ }
+ }
+
+ mObjects.clear();
}
void* BpBinder::ObjectManager::attach(const void* objectID, void* object, void* cleanupCookie,
@@ -144,20 +151,6 @@
return newObj;
}
-void BpBinder::ObjectManager::kill()
-{
- const size_t N = mObjects.size();
- ALOGV("Killing %zu objects in manager %p", N, this);
- for (auto i : mObjects) {
- const entry_t& e = i.second;
- if (e.func != nullptr) {
- e.func(i.first, e.object, e.cleanupCookie);
- }
- }
-
- mObjects.clear();
-}
-
// ---------------------------------------------------------------------------
sp<BpBinder> BpBinder::create(int32_t handle, std::function<void()>* postTask) {
@@ -408,9 +401,11 @@
status = IPCThreadState::self()->transact(binderHandle(), code, data, reply, flags);
}
- if (data.dataSize() > LOG_TRANSACTIONS_OVER_SIZE) {
+
+ if (data.dataSize() > binder::kLogTransactionsOverBytes) {
RpcMutexUniqueLock _l(mLock);
- ALOGW("Large outgoing transaction of %zu bytes, interface descriptor %s, code %d",
+ ALOGW("Large outgoing transaction of %zu bytes, interface descriptor %s, code %d was "
+ "sent",
data.dataSize(), String8(mDescriptorCache).c_str(), code);
}
@@ -697,19 +692,19 @@
void* BpBinder::attachObject(const void* objectID, void* object, void* cleanupCookie,
object_cleanup_func func) {
RpcMutexUniqueLock _l(mLock);
- ALOGV("Attaching object %p to binder %p (manager=%p)", object, this, &mObjects);
- return mObjects.attach(objectID, object, cleanupCookie, func);
+ ALOGV("Attaching object %p to binder %p (manager=%p)", object, this, &mObjectMgr);
+ return mObjectMgr.attach(objectID, object, cleanupCookie, func);
}
void* BpBinder::findObject(const void* objectID) const
{
RpcMutexUniqueLock _l(mLock);
- return mObjects.find(objectID);
+ return mObjectMgr.find(objectID);
}
void* BpBinder::detachObject(const void* objectID) {
RpcMutexUniqueLock _l(mLock);
- return mObjects.detach(objectID);
+ return mObjectMgr.detach(objectID);
}
void BpBinder::withLock(const std::function<void()>& doWithLock) {
@@ -720,7 +715,7 @@
sp<IBinder> BpBinder::lookupOrCreateWeak(const void* objectID, object_make_func make,
const void* makeArgs) {
RpcMutexUniqueLock _l(mLock);
- return mObjects.lookupOrCreateWeak(objectID, make, makeArgs);
+ return mObjectMgr.lookupOrCreateWeak(objectID, make, makeArgs);
}
BpBinder* BpBinder::remoteBinder()
diff --git a/libs/binder/Constants.h b/libs/binder/Constants.h
new file mode 100644
index 0000000..b75493c
--- /dev/null
+++ b/libs/binder/Constants.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2025 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
+
+namespace android::binder {
+
+/**
+ * See also BINDER_VM_SIZE. In kernel binder, the sum of all transactions must be allocated in this
+ * space. Large transactions are very error prone. In general, we should work to reduce this limit.
+ * The same limit is used in RPC binder for consistency.
+ */
+constexpr size_t kLogTransactionsOverBytes = 300 * 1024;
+
+/**
+ * See b/392575419 - this limit is chosen for a specific usecase, because RPC binder does not have
+ * support for shared memory in the Android Baklava timeframe. This was 100 KB during and before
+ * Android V.
+ *
+ * Keeping this low helps preserve overall system performance. Transactions of this size are far too
+ * expensive to make multiple copies over binder or sockets, and they should be avoided if at all
+ * possible and transition to shared memory.
+ */
+constexpr size_t kRpcTransactionLimitBytes = 600 * 1024;
+
+} // namespace android::binder
diff --git a/libs/binder/IActivityManager.cpp b/libs/binder/IActivityManager.cpp
index 152c815..83f4719 100644
--- a/libs/binder/IActivityManager.cpp
+++ b/libs/binder/IActivityManager.cpp
@@ -147,9 +147,11 @@
data.writeInterfaceToken(IActivityManager::getInterfaceDescriptor());
data.writeInt32(uid);
data.writeString16(callingPackage);
- remote()->transact(IS_UID_ACTIVE_TRANSACTION, data, &reply);
+ status_t err = remote()->transact(IS_UID_ACTIVE_TRANSACTION, data, &reply);
// fail on exception
- if (reply.readExceptionCode() != 0) return false;
+ if (err != NO_ERROR || ((err = reply.readExceptionCode()) != NO_ERROR)) {
+ return false;
+ }
return reply.readInt32() == 1;
}
@@ -159,9 +161,9 @@
data.writeInterfaceToken(IActivityManager::getInterfaceDescriptor());
data.writeInt32(uid);
data.writeString16(callingPackage);
- remote()->transact(GET_UID_PROCESS_STATE_TRANSACTION, data, &reply);
+ status_t err = remote()->transact(GET_UID_PROCESS_STATE_TRANSACTION, data, &reply);
// fail on exception
- if (reply.readExceptionCode() != 0) {
+ if (err != NO_ERROR || ((err = reply.readExceptionCode()) != NO_ERROR)) {
return ActivityManager::PROCESS_STATE_UNKNOWN;
}
return reply.readInt32();
@@ -192,7 +194,7 @@
data.writeInt32(appPid);
status_t err = remote()->transact(LOG_FGS_API_BEGIN_TRANSACTION, data, &reply,
IBinder::FLAG_ONEWAY);
- if (err != NO_ERROR || ((err = reply.readExceptionCode()) != NO_ERROR)) {
+ if (err != NO_ERROR) {
ALOGD("%s: FGS Logger Transaction failed, %d", __func__, err);
return err;
}
@@ -207,7 +209,7 @@
data.writeInt32(appPid);
status_t err =
remote()->transact(LOG_FGS_API_END_TRANSACTION, data, &reply, IBinder::FLAG_ONEWAY);
- if (err != NO_ERROR || ((err = reply.readExceptionCode()) != NO_ERROR)) {
+ if (err != NO_ERROR) {
ALOGD("%s: FGS Logger Transaction failed, %d", __func__, err);
return err;
}
@@ -224,7 +226,7 @@
data.writeInt32(appPid);
status_t err = remote()->transact(LOG_FGS_API_STATE_CHANGED_TRANSACTION, data, &reply,
IBinder::FLAG_ONEWAY);
- if (err != NO_ERROR || ((err = reply.readExceptionCode()) != NO_ERROR)) {
+ if (err != NO_ERROR) {
ALOGD("%s: FGS Logger Transaction failed, %d", __func__, err);
return err;
}
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index c6b0cb7..bb03e89 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -330,8 +330,8 @@
if (err != NO_ERROR || // failed transaction
size != size64 || offset != offset64) { // ILP32 size check
ALOGE("binder=%p transaction failed fd=%d, size=%zu, err=%d (%s)",
- IInterface::asBinder(this).get(),
- parcel_fd, size, err, strerror(-err));
+ IInterface::asBinder(this).get(), parcel_fd, size, err,
+ statusToString(err).c_str());
return;
}
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 6698d0c..1c1b6f3 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -38,6 +38,10 @@
#include "Utils.h"
#include "binder_module.h"
+#if (defined(__ANDROID__) || defined(__Fuchsia__)) && !defined(BINDER_WITH_KERNEL_IPC)
+#error Android and Fuchsia are expected to have BINDER_WITH_KERNEL_IPC
+#endif
+
#if LOG_NDEBUG
#define IF_LOG_TRANSACTIONS() if (false)
@@ -626,12 +630,22 @@
{
if (mProcess->mDriverFD < 0)
return;
- talkWithDriver(false);
+
+ if (status_t res = talkWithDriver(false); res != OK) {
+ // TODO: we may want to abort for some of these cases
+ ALOGW("1st call to talkWithDriver returned error in flushCommands: %s",
+ statusToString(res).c_str());
+ }
+
// The flush could have caused post-write refcount decrements to have
// been executed, which in turn could result in BC_RELEASE/BC_DECREFS
// being queued in mOut. So flush again, if we need to.
if (mOut.dataSize() > 0) {
- talkWithDriver(false);
+ if (status_t res = talkWithDriver(false); res != OK) {
+ // TODO: we may want to abort for some of these cases
+ ALOGW("2nd call to talkWithDriver returned error in flushCommands: %s",
+ statusToString(res).c_str());
+ }
}
if (mOut.dataSize() > 0) {
ALOGW("mOut.dataSize() > 0 after flushCommands()");
@@ -775,6 +789,7 @@
{
LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(),
getpid());
+ mProcess->checkExpectingThreadPoolStart();
mProcess->mCurrentThreads++;
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
@@ -802,7 +817,11 @@
mOut.writeInt32(BC_EXIT_LOOPER);
mIsLooper = false;
- talkWithDriver(false);
+ if (status_t res = talkWithDriver(false); res != OK) {
+ // TODO: we may want to abort for some of these cases
+ ALOGW("call to talkWithDriver in joinThreadPool returned error: %s, FD: %d",
+ statusToString(res).c_str(), mProcess->mDriverFD);
+ }
size_t oldCount = mProcess->mCurrentThreads.fetch_sub(1);
LOG_ALWAYS_FATAL_IF(oldCount == 0,
"Threadpool thread count underflowed. Thread cannot exist and exit in "
@@ -839,7 +858,7 @@
void IPCThreadState::stopProcess(bool /*immediate*/)
{
//ALOGI("**** STOPPING PROCESS");
- flushCommands();
+ (void)flushCommands();
int fd = mProcess->mDriverFD;
mProcess->mDriverFD = -1;
close(fd);
@@ -1214,7 +1233,7 @@
std::string message = logStream.str();
ALOGI("%s", message.c_str());
}
-#if defined(__ANDROID__)
+#if defined(BINDER_WITH_KERNEL_IPC)
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
else
@@ -1493,7 +1512,14 @@
buffer.setDataSize(0);
constexpr uint32_t kForwardReplyFlags = TF_CLEAR_BUF;
- sendReply(reply, (tr.flags & kForwardReplyFlags));
+
+ // TODO: we may want to abort if there is an error here, or return as 'error'
+ // from this function, but the impact needs to be measured
+ status_t error2 = sendReply(reply, (tr.flags & kForwardReplyFlags));
+ if (error2 != OK) {
+ ALOGE("error in sendReply for synchronous call: %s",
+ statusToString(error2).c_str());
+ }
} else {
if (error != OK) {
std::ostringstream logStream;
@@ -1603,7 +1629,7 @@
IPCThreadState* const self = static_cast<IPCThreadState*>(st);
if (self) {
self->flushCommands();
-#if defined(__ANDROID__)
+#if defined(BINDER_WITH_KERNEL_IPC)
if (self->mProcess->mDriverFD >= 0) {
ioctl(self->mProcess->mDriverFD, BINDER_THREAD_EXIT, 0);
}
@@ -1619,7 +1645,7 @@
binder_frozen_status_info info = {};
info.pid = pid;
-#if defined(__ANDROID__)
+#if defined(BINDER_WITH_KERNEL_IPC)
if (ioctl(self()->mProcess->mDriverFD, BINDER_GET_FROZEN_INFO, &info) < 0)
ret = -errno;
#endif
@@ -1638,7 +1664,7 @@
info.timeout_ms = timeout_ms;
-#if defined(__ANDROID__)
+#if defined(BINDER_WITH_KERNEL_IPC)
if (ioctl(self()->mProcess->mDriverFD, BINDER_FREEZE, &info) < 0)
ret = -errno;
#endif
@@ -1656,7 +1682,7 @@
if (!ProcessState::isDriverFeatureEnabled(ProcessState::DriverFeature::EXTENDED_ERROR))
return;
-#if defined(__ANDROID__)
+#if defined(BINDER_WITH_KERNEL_IPC)
if (ioctl(self()->mProcess->mDriverFD, BINDER_GET_EXTENDED_ERROR, &ee) < 0) {
ALOGE("Failed to get extended error: %s", strerror(errno));
return;
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 32388db..c9ca646 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -43,7 +43,11 @@
#include <binder/IPermissionController.h>
#endif
-#ifdef __ANDROID__
+#if !(defined(__ANDROID__) || defined(__FUCHSIA))
+#define BINDER_SERVICEMANAGEMENT_DELEGATION_SUPPORT
+#endif
+
+#if !defined(BINDER_SERVICEMANAGEMENT_DELEGATION_SUPPORT)
#include <cutils/properties.h>
#else
#include "ServiceManagerHost.h"
@@ -127,6 +131,8 @@
}
IBinder* onAsBinder() override { return IInterface::asBinder(mUnifiedServiceManager).get(); }
+ void enableAddServiceCache(bool value) { mUnifiedServiceManager->enableAddServiceCache(value); }
+
protected:
sp<BackendUnifiedServiceManager> mUnifiedServiceManager;
// AidlRegistrationCallback -> services that its been registered for
@@ -150,7 +156,8 @@
virtual Status realGetService(const std::string& name, sp<IBinder>* _aidl_return) {
Service service;
Status status = mUnifiedServiceManager->getService2(name, &service);
- *_aidl_return = service.get<Service::Tag::binder>();
+ auto serviceWithMetadata = service.get<Service::Tag::serviceWithMetadata>();
+ *_aidl_return = serviceWithMetadata.service;
return status;
}
};
@@ -301,6 +308,25 @@
return android::binder::Status::ok();
}
+void appendInjectedAccessorServices(std::vector<std::string>* list) {
+ LOG_ALWAYS_FATAL_IF(list == nullptr,
+ "Attempted to get list of services from Accessors with nullptr");
+ std::lock_guard<std::mutex> lock(gAccessorProvidersMutex);
+ for (const auto& entry : gAccessorProviders) {
+ list->insert(list->end(), entry.mProvider->instances().begin(),
+ entry.mProvider->instances().end());
+ }
+}
+
+void forEachInjectedAccessorService(const std::function<void(const std::string&)>& f) {
+ std::lock_guard<std::mutex> lock(gAccessorProvidersMutex);
+ for (const auto& entry : gAccessorProviders) {
+ for (const auto& instance : entry.mProvider->instances()) {
+ f(instance);
+ }
+ }
+}
+
sp<IServiceManager> defaultServiceManager()
{
std::call_once(gSmOnce, []() {
@@ -561,8 +587,9 @@
sp<IBinder> svc = checkService(name);
if (svc != nullptr) return svc;
+ sp<ProcessState> self = ProcessState::selfOrNull();
const bool isVendorService =
- strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0;
+ self && strcmp(self->getDriverName().c_str(), "/dev/vndbinder") == 0;
constexpr auto timeout = 5s;
const auto startTime = std::chrono::steady_clock::now();
// Vendor code can't access system properties
@@ -579,7 +606,7 @@
const useconds_t sleepTime = gSystemBootCompleted ? 1000 : 100;
ALOGI("Waiting for service '%s' on '%s'...", String8(name).c_str(),
- ProcessState::self()->getDriverName().c_str());
+ self ? self->getDriverName().c_str() : "RPC accessors only");
int n = 0;
while (std::chrono::steady_clock::now() - startTime < timeout) {
@@ -601,10 +628,10 @@
sp<IBinder> CppBackendShim::checkService(const String16& name) const {
Service ret;
- if (!mUnifiedServiceManager->checkService(String8(name).c_str(), &ret).isOk()) {
+ if (!mUnifiedServiceManager->checkService2(String8(name).c_str(), &ret).isOk()) {
return nullptr;
}
- return ret.get<Service::Tag::binder>();
+ return ret.get<Service::Tag::serviceWithMetadata>().service;
}
status_t CppBackendShim::addService(const String16& name, const sp<IBinder>& service,
@@ -661,7 +688,8 @@
if (Status status = realGetService(name, &out); !status.isOk()) {
ALOGW("Failed to getService in waitForService for %s: %s", name.c_str(),
status.toString8().c_str());
- if (0 == ProcessState::self()->getThreadPoolMaxTotalThreadCount()) {
+ sp<ProcessState> self = ProcessState::selfOrNull();
+ if (self && 0 == self->getThreadPoolMaxTotalThreadCount()) {
ALOGW("Got service, but may be racey because we could not wait efficiently for it. "
"Threadpool has 0 guaranteed threads. "
"Is the threadpool configured properly? "
@@ -695,9 +723,10 @@
if (waiter->mBinder != nullptr) return waiter->mBinder;
}
+ sp<ProcessState> self = ProcessState::selfOrNull();
ALOGW("Waited one second for %s (is service started? Number of threads started in the "
"threadpool: %zu. Are binder threads started and available?)",
- name.c_str(), ProcessState::self()->getThreadPoolMaxTotalThreadCount());
+ name.c_str(), self ? self->getThreadPoolMaxTotalThreadCount() : 0);
// Handle race condition for lazy services. Here is what can happen:
// - the service dies (not processed by init yet).
@@ -877,7 +906,7 @@
return ret;
}
-#ifndef __ANDROID__
+#if defined(BINDER_SERVICEMANAGEMENT_DELEGATION_SUPPORT)
// CppBackendShim for host. Implements the old libbinder android::IServiceManager API.
// The internal implementation of the AIDL interface android::os::IServiceManager calls into
// on-device service manager.
diff --git a/libs/binder/LazyServiceRegistrar.cpp b/libs/binder/LazyServiceRegistrar.cpp
index 0f0af0b..27cfe0c 100644
--- a/libs/binder/LazyServiceRegistrar.cpp
+++ b/libs/binder/LazyServiceRegistrar.cpp
@@ -19,7 +19,6 @@
#include <android/os/BnClientCallback.h>
#include <android/os/IServiceManager.h>
#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
#include <binder/LazyServiceRegistrar.h>
namespace android {
@@ -134,6 +133,12 @@
std::string regStr = (reRegister) ? "Re-registering" : "Registering";
ALOGI("%s service %s", regStr.c_str(), name.c_str());
+ if (dumpFlags & android::os::IServiceManager::FLAG_IS_LAZY_SERVICE) {
+ ALOGW("FLAG_IS_LAZY_SERVICE flag already set. This should only be set by "
+ "ClientCounterCallbackImpl in LazyServiceRegistrar");
+ }
+ dumpFlags |= android::os::IServiceManager::FLAG_IS_LAZY_SERVICE;
+
if (Status status = manager->addService(name.c_str(), service, allowIsolated, dumpFlags);
!status.isOk()) {
ALOGE("Failed to register service %s (%s)", name.c_str(), status.toString8().c_str());
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 18c4134..777c22a 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -156,7 +156,7 @@
#ifdef BINDER_WITH_KERNEL_IPC
static void acquire_object(const sp<ProcessState>& proc, const flat_binder_object& obj,
- const void* who) {
+ const void* who, bool tagFds) {
switch (obj.hdr.type) {
case BINDER_TYPE_BINDER:
if (obj.binder) {
@@ -173,7 +173,7 @@
return;
}
case BINDER_TYPE_FD: {
- if (obj.cookie != 0) { // owned
+ if (tagFds && obj.cookie != 0) { // owned
FdTag(obj.handle, nullptr, who);
}
return;
@@ -299,8 +299,13 @@
obj.handle = handle;
obj.cookie = 0;
} else {
+#if __linux__
int policy = local->getMinSchedulerPolicy();
int priority = local->getMinSchedulerPriority();
+#else
+ int policy = 0;
+ int priority = 0;
+#endif
if (policy != 0 || priority != 0) {
// override value, since it is set explicitly
@@ -611,11 +616,12 @@
}
}
- acquire_object(proc, *flat, this);
+ acquire_object(proc, *flat, this, true /*tagFds*/);
}
}
#else
LOG_ALWAYS_FATAL("Binder kernel driver disabled at build time");
+ (void)kernelFields;
return INVALID_OPERATION;
#endif // BINDER_WITH_KERNEL_IPC
} else {
@@ -668,7 +674,8 @@
// FD was unowned in the source parcel.
int newFd = -1;
if (status_t status = binder::os::dupFileDescriptor(oldFd, &newFd); status != OK) {
- ALOGW("Failed to duplicate file descriptor %d: %s", oldFd, strerror(-status));
+ ALOGW("Failed to duplicate file descriptor %d: %s", oldFd,
+ statusToString(status).c_str());
}
rpcFields->mFds->emplace_back(unique_fd(newFd));
// Fixup the index in the data.
@@ -796,6 +803,7 @@
setDataPosition(initPosition);
#else
LOG_ALWAYS_FATAL("Binder kernel driver disabled at build time");
+ (void)kernelFields;
#endif
} else if (const auto* rpcFields = maybeRpcFields(); rpcFields && rpcFields->mFds) {
for (const auto& fd : *rpcFields->mFds) {
@@ -838,9 +846,10 @@
}
#else
LOG_ALWAYS_FATAL("Binder kernel driver disabled at build time");
+ (void)kernelFields;
return INVALID_OPERATION;
#endif // BINDER_WITH_KERNEL_IPC
- } else if (const auto* rpcFields = maybeRpcFields()) {
+ } else if (maybeRpcFields()) {
return INVALID_OPERATION;
}
return NO_ERROR;
@@ -878,6 +887,7 @@
}
#else
LOG_ALWAYS_FATAL("Binder kernel driver disabled at build time");
+ (void)kernelFields;
return INVALID_OPERATION;
#endif // BINDER_WITH_KERNEL_IPC
} else if (const auto* rpcFields = maybeRpcFields()) {
@@ -970,6 +980,7 @@
writeInt32(kHeader);
#else // BINDER_WITH_KERNEL_IPC
LOG_ALWAYS_FATAL("Binder kernel driver disabled at build time");
+ (void)kernelFields;
return INVALID_OPERATION;
#endif // BINDER_WITH_KERNEL_IPC
}
@@ -1060,6 +1071,7 @@
#else // BINDER_WITH_KERNEL_IPC
LOG_ALWAYS_FATAL("Binder kernel driver disabled at build time");
(void)threadState;
+ (void)kernelFields;
return false;
#endif // BINDER_WITH_KERNEL_IPC
}
@@ -1292,10 +1304,6 @@
status_t Parcel::writeUniqueFileDescriptorVector(const std::optional<std::vector<unique_fd>>& val) {
return writeData(val);
}
-status_t Parcel::writeUniqueFileDescriptorVector(
- const std::unique_ptr<std::vector<unique_fd>>& val) {
- return writeData(val);
-}
status_t Parcel::writeStrongBinderVector(const std::vector<sp<IBinder>>& val) { return writeData(val); }
status_t Parcel::writeStrongBinderVector(const std::optional<std::vector<sp<IBinder>>>& val) { return writeData(val); }
@@ -1351,10 +1359,6 @@
status_t Parcel::readUniqueFileDescriptorVector(std::optional<std::vector<unique_fd>>* val) const {
return readData(val);
}
-status_t Parcel::readUniqueFileDescriptorVector(
- std::unique_ptr<std::vector<unique_fd>>* val) const {
- return readData(val);
-}
status_t Parcel::readUniqueFileDescriptorVector(std::vector<unique_fd>* val) const {
return readData(val);
}
@@ -1796,13 +1800,22 @@
// Need to write meta-data?
if (nullMetaData || val.binder != 0) {
kernelFields->mObjects[kernelFields->mObjectsSize] = mDataPos;
- acquire_object(ProcessState::self(), val, this);
+ acquire_object(ProcessState::self(), val, this, true /*tagFds*/);
kernelFields->mObjectsSize++;
}
return finishWrite(sizeof(flat_binder_object));
}
+ if (mOwner) {
+ // continueWrite does have the logic to convert this from an
+ // owned to an unowned Parcel. However, this is pretty inefficient,
+ // and it's really strange to need to do so, so prefer to avoid
+ // these paths than try to support them.
+ ALOGE("writing objects not supported on owned Parcels");
+ return PERMISSION_DENIED;
+ }
+
if (!enoughData) {
const status_t err = growData(sizeof(val));
if (err != NO_ERROR) return err;
@@ -2222,9 +2235,7 @@
const char* eos = reinterpret_cast<const char*>(memchr(str, 0, avail));
if (eos) {
const size_t len = eos - str;
- mDataPos += pad_size(len+1);
- ALOGV("readCString Setting data pos of %p to %zu", this, mDataPos);
- return str;
+ return static_cast<const char*>(readInplace(len + 1));
}
}
return nullptr;
@@ -2688,6 +2699,7 @@
#else // BINDER_WITH_KERNEL_IPC
(void)newObjectsSize;
LOG_ALWAYS_FATAL("Binder kernel driver disabled at build time");
+ (void)kernelFields;
#endif // BINDER_WITH_KERNEL_IPC
} else if (auto* rpcFields = maybeRpcFields()) {
rpcFields->mFds.reset();
@@ -2720,6 +2732,65 @@
return 0;
}
+static void do_nothing_release_func(const uint8_t* data, size_t dataSize,
+ const binder_size_t* objects, size_t objectsCount) {
+ (void)data;
+ (void)dataSize;
+ (void)objects;
+ (void)objectsCount;
+}
+static void delete_data_release_func(const uint8_t* data, size_t dataSize,
+ const binder_size_t* objects, size_t objectsCount) {
+ delete[] data;
+ (void)dataSize;
+ (void)objects;
+ (void)objectsCount;
+}
+
+void Parcel::makeDangerousViewOf(Parcel* p) {
+ if (p->isForRpc()) {
+ // warning: this must match the logic in rpcSetDataReference
+ auto* rf = p->maybeRpcFields();
+ LOG_ALWAYS_FATAL_IF(rf == nullptr);
+ std::vector<std::variant<binder::unique_fd, binder::borrowed_fd>> fds;
+ if (rf->mFds) {
+ fds.reserve(rf->mFds->size());
+ for (const auto& fd : *rf->mFds) {
+ fds.push_back(binder::borrowed_fd(toRawFd(fd)));
+ }
+ }
+ status_t result =
+ rpcSetDataReference(rf->mSession, p->mData, p->mDataSize,
+ rf->mObjectPositions.data(), rf->mObjectPositions.size(),
+ std::move(fds), do_nothing_release_func);
+ LOG_ALWAYS_FATAL_IF(result != OK, "Failed: %s", statusToString(result).c_str());
+ } else {
+#ifdef BINDER_WITH_KERNEL_IPC
+ // warning: this must match the logic in ipcSetDataReference
+ auto* kf = p->maybeKernelFields();
+ LOG_ALWAYS_FATAL_IF(kf == nullptr);
+
+ // Ownership of FDs is passed to the Parcel from kernel binder. This should be refactored
+ // to move this ownership out of Parcel and into release_func. However, today, Parcel
+ // always assums it can own and close FDs today. So, for purposes of testing consistency,
+ // , create new FDs it can own.
+
+ uint8_t* newData = new uint8_t[p->mDataSize]; // deleted by delete_data_release_func
+ memcpy(newData, p->mData, p->mDataSize);
+ for (size_t i = 0; i < kf->mObjectsSize; i++) {
+ flat_binder_object* flat =
+ reinterpret_cast<flat_binder_object*>(newData + kf->mObjects[i]);
+ if (flat->hdr.type == BINDER_TYPE_FD) {
+ flat->handle = fcntl(flat->handle, F_DUPFD_CLOEXEC, 0);
+ }
+ }
+
+ ipcSetDataReference(newData, p->mDataSize, kf->mObjects, kf->mObjectsSize,
+ delete_data_release_func);
+#endif // BINDER_WITH_KERNEL_IPC
+ }
+}
+
void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize, const binder_size_t* objects,
size_t objectsCount, release_func relFunc) {
// this code uses 'mOwner == nullptr' to understand whether it owns memory
@@ -2730,6 +2801,7 @@
auto* kernelFields = maybeKernelFields();
LOG_ALWAYS_FATAL_IF(kernelFields == nullptr); // guaranteed by freeData.
+ // must match makeDangerousViewOf
mData = const_cast<uint8_t*>(data);
mDataSize = mDataCapacity = dataSize;
kernelFields->mObjects = const_cast<binder_size_t*>(objects);
@@ -2808,6 +2880,7 @@
auto* rpcFields = maybeRpcFields();
LOG_ALWAYS_FATAL_IF(rpcFields == nullptr); // guaranteed by markForRpc.
+ // must match makeDangerousViewOf
mData = const_cast<uint8_t*>(data);
mDataSize = mDataCapacity = dataSize;
mOwner = relFunc;
@@ -2875,15 +2948,17 @@
#endif // BINDER_WITH_KERNEL_IPC
}
-void Parcel::acquireObjects()
-{
+void Parcel::reacquireObjects(size_t objectsSize) {
auto* kernelFields = maybeKernelFields();
if (kernelFields == nullptr) {
return;
}
#ifdef BINDER_WITH_KERNEL_IPC
- size_t i = kernelFields->mObjectsSize;
+ LOG_ALWAYS_FATAL_IF(objectsSize > kernelFields->mObjectsSize,
+ "Object size %zu out of range of %zu", objectsSize,
+ kernelFields->mObjectsSize);
+ size_t i = objectsSize;
if (i == 0) {
return;
}
@@ -2893,8 +2968,10 @@
while (i > 0) {
i--;
const flat_binder_object* flat = reinterpret_cast<flat_binder_object*>(data + objects[i]);
- acquire_object(proc, *flat, this);
+ acquire_object(proc, *flat, this, false /*tagFds*/); // they are already tagged
}
+#else
+ (void) objectsSize;
#endif // BINDER_WITH_KERNEL_IPC
}
@@ -3111,12 +3188,8 @@
return NO_MEMORY;
}
- // Little hack to only acquire references on objects
- // we will be keeping.
- size_t oldObjectsSize = kernelFields->mObjectsSize;
- kernelFields->mObjectsSize = objectsSize;
- acquireObjects();
- kernelFields->mObjectsSize = oldObjectsSize;
+ // only acquire references on objects we are keeping
+ reacquireObjects(objectsSize);
}
if (rpcFields) {
if (status_t status = truncateRpcObjects(objectsSize); status != OK) {
@@ -3328,14 +3401,6 @@
}
#ifdef BINDER_WITH_KERNEL_IPC
-size_t Parcel::getBlobAshmemSize() const
-{
- // This used to return the size of all blobs that were written to ashmem, now we're returning
- // the ashmem currently referenced by this Parcel, which should be equivalent.
- // TODO(b/202029388): Remove method once ABI can be changed.
- return getOpenAshmemSize();
-}
-
size_t Parcel::getOpenAshmemSize() const
{
auto* kernelFields = maybeKernelFields();
diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp
index abb6612..99f9726 100644
--- a/libs/binder/PersistableBundle.cpp
+++ b/libs/binder/PersistableBundle.cpp
@@ -119,6 +119,9 @@
}
RETURN_IF_FAILED(parcel->writeInt32(static_cast<int32_t>(length)));
parcel->setDataPosition(end_pos);
+ // write mHasIntent to be consistent with BaseBundle.writeToBundle. But it would always be
+ // false since PersistableBundle won't contain an intent.
+ RETURN_IF_FAILED(parcel->writeBool(false));
return NO_ERROR;
}
@@ -473,6 +476,8 @@
}
}
}
+ // result intentional ignored since it will always be false;
+ RETURN_IF_FAILED(parcel->readBool());
return NO_ERROR;
}
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 5e7f151..0bec379 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -48,6 +48,10 @@
#define DEFAULT_MAX_BINDER_THREADS 15
#define DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION 1
+#if defined(__ANDROID__) || defined(__Fuchsia__)
+#define EXPECT_BINDER_OPEN_SUCCESS
+#endif
+
#ifdef __ANDROID_VNDK__
const char* kDefaultDriver = "/dev/vndbinder";
#else
@@ -501,6 +505,21 @@
return mThreadPoolStarted;
}
+void ProcessState::checkExpectingThreadPoolStart() const {
+ if (mThreadPoolStarted) return;
+
+ // this is also racey, but you should setup the threadpool in the main thread. If that is an
+ // issue, we can check if we are the process leader, but haven't seen the issue in practice.
+ size_t requestedThreads = mMaxThreads.load();
+
+ // if it's manually set to the default, we do ignore it here...
+ if (requestedThreads == DEFAULT_MAX_BINDER_THREADS) return;
+ if (requestedThreads == 0) return;
+
+ ALOGW("Thread pool configuration of size %zu requested, but startThreadPool was not called.",
+ requestedThreads);
+}
+
#define DRIVER_FEATURES_PATH "/dev/binderfs/features/"
bool ProcessState::isDriverFeatureEnabled(const DriverFeature feature) {
// Use static variable to cache the results.
@@ -598,7 +617,7 @@
}
}
-#ifdef __ANDROID__
+#if defined(EXPECT_BINDER_OPEN_SUCCESS)
LOG_ALWAYS_FATAL_IF(!opened.ok(),
"Binder driver '%s' could not be opened. Error: %s. Terminating.",
driver, error.c_str());
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index b8742af..c7851dc 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -503,7 +503,7 @@
auto status = binder::os::getRandomBytes(sessionId.data(), sessionId.size());
if (status != OK) {
- ALOGE("Failed to read random session ID: %s", strerror(-status));
+ ALOGE("Failed to read random session ID: %s", statusToString(status).c_str());
return;
}
} while (server->mSessions.end() != server->mSessions.find(sessionId));
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index cd21a91..16023ff 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -164,7 +164,7 @@
status_t status = mBootstrapTransport->interruptableWriteFully(mShutdownTrigger.get(), &iov,
1, std::nullopt, &fds);
if (status != OK) {
- ALOGE("Failed to send fd over bootstrap transport: %s", strerror(-status));
+ ALOGE("Failed to send fd over bootstrap transport: %s", statusToString(status).c_str());
return status;
}
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index fe6e1a3..03d974d 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -23,6 +23,7 @@
#include <binder/IPCThreadState.h>
#include <binder/RpcServer.h>
+#include "Constants.h"
#include "Debug.h"
#include "RpcWireFormat.h"
#include "Utils.h"
@@ -337,6 +338,8 @@
}
RpcState::CommandData::CommandData(size_t size) : mSize(size) {
+ if (size == 0) return;
+
// The maximum size for regular binder is 1MB for all concurrent
// transactions. A very small proportion of transactions are even
// larger than a page, but we need to avoid allocating too much
@@ -348,11 +351,11 @@
// transaction (in some cases, additional fixed size amounts are added),
// though for rough consistency, we should avoid cases where this data type
// is used for multiple dynamic allocations for a single transaction.
- constexpr size_t kMaxTransactionAllocation = 100 * 1000;
- if (size == 0) return;
- if (size > kMaxTransactionAllocation) {
- ALOGW("Transaction requested too much data allocation %zu", size);
+ if (size > binder::kRpcTransactionLimitBytes) {
+ ALOGE("Transaction requested too much data allocation: %zu bytes, failing.", size);
return;
+ } else if (size > binder::kLogTransactionsOverBytes) {
+ ALOGW("Transaction too large: inefficient and in danger of breaking: %zu bytes.", size);
}
mData.reset(new (std::nothrow) uint8_t[size]);
}
diff --git a/libs/binder/RpcTransportTipcAndroid.cpp b/libs/binder/RpcTransportTipcAndroid.cpp
index 3819fb6..14c0bde 100644
--- a/libs/binder/RpcTransportTipcAndroid.cpp
+++ b/libs/binder/RpcTransportTipcAndroid.cpp
@@ -21,6 +21,7 @@
#include <log/log.h>
#include <poll.h>
#include <trusty/tipc.h>
+#include <type_traits>
#include "FdTrigger.h"
#include "RpcState.h"
@@ -32,6 +33,9 @@
namespace android {
+// Corresponds to IPC_MAX_MSG_HANDLES in the Trusty kernel
+constexpr size_t kMaxTipcHandles = 8;
+
// RpcTransport for writing Trusty IPC clients in Android.
class RpcTransportTipcAndroid : public RpcTransport {
public:
@@ -78,12 +82,28 @@
FdTrigger* fdTrigger, iovec* iovs, int niovs,
const std::optional<SmallFunction<status_t()>>& altPoll,
const std::vector<std::variant<unique_fd, borrowed_fd>>* ancillaryFds) override {
+ bool sentFds = false;
auto writeFn = [&](iovec* iovs, size_t niovs) -> ssize_t {
- // TODO: send ancillaryFds. For now, we just abort if anyone tries
- // to send any.
- LOG_ALWAYS_FATAL_IF(ancillaryFds != nullptr && !ancillaryFds->empty(),
- "File descriptors are not supported on Trusty yet");
- return TEMP_FAILURE_RETRY(tipc_send(mSocket.fd.get(), iovs, niovs, nullptr, 0));
+ trusty_shm shms[kMaxTipcHandles] = {{0}};
+ ssize_t shm_count = 0;
+
+ if (!sentFds && ancillaryFds != nullptr && !ancillaryFds->empty()) {
+ if (ancillaryFds->size() > kMaxTipcHandles) {
+ ALOGE("Too many file descriptors for TIPC: %zu", ancillaryFds->size());
+ errno = EINVAL;
+ return -1;
+ }
+ for (const auto& fdVariant : *ancillaryFds) {
+ shms[shm_count++] = {std::visit([](const auto& fd) { return fd.get(); },
+ fdVariant),
+ TRUSTY_SEND_SECURE_OR_SHARE};
+ }
+ }
+
+ auto ret = TEMP_FAILURE_RETRY(tipc_send(mSocket.fd.get(), iovs, niovs,
+ (shm_count == 0) ? nullptr : shms, shm_count));
+ sentFds |= ret >= 0;
+ return ret;
};
status_t status = interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, writeFn,
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index ab44957..4332f8a 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -37,6 +37,9 @@
"name": "binderStabilityTest"
},
{
+ "name": "binderStabilityIntegrationTest"
+ },
+ {
"name": "binderRpcWireProtocolTest"
},
{
@@ -67,15 +70,10 @@
"name": "fuzz_service_test"
},
{
- "name": "CtsOsTestCases",
- "options": [
- {
- "include-filter": "android.os.cts.BinderTest"
- },
- {
- "include-filter": "android.os.cts.ParcelTest"
- }
- ]
+ "name": "CtsOsTestCases_ParcelAndBinderTests"
+ },
+ {
+ "name": "FrameworksCoreTests_all_binder"
},
{
"name": "libbinder_rs-internal_test"
diff --git a/libs/binder/aidl/android/content/pm/OWNERS b/libs/binder/aidl/android/content/pm/OWNERS
index 3100518..2617a16 100644
--- a/libs/binder/aidl/android/content/pm/OWNERS
+++ b/libs/binder/aidl/android/content/pm/OWNERS
@@ -1,5 +1,4 @@
+michaelwr@google.com
narayan@google.com
patb@google.com
-svetoslavganov@google.com
-toddke@google.com
-patb@google.com
\ No newline at end of file
+schfan@google.com
diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl
index 1d1f84f..6539238 100644
--- a/libs/binder/aidl/android/os/IServiceManager.aidl
+++ b/libs/binder/aidl/android/os/IServiceManager.aidl
@@ -49,6 +49,8 @@
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH
| DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PRIORITY_DEFAULT;
+ const int FLAG_IS_LAZY_SERVICE = 1 << 30;
+
/* Allows services to dump sections in protobuf format. */
const int DUMP_FLAG_PROTO = 1 << 4;
@@ -61,7 +63,8 @@
*
* Returns null if the service does not exist.
*
- * @deprecated TODO(b/355394904): Use getService2 instead.
+ * @deprecated TODO(b/355394904): Use getService2 instead. This does not return metadata
+ * that is included in ServiceWithMetadata
*/
@UnsupportedAppUsage
@nullable IBinder getService(@utf8InCpp String name);
@@ -80,11 +83,20 @@
/**
* Retrieve an existing service called @a name from the service
+ * manager. Non-blocking. Returns null if the service does not exist.
+ *
+ * @deprecated TODO(b/355394904): Use checkService2 instead. This does not
+ * return metadata that is included in ServiceWithMetadata
+ */
+ @UnsupportedAppUsage
+ @nullable IBinder checkService(@utf8InCpp String name);
+
+ /**
+ * Retrieve an existing service called @a name from the service
* manager. Non-blocking. Returns null if the service does not
* exist.
*/
- @UnsupportedAppUsage
- Service checkService(@utf8InCpp String name);
+ Service checkService2(@utf8InCpp String name);
/**
* Place a new @a service called @a name into the service
diff --git a/libs/binder/aidl/android/os/Service.aidl b/libs/binder/aidl/android/os/Service.aidl
index 4c52109..3bc6588 100644
--- a/libs/binder/aidl/android/os/Service.aidl
+++ b/libs/binder/aidl/android/os/Service.aidl
@@ -16,6 +16,8 @@
package android.os;
+import android.os.ServiceWithMetadata;
+
/**
* Service is a union of different service types that can be returned
* by the internal {@link ServiceManager#getService(name)} API.
@@ -23,6 +25,6 @@
* @hide
*/
union Service {
- @nullable IBinder binder;
+ ServiceWithMetadata serviceWithMetadata;
@nullable IBinder accessor;
}
\ No newline at end of file
diff --git a/libs/binder/trusty/ndk/include/android/llndk-versioning.h b/libs/binder/aidl/android/os/ServiceWithMetadata.aidl
similarity index 68%
copy from libs/binder/trusty/ndk/include/android/llndk-versioning.h
copy to libs/binder/aidl/android/os/ServiceWithMetadata.aidl
index e955a34..96f76ff 100644
--- a/libs/binder/trusty/ndk/include/android/llndk-versioning.h
+++ b/libs/binder/aidl/android/os/ServiceWithMetadata.aidl
@@ -13,7 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#pragma once
-// TODO(b/349936395): set to true for Trusty
-#define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) (false)
+package android.os;
+
+/**
+ * Service binder with metadata.
+ * @hide
+ */
+parcelable ServiceWithMetadata {
+ /**
+ * IBinder to service
+ */
+ @nullable IBinder service;
+ /**
+ * boolean if the IBinder can be cached by client.
+ */
+ boolean isLazyService;
+}
diff --git a/libs/binder/binder_module.h b/libs/binder/binder_module.h
index 65cdcd7..b3a2d9e 100644
--- a/libs/binder/binder_module.h
+++ b/libs/binder/binder_module.h
@@ -32,34 +32,4 @@
#include <linux/android/binder.h>
#include <sys/ioctl.h>
-struct binder_frozen_state_info {
- binder_uintptr_t cookie;
- __u32 is_frozen;
-};
-
-#ifndef BR_FROZEN_BINDER
-// Temporary definition of BR_FROZEN_BINDER until UAPI binder.h includes it.
-#define BR_FROZEN_BINDER _IOR('r', 21, struct binder_frozen_state_info)
-#endif // BR_FROZEN_BINDER
-
-#ifndef BR_CLEAR_FREEZE_NOTIFICATION_DONE
-// Temporary definition of BR_CLEAR_FREEZE_NOTIFICATION_DONE until UAPI binder.h includes it.
-#define BR_CLEAR_FREEZE_NOTIFICATION_DONE _IOR('r', 22, binder_uintptr_t)
-#endif // BR_CLEAR_FREEZE_NOTIFICATION_DONE
-
-#ifndef BC_REQUEST_FREEZE_NOTIFICATION
-// Temporary definition of BC_REQUEST_FREEZE_NOTIFICATION until UAPI binder.h includes it.
-#define BC_REQUEST_FREEZE_NOTIFICATION _IOW('c', 19, struct binder_handle_cookie)
-#endif // BC_REQUEST_FREEZE_NOTIFICATION
-
-#ifndef BC_CLEAR_FREEZE_NOTIFICATION
-// Temporary definition of BC_CLEAR_FREEZE_NOTIFICATION until UAPI binder.h includes it.
-#define BC_CLEAR_FREEZE_NOTIFICATION _IOW('c', 20, struct binder_handle_cookie)
-#endif // BC_CLEAR_FREEZE_NOTIFICATION
-
-#ifndef BC_FREEZE_NOTIFICATION_DONE
-// Temporary definition of BC_FREEZE_NOTIFICATION_DONE until UAPI binder.h includes it.
-#define BC_FREEZE_NOTIFICATION_DONE _IOW('c', 21, binder_uintptr_t)
-#endif // BC_FREEZE_NOTIFICATION_DONE
-
#endif // _BINDER_MODULE_H_
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 7518044..935bd8d 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -104,6 +104,7 @@
// Stop the current recording.
LIBBINDER_EXPORTED status_t stopRecordingBinder();
+ // Note: This class is not thread safe so protect uses of it when necessary
class ObjectManager {
public:
ObjectManager();
@@ -116,8 +117,6 @@
sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make,
const void* makeArgs);
- void kill();
-
private:
ObjectManager(const ObjectManager&);
ObjectManager& operator=(const ObjectManager&);
@@ -224,7 +223,7 @@
volatile int32_t mObitsSent;
Vector<Obituary>* mObituaries;
std::unique_ptr<FrozenStateChange> mFrozen;
- ObjectManager mObjects;
+ ObjectManager mObjectMgr;
mutable String16 mDescriptorCache;
int32_t mTrackedUid;
diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
index 30e005c..993ad82 100644
--- a/libs/binder/include/binder/IInterface.h
+++ b/libs/binder/include/binder/IInterface.h
@@ -219,9 +219,6 @@
constexpr const char* const kManualInterfaces[] = {
"android.app.IActivityManager",
"android.app.IUidObserver",
- "android.drm.IDrm",
- "android.dvr.IVsyncCallback",
- "android.dvr.IVsyncService",
"android.gfx.tests.ICallback",
"android.gfx.tests.IIPCTest",
"android.gfx.tests.ISafeInterfaceTest",
@@ -235,22 +232,17 @@
"android.hardware.ICameraClient",
"android.hardware.ICameraRecordingProxy",
"android.hardware.ICameraRecordingProxyListener",
- "android.hardware.ICrypto",
"android.hardware.IOMXObserver",
"android.hardware.IStreamListener",
"android.hardware.IStreamSource",
"android.media.IAudioService",
"android.media.IDataSource",
- "android.media.IDrmClient",
"android.media.IMediaCodecList",
- "android.media.IMediaDrmService",
"android.media.IMediaExtractor",
- "android.media.IMediaExtractorService",
"android.media.IMediaHTTPConnection",
"android.media.IMediaHTTPService",
"android.media.IMediaLogService",
"android.media.IMediaMetadataRetriever",
- "android.media.IMediaMetricsService",
"android.media.IMediaPlayer",
"android.media.IMediaPlayerClient",
"android.media.IMediaPlayerService",
@@ -260,35 +252,23 @@
"android.media.IMediaSource",
"android.media.IRemoteDisplay",
"android.media.IRemoteDisplayClient",
- "android.media.IResourceManagerClient",
- "android.media.IResourceManagerService",
- "android.os.IComplexTypeInterface",
"android.os.IPermissionController",
- "android.os.IPingResponder",
"android.os.IProcessInfoService",
"android.os.ISchedulingPolicyService",
- "android.os.IStringConstants",
"android.os.storage.IObbActionListener",
"android.os.storage.IStorageEventListener",
"android.os.storage.IStorageManager",
"android.os.storage.IStorageShutdownObserver",
- "android.service.vr.IPersistentVrStateCallbacks",
- "android.service.vr.IVrManager",
- "android.service.vr.IVrStateCallbacks",
"android.ui.ISurfaceComposer",
"android.utils.IMemory",
"android.utils.IMemoryHeap",
"com.android.car.procfsinspector.IProcfsInspector",
- "com.android.internal.app.IAppOpsCallback",
"com.android.internal.app.IAppOpsService",
"com.android.internal.app.IBatteryStats",
"com.android.internal.os.IResultReceiver",
"com.android.internal.os.IShellCallback",
"drm.IDrmManagerService",
"drm.IDrmServiceListener",
- "IAAudioClient",
- "IAAudioService",
- "VtsFuzzer",
nullptr,
};
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 9ef4e69..f7465e2 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -64,7 +64,10 @@
* Returns the PID of the process which has made the current binder
* call. If not in a binder call, this will return getpid.
*
- * Warning: oneway transactions do not receive PID. Even if you expect
+ * Warning do not use this as a security identifier! PID is unreliable
+ * as it may be re-used. This should mostly be used for debugging.
+ *
+ * oneway transactions do not receive PID. Even if you expect
* a transaction to be synchronous, a misbehaving client could send it
* as an asynchronous call and result in a 0 PID here. Additionally, if
* there is a race and the calling process dies, the PID may still be
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 81f7cdb..d248f22 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -80,6 +80,14 @@
/**
* Register a service.
+ *
+ * Note:
+ * This status_t return value may be an exception code from an underlying
+ * Status type that doesn't have a representive error code in
+ * utils/Errors.h.
+ * One example of this is a return value of -7
+ * (Status::Exception::EX_UNSUPPORTED_OPERATION) when the service manager
+ * process is not installed on the device when addService is called.
*/
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t addService(const String16& name, const sp<IBinder>& service,
@@ -150,6 +158,12 @@
int pid;
};
virtual std::vector<ServiceDebugInfo> getServiceDebugInfo() = 0;
+
+ /**
+ * Directly enable or disable caching binder during addService calls.
+ * Only used for testing. This is enabled by default.
+ */
+ virtual void enableAddServiceCache(bool value) = 0;
};
LIBBINDER_EXPORTED sp<IServiceManager> defaultServiceManager();
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index ceab20a..6c4c6fe 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -178,7 +178,8 @@
LIBBINDER_EXPORTED status_t writeUint64(uint64_t val);
LIBBINDER_EXPORTED status_t writeFloat(float val);
LIBBINDER_EXPORTED status_t writeDouble(double val);
- LIBBINDER_EXPORTED status_t writeCString(const char* str);
+ LIBBINDER_EXPORTED status_t writeCString(const char* str)
+ __attribute__((deprecated("use AIDL, writeString* instead")));
LIBBINDER_EXPORTED status_t writeString8(const String8& str);
LIBBINDER_EXPORTED status_t writeString8(const char* str, size_t len);
LIBBINDER_EXPORTED status_t writeString16(const String16& str);
@@ -382,11 +383,13 @@
LIBBINDER_EXPORTED status_t
writeUniqueFileDescriptorVector(const std::optional<std::vector<binder::unique_fd>>& val);
LIBBINDER_EXPORTED status_t
- writeUniqueFileDescriptorVector(const std::unique_ptr<std::vector<binder::unique_fd>>& val)
- __attribute__((deprecated("use std::optional version instead")));
- LIBBINDER_EXPORTED status_t
writeUniqueFileDescriptorVector(const std::vector<binder::unique_fd>& val);
+ // WARNING: deprecated and incompatible with AIDL. You should use Parcelable
+ // definitions outside of Parcel to represent shared memory, such as
+ // IMemory or with ParcelFileDescriptor. We should remove this, or move it to be
+ // external to Parcel, it's not a very encapsulated API.
+ //
// Writes a blob to the parcel.
// If the blob is small, then it is stored in-place, otherwise it is
// transferred by way of an anonymous shared memory region. Prefer sending
@@ -400,8 +403,6 @@
// as long as it keeps a dup of the blob file descriptor handy for later.
LIBBINDER_EXPORTED status_t writeDupImmutableBlobFileDescriptor(int fd);
- LIBBINDER_EXPORTED status_t writeObject(const flat_binder_object& val, bool nullMetaData);
-
// Like Parcel.java's writeNoException(). Just writes a zero int32.
// Currently the native implementation doesn't do any of the StrictMode
// stack gathering and serialization that the Java implementation does.
@@ -434,7 +435,8 @@
LIBBINDER_EXPORTED status_t readUtf8FromUtf16(std::unique_ptr<std::string>* str) const
__attribute__((deprecated("use std::optional version instead")));
- LIBBINDER_EXPORTED const char* readCString() const;
+ LIBBINDER_EXPORTED const char* readCString() const
+ __attribute__((deprecated("use AIDL, use readString*")));
LIBBINDER_EXPORTED String8 readString8() const;
LIBBINDER_EXPORTED status_t readString8(String8* pArg) const;
LIBBINDER_EXPORTED const char* readString8Inplace(size_t* outLen) const;
@@ -625,11 +627,13 @@
LIBBINDER_EXPORTED status_t
readUniqueFileDescriptorVector(std::optional<std::vector<binder::unique_fd>>* val) const;
LIBBINDER_EXPORTED status_t
- readUniqueFileDescriptorVector(std::unique_ptr<std::vector<binder::unique_fd>>* val) const
- __attribute__((deprecated("use std::optional version instead")));
- LIBBINDER_EXPORTED status_t
readUniqueFileDescriptorVector(std::vector<binder::unique_fd>* val) const;
+ // WARNING: deprecated and incompatible with AIDL. You should use Parcelable
+ // definitions outside of Parcel to represent shared memory, such as
+ // IMemory or with ParcelFileDescriptor. We should remove this, or move it to be
+ // external to Parcel, it's not a very encapsulated API.
+ //
// Reads a blob from the parcel.
// The caller should call release() on the blob after reading its contents.
LIBBINDER_EXPORTED status_t readBlob(size_t len, ReadableBlob* outBlob) const;
@@ -647,6 +651,11 @@
LIBBINDER_EXPORTED void print(std::ostream& to, uint32_t flags = 0) const;
+ // This API is to quickly become a view of another Parcel, so that we can also
+ // test 'owner' paths quickly. It's extremely dangerous to use this API in
+ // practice, and you should never ever do it.
+ LIBBINDER_EXPORTED void makeDangerousViewOf(Parcel* p);
+
private:
// Close all file descriptors in the parcel at object positions >= newObjectsSize.
void closeFileDescriptors(size_t newObjectsSize);
@@ -662,7 +671,7 @@
void ipcSetDataReference(const uint8_t* data, size_t dataSize, const binder_size_t* objects,
size_t objectsCount, release_func relFunc);
// Takes ownership even when an error is returned.
- status_t rpcSetDataReference(
+ [[nodiscard]] status_t rpcSetDataReference(
const sp<RpcSession>& session, const uint8_t* data, size_t dataSize,
const uint32_t* objectTable, size_t objectTableSize,
std::vector<std::variant<binder::unique_fd, binder::borrowed_fd>>&& ancillaryFds,
@@ -670,7 +679,7 @@
status_t finishWrite(size_t len);
void releaseObjects();
- void acquireObjects();
+ void reacquireObjects(size_t objectSize);
status_t growData(size_t len);
// Clear the Parcel and set the capacity to `desired`.
// Doesn't reset the RPC session association.
@@ -678,6 +687,7 @@
// Set the capacity to `desired`, truncating the Parcel if necessary.
status_t continueWrite(size_t desired);
status_t truncateRpcObjects(size_t newObjectsSize);
+ status_t writeObject(const flat_binder_object& val, bool nullMetaData);
status_t writePointer(uintptr_t val);
status_t readPointer(uintptr_t *pArg) const;
uintptr_t readPointer() const;
@@ -1478,14 +1488,15 @@
* Note: for historical reasons, this does not include ashmem memory which
* is referenced by this Parcel, but which this parcel doesn't own (e.g.
* writeFileDescriptor is called without 'takeOwnership' true).
+ *
+ * WARNING: you should not use this, but rather, unparcel, and inspect
+ * each FD independently. This counts ashmem size, but there may be
+ * other resources used for non-ashmem FDs, such as other types of
+ * shared memory, files, etc..
*/
LIBBINDER_EXPORTED size_t getOpenAshmemSize() const;
private:
- // TODO(b/202029388): Remove 'getBlobAshmemSize' once no prebuilts reference
- // this
- LIBBINDER_EXPORTED size_t getBlobAshmemSize() const;
-
// Needed so that we can save object metadata to the disk
friend class android::binder::debug::RecordedTransaction;
};
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index 21bfd42..ced49c1 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -141,6 +141,8 @@
private:
static sp<ProcessState> init(const char* defaultDriver, bool requireDefault);
+ void checkExpectingThreadPoolStart() const;
+
static void onFork();
static void parentPostFork();
static void childPostFork();
diff --git a/libs/binder/include/binder/RpcThreads.h b/libs/binder/include/binder/RpcThreads.h
index 99fa6b8..51b9716b 100644
--- a/libs/binder/include/binder/RpcThreads.h
+++ b/libs/binder/include/binder/RpcThreads.h
@@ -20,6 +20,7 @@
#include <condition_variable>
#include <functional>
#include <memory>
+#include <mutex>
#include <thread>
#include <binder/Common.h>
diff --git a/libs/binder/include/binder/SafeInterface.h b/libs/binder/include/binder/SafeInterface.h
index 0b4f196..e848385 100644
--- a/libs/binder/include/binder/SafeInterface.h
+++ b/libs/binder/include/binder/SafeInterface.h
@@ -34,6 +34,13 @@
namespace android {
namespace SafeInterface {
+/**
+ * WARNING: Prefer to use AIDL-generated interfaces. Using SafeInterface to generate interfaces
+ * does not support tracing, and many other AIDL features out of the box. The general direction
+ * we should go is to migrate safe interface users to AIDL and then remove this so that there
+ * is only one thing to learn/use/test/integrate, not this as well.
+ */
+
// ParcelHandler is responsible for writing/reading various types to/from a Parcel in a generic way
class LIBBINDER_EXPORTED ParcelHandler {
public:
@@ -72,7 +79,7 @@
template <typename T>
typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type read(
const Parcel& parcel, sp<T>* t) const {
- *t = new T{};
+ *t = sp<T>::make();
return callParcel("read(sp<Flattenable>)", [&]() { return parcel.read(*(t->get())); });
}
template <typename T>
diff --git a/libs/binder/include/binder/Stability.h b/libs/binder/include/binder/Stability.h
index cafb8aa..bfe0a5a 100644
--- a/libs/binder/include/binder/Stability.h
+++ b/libs/binder/include/binder/Stability.h
@@ -20,6 +20,8 @@
#include <binder/IBinder.h>
#include <string>
+class BinderStabilityIntegrationTest_ExpectedStabilityForItsPartition_Test;
+
namespace android {
class BpBinder;
@@ -127,6 +129,8 @@
// through Parcel)
friend ::android::ProcessState;
+ friend ::BinderStabilityIntegrationTest_ExpectedStabilityForItsPartition_Test;
+
static void tryMarkCompilationUnit(IBinder* binder);
// Currently, we use int16_t for Level so that it can fit in BBinder.
@@ -156,11 +160,11 @@
uint32_t flags);
// get stability information as encoded on the wire
- static int16_t getRepr(IBinder* binder);
+ LIBBINDER_EXPORTED static int16_t getRepr(IBinder* binder);
// whether a transaction on binder is allowed, if the transaction
// is done from a context with a specific stability level
- static bool check(int16_t provided, Level required);
+ LIBBINDER_EXPORTED static bool check(int16_t provided, Level required);
static bool isDeclaredLevel(int32_t level);
static std::string levelString(int32_t level);
diff --git a/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp b/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
index 392ebb5..48c0ea6 100644
--- a/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
+++ b/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
@@ -37,8 +37,12 @@
// Set `cid` to VMADDR_CID_LOCAL to only bind to the local vsock interface.
// Returns an opaque handle to the running server instance, or null if the server
// could not be started.
+// Set |port| to VMADDR_PORT_ANY to pick an available ephemeral port.
+// |assignedPort| will be set to the assigned port number if it is not null.
+// This will be the provided |port|, or the chosen available ephemeral port when
+// |port| is VMADDR_PORT_ANY.
[[nodiscard]] ARpcServer* ARpcServer_newVsock(AIBinder* service, unsigned int cid,
- unsigned int port);
+ unsigned int port, unsigned int* assignedPort);
// Starts a Unix domain RPC server with an open raw socket file descriptor
// and a given root IBinder object.
diff --git a/libs/binder/libbinder_rpc_unstable.cpp b/libs/binder/libbinder_rpc_unstable.cpp
index 21537fc..64b1be2 100644
--- a/libs/binder/libbinder_rpc_unstable.cpp
+++ b/libs/binder/libbinder_rpc_unstable.cpp
@@ -23,11 +23,8 @@
#ifndef __TRUSTY__
#include <cutils/sockets.h>
-#endif
-
-#ifdef __linux__
-#include <linux/vm_sockets.h>
-#endif // __linux__
+#include "vm_sockets.h"
+#endif // !__TRUSTY__
using android::OK;
using android::RpcServer;
@@ -81,7 +78,8 @@
extern "C" {
#ifndef __TRUSTY__
-ARpcServer* ARpcServer_newVsock(AIBinder* service, unsigned int cid, unsigned int port) {
+ARpcServer* ARpcServer_newVsock(AIBinder* service, unsigned int cid, unsigned int port,
+ unsigned int* assignedPort) {
auto server = RpcServer::make();
unsigned int bindCid = VMADDR_CID_ANY; // bind to the remote interface
@@ -90,7 +88,7 @@
cid = VMADDR_CID_ANY; // no need for a connection filter
}
- if (status_t status = server->setupVsockServer(bindCid, port); status != OK) {
+ if (status_t status = server->setupVsockServer(bindCid, port, assignedPort); status != OK) {
ALOGE("Failed to set up vsock server with port %u error: %s", port,
statusToString(status).c_str());
return nullptr;
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index a7423b3..5710bbf 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -82,7 +82,6 @@
llndk: {
symbol_file: "libbinder_ndk.map.txt",
- export_llndk_headers: ["libvendorsupport_llndk_headers"],
},
cflags: [
@@ -110,11 +109,9 @@
],
header_libs: [
- "libvendorsupport_llndk_headers",
"jni_headers",
],
export_header_lib_headers: [
- "libvendorsupport_llndk_headers",
"jni_headers",
],
diff --git a/libs/binder/ndk/binder_rpc.cpp b/libs/binder/ndk/binder_rpc.cpp
index 07b8c40..bb5989d 100644
--- a/libs/binder/ndk/binder_rpc.cpp
+++ b/libs/binder/ndk/binder_rpc.cpp
@@ -104,19 +104,23 @@
};
ABinderRpc_AccessorProvider* ABinderRpc_registerAccessorProvider(
- ABinderRpc_AccessorProvider_getAccessorCallback provider, const char** instances,
- size_t numInstances, void* data,
+ ABinderRpc_AccessorProvider_getAccessorCallback provider,
+ const char* const* const instances, size_t numInstances, void* data,
ABinderRpc_AccessorProviderUserData_deleteCallback onDelete) {
- if (provider == nullptr) {
- ALOGE("Null provider passed to ABinderRpc_registerAccessorProvider");
- return nullptr;
- }
if (data && onDelete == nullptr) {
ALOGE("If a non-null data ptr is passed to ABinderRpc_registerAccessorProvider, then a "
"ABinderRpc_AccessorProviderUserData_deleteCallback must also be passed to delete "
"the data object once the ABinderRpc_AccessorProvider is removed.");
return nullptr;
}
+ // call the onDelete when the last reference of this goes away (when the
+ // last reference to the generate std::function goes away).
+ std::shared_ptr<OnDeleteProviderHolder> onDeleteHolder =
+ std::make_shared<OnDeleteProviderHolder>(data, onDelete);
+ if (provider == nullptr) {
+ ALOGE("Null provider passed to ABinderRpc_registerAccessorProvider");
+ return nullptr;
+ }
if (numInstances == 0 || instances == nullptr) {
ALOGE("No instances passed to ABinderRpc_registerAccessorProvider. numInstances: %zu",
numInstances);
@@ -126,10 +130,6 @@
for (size_t i = 0; i < numInstances; i++) {
instanceStrings.emplace(instances[i]);
}
- // call the onDelete when the last reference of this goes away (when the
- // last reference to the generate std::function goes away).
- std::shared_ptr<OnDeleteProviderHolder> onDeleteHolder =
- std::make_shared<OnDeleteProviderHolder>(data, onDelete);
android::RpcAccessorProvider generate = [provider,
onDeleteHolder](const String16& name) -> sp<IBinder> {
ABinderRpc_Accessor* accessor = provider(String8(name).c_str(), onDeleteHolder->mData);
@@ -255,7 +255,7 @@
"new variant was added to the ABinderRpc_ConnectionInfo and this needs to be "
"updated.");
}
- return OK;
+ return STATUS_OK;
};
sp<IBinder> accessorBinder = android::createAccessor(String16(instance), std::move(generate));
if (accessorBinder == nullptr) {
@@ -321,7 +321,7 @@
// This AIBinder needs a strong ref to pass ownership to the caller
binder->incStrong(nullptr);
*outDelegator = binder.get();
- return OK;
+ return STATUS_OK;
}
ABinderRpc_ConnectionInfo* ABinderRpc_ConnectionInfo_new(const sockaddr* addr, socklen_t len) {
diff --git a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
index 0ad110e..c6518d8 100644
--- a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
@@ -30,16 +30,14 @@
#include <android/binder_auto_utils.h>
#include <android/binder_ibinder.h>
-#if defined(__ANDROID_VENDOR_API__)
-#include <android/llndk-versioning.h>
-#elif !defined(API_LEVEL_AT_LEAST)
#if defined(__BIONIC__)
-#define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) \
- (__builtin_available(android sdk_api_level, *))
+#define API_LEVEL_AT_LEAST(sdk_api_level) __builtin_available(android sdk_api_level, *)
+#elif defined(TRUSTY_USERSPACE)
+// TODO(b/349936395): set to true for Trusty
+#define API_LEVEL_AT_LEAST(sdk_api_level) (false)
#else
-#define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) (true)
+#define API_LEVEL_AT_LEAST(sdk_api_level) (true)
#endif // __BIONIC__
-#endif // __ANDROID_VENDOR_API__
#if __has_include(<android/binder_shell.h>)
#include <android/binder_shell.h>
@@ -298,9 +296,8 @@
#endif
#if defined(__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__) || __ANDROID_API__ >= 36
- if API_LEVEL_AT_LEAST (36, 202504) {
- if (codeToFunction != nullptr &&
- (&AIBinder_Class_setTransactionCodeToFunctionNameMap != nullptr)) {
+ if (API_LEVEL_AT_LEAST(36)) {
+ if (codeToFunction != nullptr) {
AIBinder_Class_setTransactionCodeToFunctionNameMap(clazz, codeToFunction,
functionCount);
}
diff --git a/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h b/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h
index 83976b3..f3f3c38 100644
--- a/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h
+++ b/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h
@@ -22,17 +22,14 @@
#include <set>
#include <sstream>
-// Include llndk-versioning.h only for non-system build as it is not available for NDK headers.
-#if defined(__ANDROID_VENDOR_API__)
-#include <android/llndk-versioning.h>
-#elif !defined(API_LEVEL_AT_LEAST)
#if defined(__BIONIC__)
-#define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) \
- (__builtin_available(android sdk_api_level, *))
+#define API_LEVEL_AT_LEAST(sdk_api_level) __builtin_available(android sdk_api_level, *)
+#elif defined(TRUSTY_USERSPACE)
+// TODO(b/349936395): set to true for Trusty
+#define API_LEVEL_AT_LEAST(sdk_api_level) (false)
#else
-#define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) (true)
+#define API_LEVEL_AT_LEAST(sdk_api_level) (true)
#endif // __BIONIC__
-#endif // __ANDROID_VENDOR_API__
namespace aidl::android::os {
@@ -44,7 +41,7 @@
class PersistableBundle {
public:
PersistableBundle() noexcept {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
mPBundle = APersistableBundle_new();
}
}
@@ -54,13 +51,13 @@
PersistableBundle(PersistableBundle&& other) noexcept : mPBundle(other.release()) {}
// duplicates, does not take ownership of the APersistableBundle*
PersistableBundle(const PersistableBundle& other) {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
mPBundle = APersistableBundle_dup(other.mPBundle);
}
}
// duplicates, does not take ownership of the APersistableBundle*
PersistableBundle& operator=(const PersistableBundle& other) {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
mPBundle = APersistableBundle_dup(other.mPBundle);
}
return *this;
@@ -70,7 +67,7 @@
binder_status_t readFromParcel(const AParcel* _Nonnull parcel) {
reset();
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return APersistableBundle_readFromParcel(parcel, &mPBundle);
} else {
return STATUS_INVALID_OPERATION;
@@ -81,7 +78,7 @@
if (!mPBundle) {
return STATUS_BAD_VALUE;
}
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return APersistableBundle_writeToParcel(mPBundle, parcel);
} else {
return STATUS_INVALID_OPERATION;
@@ -96,7 +93,7 @@
*/
void reset(APersistableBundle* _Nullable pBundle = nullptr) noexcept {
if (mPBundle) {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
APersistableBundle_delete(mPBundle);
}
mPBundle = nullptr;
@@ -109,7 +106,7 @@
* what should be used to check for equality.
*/
bool deepEquals(const PersistableBundle& rhs) const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return APersistableBundle_isEqual(get(), rhs.get());
} else {
return false;
@@ -148,7 +145,7 @@
inline std::string toString() const {
if (!mPBundle) {
return "<PersistableBundle: null>";
- } else if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ } else if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
std::ostringstream os;
os << "<PersistableBundle: ";
os << "size: " << std::to_string(APersistableBundle_size(mPBundle));
@@ -159,7 +156,7 @@
}
int32_t size() const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return APersistableBundle_size(mPBundle);
} else {
return 0;
@@ -167,7 +164,7 @@
}
int32_t erase(const std::string& key) {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return APersistableBundle_erase(mPBundle, key.c_str());
} else {
return 0;
@@ -175,37 +172,37 @@
}
void putBoolean(const std::string& key, bool val) {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
APersistableBundle_putBoolean(mPBundle, key.c_str(), val);
}
}
void putInt(const std::string& key, int32_t val) {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
APersistableBundle_putInt(mPBundle, key.c_str(), val);
}
}
void putLong(const std::string& key, int64_t val) {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
APersistableBundle_putLong(mPBundle, key.c_str(), val);
}
}
void putDouble(const std::string& key, double val) {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
APersistableBundle_putDouble(mPBundle, key.c_str(), val);
}
}
void putString(const std::string& key, const std::string& val) {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
APersistableBundle_putString(mPBundle, key.c_str(), val.c_str());
}
}
void putBooleanVector(const std::string& key, const std::vector<bool>& vec) {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
// std::vector<bool> has no ::data().
int32_t num = vec.size();
if (num > 0) {
@@ -222,7 +219,7 @@
}
void putIntVector(const std::string& key, const std::vector<int32_t>& vec) {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
int32_t num = vec.size();
if (num > 0) {
APersistableBundle_putIntVector(mPBundle, key.c_str(), vec.data(), num);
@@ -230,7 +227,7 @@
}
}
void putLongVector(const std::string& key, const std::vector<int64_t>& vec) {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
int32_t num = vec.size();
if (num > 0) {
APersistableBundle_putLongVector(mPBundle, key.c_str(), vec.data(), num);
@@ -238,7 +235,7 @@
}
}
void putDoubleVector(const std::string& key, const std::vector<double>& vec) {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
int32_t num = vec.size();
if (num > 0) {
APersistableBundle_putDoubleVector(mPBundle, key.c_str(), vec.data(), num);
@@ -246,7 +243,7 @@
}
}
void putStringVector(const std::string& key, const std::vector<std::string>& vec) {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
int32_t num = vec.size();
if (num > 0) {
char** inVec = (char**)malloc(num * sizeof(char*));
@@ -261,13 +258,13 @@
}
}
void putPersistableBundle(const std::string& key, const PersistableBundle& pBundle) {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
APersistableBundle_putPersistableBundle(mPBundle, key.c_str(), pBundle.mPBundle);
}
}
bool getBoolean(const std::string& key, bool* _Nonnull val) const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return APersistableBundle_getBoolean(mPBundle, key.c_str(), val);
} else {
return false;
@@ -275,7 +272,7 @@
}
bool getInt(const std::string& key, int32_t* _Nonnull val) const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return APersistableBundle_getInt(mPBundle, key.c_str(), val);
} else {
return false;
@@ -283,7 +280,7 @@
}
bool getLong(const std::string& key, int64_t* _Nonnull val) const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return APersistableBundle_getLong(mPBundle, key.c_str(), val);
} else {
return false;
@@ -291,7 +288,7 @@
}
bool getDouble(const std::string& key, double* _Nonnull val) const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return APersistableBundle_getDouble(mPBundle, key.c_str(), val);
} else {
return false;
@@ -303,7 +300,7 @@
}
bool getString(const std::string& key, std::string* _Nonnull val) const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
char* outString = nullptr;
bool ret = APersistableBundle_getString(mPBundle, key.c_str(), &outString,
&stringAllocator, nullptr);
@@ -321,7 +318,7 @@
const char* _Nonnull, T* _Nullable, int32_t),
const APersistableBundle* _Nonnull pBundle, const char* _Nonnull key,
std::vector<T>* _Nonnull vec) const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
int32_t bytes = 0;
// call first with nullptr to get required size in bytes
bytes = getVec(pBundle, key, nullptr, 0);
@@ -343,28 +340,28 @@
}
bool getBooleanVector(const std::string& key, std::vector<bool>* _Nonnull vec) const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return getVecInternal<bool>(&APersistableBundle_getBooleanVector, mPBundle, key.c_str(),
vec);
}
return false;
}
bool getIntVector(const std::string& key, std::vector<int32_t>* _Nonnull vec) const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return getVecInternal<int32_t>(&APersistableBundle_getIntVector, mPBundle, key.c_str(),
vec);
}
return false;
}
bool getLongVector(const std::string& key, std::vector<int64_t>* _Nonnull vec) const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return getVecInternal<int64_t>(&APersistableBundle_getLongVector, mPBundle, key.c_str(),
vec);
}
return false;
}
bool getDoubleVector(const std::string& key, std::vector<double>* _Nonnull vec) const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return getVecInternal<double>(&APersistableBundle_getDoubleVector, mPBundle,
key.c_str(), vec);
}
@@ -389,7 +386,7 @@
}
bool getStringVector(const std::string& key, std::vector<std::string>* _Nonnull vec) const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
int32_t bytes = APersistableBundle_getStringVector(mPBundle, key.c_str(), nullptr, 0,
&stringAllocator, nullptr);
if (bytes > 0) {
@@ -406,7 +403,7 @@
}
bool getPersistableBundle(const std::string& key, PersistableBundle* _Nonnull val) const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
APersistableBundle* bundle = nullptr;
bool ret = APersistableBundle_getPersistableBundle(mPBundle, key.c_str(), &bundle);
if (ret) {
@@ -438,77 +435,77 @@
}
std::set<std::string> getBooleanKeys() const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return getKeys(&APersistableBundle_getBooleanKeys, mPBundle);
} else {
return {};
}
}
std::set<std::string> getIntKeys() const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return getKeys(&APersistableBundle_getIntKeys, mPBundle);
} else {
return {};
}
}
std::set<std::string> getLongKeys() const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return getKeys(&APersistableBundle_getLongKeys, mPBundle);
} else {
return {};
}
}
std::set<std::string> getDoubleKeys() const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return getKeys(&APersistableBundle_getDoubleKeys, mPBundle);
} else {
return {};
}
}
std::set<std::string> getStringKeys() const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return getKeys(&APersistableBundle_getStringKeys, mPBundle);
} else {
return {};
}
}
std::set<std::string> getBooleanVectorKeys() const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return getKeys(&APersistableBundle_getBooleanVectorKeys, mPBundle);
} else {
return {};
}
}
std::set<std::string> getIntVectorKeys() const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return getKeys(&APersistableBundle_getIntVectorKeys, mPBundle);
} else {
return {};
}
}
std::set<std::string> getLongVectorKeys() const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return getKeys(&APersistableBundle_getLongVectorKeys, mPBundle);
} else {
return {};
}
}
std::set<std::string> getDoubleVectorKeys() const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return getKeys(&APersistableBundle_getDoubleVectorKeys, mPBundle);
} else {
return {};
}
}
std::set<std::string> getStringVectorKeys() const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return getKeys(&APersistableBundle_getStringVectorKeys, mPBundle);
} else {
return {};
}
}
std::set<std::string> getPersistableBundleKeys() const {
- if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) {
+ if (API_LEVEL_AT_LEAST(__ANDROID_API_V__)) {
return getKeys(&APersistableBundle_getPersistableBundleKeys, mPBundle);
} else {
return {};
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index bd46c47..d69d318 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -419,6 +419,9 @@
* This can be used with higher-level system services to determine the caller's identity and check
* permissions.
*
+ * Warning do not use this as a security identifier! PID is unreliable as it may be re-used. This
+ * should mostly be used for debugging.
+ *
* Available since API level 29.
*
* \return calling uid or the current process's UID if this thread isn't processing a transaction.
diff --git a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
index 89f21dd..783e11f 100644
--- a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
+++ b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
@@ -62,6 +62,8 @@
* This must be called before the object is sent to another process.
* Aborts on invalid values. Not thread safe.
*
+ * This overrides the setting in ABinderProcess_disableBackgroundScheduling.
+ *
* \param binder local server binder to set the policy for
* \param policy scheduler policy as defined in linux UAPI
* \param priority priority. [-20..19] for SCHED_NORMAL, [1..99] for RT
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index cc4943b..2c2e2c8 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -30,10 +30,15 @@
* not be added with this flag for privacy concerns.
*/
ADD_SERVICE_ALLOW_ISOLATED = 1 << 0,
+ /**
+ * Allows services to dump sections according to priorities and format
+ */
ADD_SERVICE_DUMP_FLAG_PRIORITY_CRITICAL = 1 << 1,
ADD_SERVICE_DUMP_FLAG_PRIORITY_HIGH = 1 << 2,
ADD_SERVICE_DUMP_FLAG_PRIORITY_NORMAL = 1 << 3,
ADD_SERVICE_DUMP_FLAG_PRIORITY_DEFAULT = 1 << 4,
+ ADD_SERVICE_DUMP_FLAG_PROTO = 1 << 5,
+ // All other bits are reserved for internal usage
};
/**
diff --git a/libs/binder/ndk/include_platform/android/binder_process.h b/libs/binder/ndk/include_platform/android/binder_process.h
index 6aff994..2432099 100644
--- a/libs/binder/ndk/include_platform/android/binder_process.h
+++ b/libs/binder/ndk/include_platform/android/binder_process.h
@@ -75,6 +75,19 @@
void ABinderProcess_joinThreadPool(void);
/**
+ * Disables (or enables) background scheduling.
+ *
+ * By default, binder threads execute at a lower priority. However, this can cause
+ * priority inversion, so it is recommended to be disabled in high priority
+ * or in system processes.
+ *
+ * See also AIBinder_setMinSchedulerPolicy, which overrides this setting.
+ *
+ * \param disable whether to disable background scheduling
+ */
+void ABinderProcess_disableBackgroundScheduling(bool disable);
+
+/**
* This gives you an fd to wait on. Whenever data is available on the fd,
* ABinderProcess_handlePolledCommands can be called to handle binder queries.
* This is expected to be used in a single threaded process which waits on
diff --git a/libs/binder/ndk/include_platform/android/binder_rpc.h b/libs/binder/ndk/include_platform/android/binder_rpc.h
index 9fe5d78..1318889 100644
--- a/libs/binder/ndk/include_platform/android/binder_rpc.h
+++ b/libs/binder/ndk/include_platform/android/binder_rpc.h
@@ -139,13 +139,16 @@
* registered. In the error case of duplicate instances, if data was
* provided with a ABinderRpc_AccessorProviderUserData_deleteCallback,
* the callback will be called to delete the data.
+ * If nullptr is returned, ABinderRpc_AccessorProviderUserData_deleteCallback
+ * will be called on data immediately.
* Otherwise returns a pointer to the ABinderRpc_AccessorProvider that
* can be used to remove with ABinderRpc_unregisterAccessorProvider.
*/
ABinderRpc_AccessorProvider* _Nullable ABinderRpc_registerAccessorProvider(
ABinderRpc_AccessorProvider_getAccessorCallback _Nonnull provider,
- const char* _Nullable* _Nonnull instances, size_t numInstances, void* _Nullable data,
- ABinderRpc_AccessorProviderUserData_deleteCallback _Nullable onDelete) __INTRODUCED_IN(36);
+ const char* _Nullable const* const _Nonnull instances, size_t numInstances,
+ void* _Nullable data, ABinderRpc_AccessorProviderUserData_deleteCallback _Nullable onDelete)
+ __INTRODUCED_IN(36);
/**
* Remove an ABinderRpc_AccessorProvider from libbinder. This will remove references
@@ -287,6 +290,11 @@
* this object with one strong ref count and is responsible for removing
* that ref count with with AIBinder_decStrong when the caller wishes to
* drop the reference.
+ * \return STATUS_OK on success.
+ * STATUS_UNEXPECTED_NULL if instance or binder arguments are null.
+ * STATUS_BAD_TYPE if the binder is not an IAccessor.
+ * STATUS_NAME_NOT_FOUND if the binder is an IAccessor, but not
+ * associated with the provided instance name.
*/
binder_status_t ABinderRpc_Accessor_delegateAccessor(const char* _Nonnull instance,
AIBinder* _Nonnull binder,
diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h
index 089c775..8050205 100644
--- a/libs/binder/ndk/include_platform/android/binder_stability.h
+++ b/libs/binder/ndk/include_platform/android/binder_stability.h
@@ -27,6 +27,10 @@
#if defined(__ANDROID_VENDOR__)
+#if defined(__ANDROID_PRODUCT__)
+#error "build bug: product is not part of the vendor half of the Treble system/vendor split"
+#endif
+
/**
* Private addition to binder_flag_t.
*/
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 4d691f8..d4eb8c7 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -164,96 +164,53 @@
LIBBINDER_NDK35 { # introduced=VanillaIceCream
global:
APersistableBundle_readFromParcel;
- APersistableBundle_readFromParcel; # llndk=202404
APersistableBundle_writeToParcel;
- APersistableBundle_writeToParcel; # llndk=202404
APersistableBundle_new;
- APersistableBundle_new; # llndk=202404
APersistableBundle_dup;
- APersistableBundle_dup; # llndk=202404
APersistableBundle_delete;
- APersistableBundle_delete; # llndk=202404
APersistableBundle_isEqual;
- APersistableBundle_isEqual; # llndk=202404
APersistableBundle_size;
- APersistableBundle_size; # llndk=202404
APersistableBundle_erase;
- APersistableBundle_erase; # llndk=202404
APersistableBundle_putBoolean;
- APersistableBundle_putBoolean; # llndk=202404
APersistableBundle_putInt;
- APersistableBundle_putInt; # llndk=202404
APersistableBundle_putLong;
- APersistableBundle_putLong; # llndk=202404
APersistableBundle_putDouble;
- APersistableBundle_putDouble; # llndk=202404
APersistableBundle_putString;
- APersistableBundle_putString; # llndk=202404
APersistableBundle_putBooleanVector;
- APersistableBundle_putBooleanVector; # llndk=202404
APersistableBundle_putIntVector;
- APersistableBundle_putIntVector; # llndk=202404
APersistableBundle_putLongVector;
- APersistableBundle_putLongVector; # llndk=202404
APersistableBundle_putDoubleVector;
- APersistableBundle_putDoubleVector; # llndk=202404
APersistableBundle_putStringVector;
- APersistableBundle_putStringVector; # llndk=202404
APersistableBundle_putPersistableBundle;
- APersistableBundle_putPersistableBundle; # llndk=202404
APersistableBundle_getBoolean;
- APersistableBundle_getBoolean; # llndk=202404
APersistableBundle_getInt;
- APersistableBundle_getInt; # llndk=202404
APersistableBundle_getLong;
- APersistableBundle_getLong; # llndk=202404
APersistableBundle_getDouble;
- APersistableBundle_getDouble; # llndk=202404
APersistableBundle_getString;
- APersistableBundle_getString; # llndk=202404
APersistableBundle_getBooleanVector;
- APersistableBundle_getBooleanVector; # llndk=202404
APersistableBundle_getIntVector;
- APersistableBundle_getIntVector; # llndk=202404
APersistableBundle_getLongVector;
- APersistableBundle_getLongVector; # llndk=202404
APersistableBundle_getDoubleVector;
- APersistableBundle_getDoubleVector; # llndk=202404
APersistableBundle_getStringVector;
- APersistableBundle_getStringVector; # llndk=202404
APersistableBundle_getPersistableBundle;
- APersistableBundle_getPersistableBundle; # llndk=202404
APersistableBundle_getBooleanKeys;
- APersistableBundle_getBooleanKeys; # llndk=202404
APersistableBundle_getIntKeys;
- APersistableBundle_getIntKeys; # llndk=202404
APersistableBundle_getLongKeys;
- APersistableBundle_getLongKeys; # llndk=202404
APersistableBundle_getDoubleKeys;
- APersistableBundle_getDoubleKeys; # llndk=202404
APersistableBundle_getStringKeys;
- APersistableBundle_getStringKeys; # llndk=202404
APersistableBundle_getBooleanVectorKeys;
- APersistableBundle_getBooleanVectorKeys; # llndk=202404
APersistableBundle_getIntVectorKeys;
- APersistableBundle_getIntVectorKeys; # llndk=202404
APersistableBundle_getLongVectorKeys;
- APersistableBundle_getLongVectorKeys; # llndk=202404
APersistableBundle_getDoubleVectorKeys;
- APersistableBundle_getDoubleVectorKeys; # llndk=202404
APersistableBundle_getStringVectorKeys;
- APersistableBundle_getStringVectorKeys; # llndk=202404
APersistableBundle_getPersistableBundleKeys;
- APersistableBundle_getPersistableBundleKeys; # llndk=202404
- AServiceManager_openDeclaredPassthroughHal; # systemapi llndk=202404
+ AServiceManager_openDeclaredPassthroughHal; # systemapi llndk
};
LIBBINDER_NDK36 { # introduced=36
global:
AIBinder_Class_setTransactionCodeToFunctionNameMap;
- AIBinder_Class_setTransactionCodeToFunctionNameMap; # llndk=202504
AIBinder_Class_getFunctionName;
- AIBinder_Class_getFunctionName; # llndk=202504
ABinderRpc_registerAccessorProvider; # systemapi
ABinderRpc_unregisterAccessorProvider; # systemapi
ABinderRpc_Accessor_new; # systemapi
@@ -272,6 +229,7 @@
AIBinder_fromPlatformBinder*;
AIBinder_toPlatformBinder*;
AParcel_viewPlatformParcel*;
+ ABinderProcess_disableBackgroundScheduling;
};
local:
*;
diff --git a/libs/binder/ndk/process.cpp b/libs/binder/ndk/process.cpp
index 0072ac3..bcdb959 100644
--- a/libs/binder/ndk/process.cpp
+++ b/libs/binder/ndk/process.cpp
@@ -36,6 +36,10 @@
IPCThreadState::self()->joinThreadPool();
}
+void ABinderProcess_disableBackgroundScheduling(bool disable) {
+ IPCThreadState::disableBackgroundScheduling(disable);
+}
+
binder_status_t ABinderProcess_setupPolling(int* fd) {
return IPCThreadState::self()->setupPolling(fd);
}
diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp
index d6ac4ac..14bc5d2 100644
--- a/libs/binder/ndk/service_manager.cpp
+++ b/libs/binder/ndk/service_manager.cpp
@@ -63,6 +63,9 @@
if (flags & AServiceManager_AddServiceFlag::ADD_SERVICE_DUMP_FLAG_PRIORITY_DEFAULT) {
dumpFlags |= IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT;
}
+ if (flags & AServiceManager_AddServiceFlag::ADD_SERVICE_DUMP_FLAG_PROTO) {
+ dumpFlags |= IServiceManager::DUMP_FLAG_PROTO;
+ }
if (dumpFlags == 0) {
dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT;
}
diff --git a/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp b/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp
index 66be94f..fb92e05 100644
--- a/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp
+++ b/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp
@@ -30,6 +30,8 @@
#include <gtest/gtest.h>
#include <sys/prctl.h>
+static_assert(FLAG_PRIVATE_LOCAL != 0, "Build system configuration breaks stability");
+
using namespace android;
using ::android::binder::Status;
using ::android::internal::Stability;
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index 4545d7b..adef9ea 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -16,7 +16,7 @@
"libdowncast_rs",
"liblibc",
"liblog_rust",
- "libnix",
+ "libzerocopy",
],
host_supported: true,
vendor_available: true,
@@ -140,6 +140,9 @@
"--raw-line",
"use libc::sockaddr;",
],
+ cflags: [
+ "-DANDROID_PLATFORM",
+ ],
shared_libs: [
"libbinder_ndk",
],
@@ -180,6 +183,9 @@
// rustified
"libbinder_ndk_bindgen_flags.txt",
],
+ cflags: [
+ "-DANDROID_PLATFORM",
+ ],
shared_libs: [
"libbinder_ndk_on_trusty_mock",
"libc++",
@@ -200,7 +206,7 @@
"libdowncast_rs",
"liblibc",
"liblog_rust",
- "libnix",
+ "libzerocopy",
],
}
diff --git a/libs/binder/rust/Cargo.toml b/libs/binder/rust/Cargo.toml
new file mode 100644
index 0000000..e5738c5
--- /dev/null
+++ b/libs/binder/rust/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "android-binder"
+version = "0.1.0"
+edition = "2021"
+description = "Safe bindings to Android Binder, restricted to the NDK"
+license = "Apache-2.0"
+
+[dependencies]
+binder-ndk-sys = { package = "android-binder-ndk-sys", version = "0.1", path = "./sys" }
+downcast-rs = "1.2.1"
+libc = "0.2.159"
+
+[lints.rust.unexpected_cfgs]
+level = "warn"
+check-cfg = ["cfg(android_vendor)", "cfg(android_ndk)", "cfg(android_vndk)", "cfg(trusty)"]
diff --git a/libs/binder/rust/build.rs b/libs/binder/rust/build.rs
new file mode 100644
index 0000000..f3e6b53
--- /dev/null
+++ b/libs/binder/rust/build.rs
@@ -0,0 +1,4 @@
+fn main() {
+ // Anything with cargo is NDK only. If you want to access anything else, use Soong.
+ println!("cargo::rustc-cfg=android_ndk");
+}
diff --git a/libs/binder/rust/rpcbinder/Android.bp b/libs/binder/rust/rpcbinder/Android.bp
index 174fe8a..46651ce 100644
--- a/libs/binder/rust/rpcbinder/Android.bp
+++ b/libs/binder/rust/rpcbinder/Android.bp
@@ -26,8 +26,8 @@
],
visibility: [
"//device/google/cuttlefish/shared/minidroid/sample",
+ "//hardware/interfaces/security/see:__subpackages__",
"//packages/modules/Virtualization:__subpackages__",
- "//system/software_defined_vehicle:__subpackages__",
],
apex_available: [
"//apex_available:platform",
diff --git a/libs/binder/rust/rpcbinder/src/server/android.rs b/libs/binder/rust/rpcbinder/src/server/android.rs
index 2ab3447..74ce315 100644
--- a/libs/binder/rust/rpcbinder/src/server/android.rs
+++ b/libs/binder/rust/rpcbinder/src/server/android.rs
@@ -18,7 +18,7 @@
use binder::{unstable_api::AsNative, SpIBinder};
use binder_rpc_unstable_bindgen::ARpcServer;
use foreign_types::{foreign_type, ForeignType, ForeignTypeRef};
-use std::ffi::CString;
+use std::ffi::{c_uint, CString};
use std::io::{Error, ErrorKind};
use std::os::unix::io::{IntoRawFd, OwnedFd};
@@ -42,18 +42,29 @@
/// Creates a binder RPC server, serving the supplied binder service implementation on the given
/// vsock port. Only connections from the given CID are accepted.
///
- // Set `cid` to libc::VMADDR_CID_ANY to accept connections from any client.
- // Set `cid` to libc::VMADDR_CID_LOCAL to only bind to the local vsock interface.
- pub fn new_vsock(mut service: SpIBinder, cid: u32, port: u32) -> Result<RpcServer, Error> {
+ /// Set `cid` to [`libc::VMADDR_CID_ANY`] to accept connections from any client.
+ /// Set `cid` to [`libc::VMADDR_CID_LOCAL`] to only bind to the local vsock interface.
+ /// Set `port` to [`libc::VMADDR_PORT_ANY`] to pick an ephemeral port.
+ /// The assigned port is returned with RpcServer.
+ pub fn new_vsock(
+ mut service: SpIBinder,
+ cid: u32,
+ port: u32,
+ ) -> Result<(RpcServer, u32 /* assigned_port */), Error> {
let service = service.as_native_mut();
+ let mut assigned_port: c_uint = 0;
// SAFETY: Service ownership is transferring to the server and won't be valid afterward.
// Plus the binder objects are threadsafe.
- unsafe {
+ let server = unsafe {
Self::checked_from_ptr(binder_rpc_unstable_bindgen::ARpcServer_newVsock(
- service, cid, port,
- ))
- }
+ service,
+ cid,
+ port,
+ &mut assigned_port,
+ ))?
+ };
+ Ok((server, assigned_port as _))
}
/// Creates a binder RPC server, serving the supplied binder service implementation on the given
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index 23026e5..6a8a698 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -207,8 +207,10 @@
/// Corresponds to TF_ONE_WAY -- an asynchronous call.
pub const FLAG_ONEWAY: TransactionFlags = sys::FLAG_ONEWAY;
/// Corresponds to TF_CLEAR_BUF -- clear transaction buffers after call is made.
+#[cfg(not(android_ndk))]
pub const FLAG_CLEAR_BUF: TransactionFlags = sys::FLAG_CLEAR_BUF;
/// Set to the vendor flag if we are building for the VNDK, 0 otherwise
+#[cfg(not(android_ndk))]
pub const FLAG_PRIVATE_LOCAL: TransactionFlags = sys::FLAG_PRIVATE_LOCAL;
/// Internal interface of binder local or remote objects for making
@@ -221,7 +223,7 @@
fn is_binder_alive(&self) -> bool;
/// Indicate that the service intends to receive caller security contexts.
- #[cfg(not(android_vndk))]
+ #[cfg(not(any(android_vndk, android_ndk)))]
fn set_requesting_sid(&mut self, enable: bool);
/// Dump this object to the given file handle
@@ -346,7 +348,6 @@
panic!("Expected non-null class pointer from AIBinder_Class_define!");
}
sys::AIBinder_Class_setOnDump(class, Some(I::on_dump));
- sys::AIBinder_Class_setHandleShellCommand(class, None);
class
};
InterfaceClass(ptr)
@@ -714,7 +715,7 @@
pub struct BinderFeatures {
/// Indicates that the service intends to receive caller security contexts. This must be true
/// for `ThreadState::with_calling_sid` to work.
- #[cfg(not(android_vndk))]
+ #[cfg(not(any(android_vndk, android_ndk)))]
pub set_requesting_sid: bool,
// Ensure that clients include a ..BinderFeatures::default() to preserve backwards compatibility
// when new fields are added. #[non_exhaustive] doesn't work because it prevents struct
@@ -916,8 +917,12 @@
impl $native {
/// Create a new binder service.
pub fn new_binder<T: $interface + Sync + Send + 'static>(inner: T, features: $crate::BinderFeatures) -> $crate::Strong<dyn $interface> {
+ #[cfg(not(android_ndk))]
let mut binder = $crate::binder_impl::Binder::new_with_stability($native(Box::new(inner)), $stability);
- #[cfg(not(android_vndk))]
+ #[cfg(android_ndk)]
+ let mut binder = $crate::binder_impl::Binder::new($native(Box::new(inner)));
+
+ #[cfg(not(any(android_vndk, android_ndk)))]
$crate::binder_impl::IBinderInternal::set_requesting_sid(&mut binder, features.set_requesting_sid);
$crate::Strong::new(Box::new(binder))
}
@@ -1196,5 +1201,45 @@
Ok(v.map(|v| v.into_iter().map(Self).collect()))
}
}
+
+ impl std::ops::BitOr for $enum {
+ type Output = Self;
+ fn bitor(self, rhs: Self) -> Self {
+ Self(self.0 | rhs.0)
+ }
+ }
+
+ impl std::ops::BitOrAssign for $enum {
+ fn bitor_assign(&mut self, rhs: Self) {
+ self.0 = self.0 | rhs.0;
+ }
+ }
+
+ impl std::ops::BitAnd for $enum {
+ type Output = Self;
+ fn bitand(self, rhs: Self) -> Self {
+ Self(self.0 & rhs.0)
+ }
+ }
+
+ impl std::ops::BitAndAssign for $enum {
+ fn bitand_assign(&mut self, rhs: Self) {
+ self.0 = self.0 & rhs.0;
+ }
+ }
+
+ impl std::ops::BitXor for $enum {
+ type Output = Self;
+ fn bitxor(self, rhs: Self) -> Self {
+ Self(self.0 ^ rhs.0)
+ }
+ }
+
+ impl std::ops::BitXorAssign for $enum {
+ fn bitxor_assign(&mut self, rhs: Self) {
+ self.0 = self.0 ^ rhs.0;
+ }
+ }
+
};
}
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs
index f7f3f35..0026f21 100644
--- a/libs/binder/rust/src/lib.rs
+++ b/libs/binder/rust/src/lib.rs
@@ -99,12 +99,14 @@
mod error;
mod native;
mod parcel;
+#[cfg(not(trusty))]
+mod persistable_bundle;
mod proxy;
-#[cfg(not(trusty))]
+#[cfg(not(any(trusty, android_ndk)))]
mod service;
-#[cfg(not(trusty))]
+#[cfg(not(any(trusty, android_ndk)))]
mod state;
-#[cfg(not(any(android_vendor, android_vndk)))]
+#[cfg(not(any(android_vendor, android_ndk, android_vndk, trusty)))]
mod system_only;
use binder_ndk_sys as sys;
@@ -113,17 +115,22 @@
pub use binder::{BinderFeatures, FromIBinder, IBinder, Interface, Strong, Weak};
pub use error::{ExceptionCode, IntoBinderResult, Status, StatusCode};
pub use parcel::{ParcelFileDescriptor, Parcelable, ParcelableHolder};
-pub use proxy::{DeathRecipient, SpIBinder, WpIBinder};
#[cfg(not(trusty))]
+pub use persistable_bundle::{PersistableBundle, ValueType};
+pub use proxy::{DeathRecipient, SpIBinder, WpIBinder};
+#[cfg(not(any(trusty, android_ndk)))]
pub use service::{
add_service, check_interface, check_service, force_lazy_services_persist,
- get_declared_instances, get_interface, get_service, is_declared, is_handling_transaction,
- register_lazy_service, wait_for_interface, wait_for_service, LazyServiceGuard,
+ get_declared_instances, is_declared, is_handling_transaction, register_lazy_service,
+ wait_for_interface, wait_for_service, LazyServiceGuard,
};
-#[cfg(not(trusty))]
+#[cfg(not(any(trusty, android_ndk)))]
+#[allow(deprecated)]
+pub use service::{get_interface, get_service};
+#[cfg(not(any(trusty, android_ndk)))]
pub use state::{ProcessState, ThreadState};
-#[cfg(not(any(android_vendor, android_vndk)))]
-pub use system_only::{delegate_accessor, Accessor, ConnectionInfo};
+#[cfg(not(any(android_vendor, android_vndk, android_ndk, trusty)))]
+pub use system_only::{delegate_accessor, Accessor, AccessorProvider, ConnectionInfo};
/// Binder result containing a [`Status`] on error.
pub type Result<T> = std::result::Result<T, Status>;
@@ -134,9 +141,10 @@
pub use crate::binder::{
IBinderInternal, InterfaceClass, LocalStabilityType, Remotable, Stability, StabilityType,
ToAsyncInterface, ToSyncInterface, TransactionCode, TransactionFlags, VintfStabilityType,
- FIRST_CALL_TRANSACTION, FLAG_CLEAR_BUF, FLAG_ONEWAY, FLAG_PRIVATE_LOCAL,
- LAST_CALL_TRANSACTION,
+ FIRST_CALL_TRANSACTION, FLAG_ONEWAY, LAST_CALL_TRANSACTION,
};
+ #[cfg(not(android_ndk))]
+ pub use crate::binder::{FLAG_CLEAR_BUF, FLAG_PRIVATE_LOCAL};
pub use crate::binder_async::BinderAsyncRuntime;
pub use crate::error::status_t;
pub use crate::native::Binder;
diff --git a/libs/binder/rust/src/native.rs b/libs/binder/rust/src/native.rs
index c87cc94..9e1cfd6 100644
--- a/libs/binder/rust/src/native.rs
+++ b/libs/binder/rust/src/native.rs
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-use crate::binder::{
- AsNative, Interface, InterfaceClassMethods, Remotable, Stability, TransactionCode,
-};
+#[cfg(not(android_ndk))]
+use crate::binder::Stability;
+use crate::binder::{AsNative, Interface, InterfaceClassMethods, Remotable, TransactionCode};
use crate::error::{status_result, status_t, Result, StatusCode};
use crate::parcel::{BorrowedParcel, Serialize};
use crate::proxy::SpIBinder;
@@ -76,14 +76,32 @@
/// This moves the `rust_object` into an owned [`Box`] and Binder will
/// manage its lifetime.
pub fn new(rust_object: T) -> Binder<T> {
- Self::new_with_stability(rust_object, Stability::default())
+ #[cfg(not(android_ndk))]
+ {
+ Self::new_with_stability(rust_object, Stability::default())
+ }
+ #[cfg(android_ndk)]
+ {
+ Self::new_unmarked(rust_object)
+ }
}
/// Create a new Binder remotable object with the given stability
///
/// This moves the `rust_object` into an owned [`Box`] and Binder will
/// manage its lifetime.
+ #[cfg(not(android_ndk))]
pub fn new_with_stability(rust_object: T, stability: Stability) -> Binder<T> {
+ let mut binder = Self::new_unmarked(rust_object);
+ binder.mark_stability(stability);
+ binder
+ }
+
+ /// Creates a new Binder remotable object with unset stability
+ ///
+ /// This is internal because normally we want to set the stability explicitly,
+ /// however for the NDK variant we cannot mark the stability.
+ fn new_unmarked(rust_object: T) -> Binder<T> {
let class = T::get_class();
let rust_object = Box::into_raw(Box::new(rust_object));
// Safety: `AIBinder_new` expects a valid class pointer (which we
@@ -93,9 +111,7 @@
// decremented via `AIBinder_decStrong` when the reference lifetime
// ends.
let ibinder = unsafe { sys::AIBinder_new(class.into(), rust_object as *mut c_void) };
- let mut binder = Binder { ibinder, rust_object };
- binder.mark_stability(stability);
- binder
+ Binder { ibinder, rust_object }
}
/// Set the extension of a binder interface. This allows a downstream
@@ -189,6 +205,7 @@
}
/// Mark this binder object with the given stability guarantee
+ #[cfg(not(android_ndk))]
fn mark_stability(&mut self, stability: Stability) {
match stability {
Stability::Local => self.mark_local_stability(),
@@ -215,7 +232,7 @@
/// Mark this binder object with local stability, which is vendor if we are
/// building for android_vendor and system otherwise.
- #[cfg(not(android_vendor))]
+ #[cfg(not(any(android_vendor, android_ndk)))]
fn mark_local_stability(&mut self) {
// Safety: Self always contains a valid `AIBinder` pointer, so we can
// always call this C API safely.
diff --git a/libs/binder/rust/src/parcel.rs b/libs/binder/rust/src/parcel.rs
index 3bfc425..2d40ced 100644
--- a/libs/binder/rust/src/parcel.rs
+++ b/libs/binder/rust/src/parcel.rs
@@ -184,7 +184,7 @@
/// Safety: The `BorrowedParcel` constructors guarantee that a `BorrowedParcel`
/// object will always contain a valid pointer to an `AParcel`.
-unsafe impl<'a> AsNative<sys::AParcel> for BorrowedParcel<'a> {
+unsafe impl AsNative<sys::AParcel> for BorrowedParcel<'_> {
fn as_native(&self) -> *const sys::AParcel {
self.ptr.as_ptr()
}
@@ -195,8 +195,9 @@
}
// Data serialization methods
-impl<'a> BorrowedParcel<'a> {
+impl BorrowedParcel<'_> {
/// Data written to parcelable is zero'd before being deleted or reallocated.
+ #[cfg(not(android_ndk))]
pub fn mark_sensitive(&mut self) {
// Safety: guaranteed to have a parcel object, and this method never fails
unsafe { sys::AParcel_markSensitive(self.as_native()) }
@@ -333,7 +334,7 @@
/// A segment of a writable parcel, used for [`BorrowedParcel::sized_write`].
pub struct WritableSubParcel<'a>(BorrowedParcel<'a>);
-impl<'a> WritableSubParcel<'a> {
+impl WritableSubParcel<'_> {
/// Write a type that implements [`Serialize`] to the sub-parcel.
pub fn write<S: Serialize + ?Sized>(&mut self, parcelable: &S) -> Result<()> {
parcelable.serialize(&mut self.0)
@@ -342,6 +343,7 @@
impl Parcel {
/// Data written to parcelable is zero'd before being deleted or reallocated.
+ #[cfg(not(android_ndk))]
pub fn mark_sensitive(&mut self) {
self.borrowed().mark_sensitive()
}
@@ -438,7 +440,7 @@
}
// Data deserialization methods
-impl<'a> BorrowedParcel<'a> {
+impl BorrowedParcel<'_> {
/// Attempt to read a type that implements [`Deserialize`] from this parcel.
pub fn read<D: Deserialize>(&self) -> Result<D> {
D::deserialize(self)
@@ -563,7 +565,7 @@
end_position: i32,
}
-impl<'a> ReadableSubParcel<'a> {
+impl ReadableSubParcel<'_> {
/// Read a type that implements [`Deserialize`] from the sub-parcel.
pub fn read<D: Deserialize>(&self) -> Result<D> {
D::deserialize(&self.parcel)
@@ -647,7 +649,7 @@
}
// Internal APIs
-impl<'a> BorrowedParcel<'a> {
+impl BorrowedParcel<'_> {
pub(crate) fn write_binder(&mut self, binder: Option<&SpIBinder>) -> Result<()> {
// Safety: `BorrowedParcel` always contains a valid pointer to an
// `AParcel`. `AsNative` for `Option<SpIBinder`> will either return
@@ -700,7 +702,7 @@
}
}
-impl<'a> fmt::Debug for BorrowedParcel<'a> {
+impl fmt::Debug for BorrowedParcel<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("BorrowedParcel").finish()
}
diff --git a/libs/binder/rust/src/persistable_bundle.rs b/libs/binder/rust/src/persistable_bundle.rs
new file mode 100644
index 0000000..8639c0d
--- /dev/null
+++ b/libs/binder/rust/src/persistable_bundle.rs
@@ -0,0 +1,1076 @@
+/*
+ * Copyright (C) 2025 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.
+ */
+
+use crate::{
+ binder::AsNative,
+ error::{status_result, StatusCode},
+ impl_deserialize_for_unstructured_parcelable, impl_serialize_for_unstructured_parcelable,
+ parcel::{BorrowedParcel, UnstructuredParcelable},
+};
+use binder_ndk_sys::{
+ APersistableBundle, APersistableBundle_delete, APersistableBundle_dup,
+ APersistableBundle_erase, APersistableBundle_getBoolean, APersistableBundle_getBooleanKeys,
+ APersistableBundle_getBooleanVector, APersistableBundle_getBooleanVectorKeys,
+ APersistableBundle_getDouble, APersistableBundle_getDoubleKeys,
+ APersistableBundle_getDoubleVector, APersistableBundle_getDoubleVectorKeys,
+ APersistableBundle_getInt, APersistableBundle_getIntKeys, APersistableBundle_getIntVector,
+ APersistableBundle_getIntVectorKeys, APersistableBundle_getLong,
+ APersistableBundle_getLongKeys, APersistableBundle_getLongVector,
+ APersistableBundle_getLongVectorKeys, APersistableBundle_getPersistableBundle,
+ APersistableBundle_getPersistableBundleKeys, APersistableBundle_getString,
+ APersistableBundle_getStringKeys, APersistableBundle_getStringVector,
+ APersistableBundle_getStringVectorKeys, APersistableBundle_isEqual, APersistableBundle_new,
+ APersistableBundle_putBoolean, APersistableBundle_putBooleanVector,
+ APersistableBundle_putDouble, APersistableBundle_putDoubleVector, APersistableBundle_putInt,
+ APersistableBundle_putIntVector, APersistableBundle_putLong, APersistableBundle_putLongVector,
+ APersistableBundle_putPersistableBundle, APersistableBundle_putString,
+ APersistableBundle_putStringVector, APersistableBundle_readFromParcel, APersistableBundle_size,
+ APersistableBundle_writeToParcel, APERSISTABLEBUNDLE_ALLOCATOR_FAILED,
+ APERSISTABLEBUNDLE_KEY_NOT_FOUND,
+};
+use std::ffi::{c_char, c_void, CStr, CString, NulError};
+use std::ptr::{null_mut, slice_from_raw_parts_mut, NonNull};
+use zerocopy::FromZeros;
+
+/// A mapping from string keys to values of various types.
+#[derive(Debug)]
+pub struct PersistableBundle(NonNull<APersistableBundle>);
+
+impl PersistableBundle {
+ /// Creates a new `PersistableBundle`.
+ pub fn new() -> Self {
+ // SAFETY: APersistableBundle_new doesn't actually have any safety requirements.
+ let bundle = unsafe { APersistableBundle_new() };
+ Self(NonNull::new(bundle).expect("Allocated APersistableBundle was null"))
+ }
+
+ /// Returns the number of mappings in the bundle.
+ pub fn size(&self) -> usize {
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`.
+ unsafe { APersistableBundle_size(self.0.as_ptr()) }
+ .try_into()
+ .expect("APersistableBundle_size returned a negative size")
+ }
+
+ /// Removes any entry with the given key.
+ ///
+ /// Returns an error if the given key contains a NUL character, otherwise returns whether there
+ /// was any entry to remove.
+ pub fn remove(&mut self, key: &str) -> Result<bool, NulError> {
+ let key = CString::new(key)?;
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
+ // to be valid for the duration of this call.
+ Ok(unsafe { APersistableBundle_erase(self.0.as_ptr(), key.as_ptr()) != 0 })
+ }
+
+ /// Inserts a key-value pair into the bundle.
+ ///
+ /// If the key is already present then its value will be overwritten by the given value.
+ ///
+ /// Returns an error if the key contains a NUL character.
+ pub fn insert_bool(&mut self, key: &str, value: bool) -> Result<(), NulError> {
+ let key = CString::new(key)?;
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
+ // to be valid for the duration of this call.
+ unsafe {
+ APersistableBundle_putBoolean(self.0.as_ptr(), key.as_ptr(), value);
+ }
+ Ok(())
+ }
+
+ /// Inserts a key-value pair into the bundle.
+ ///
+ /// If the key is already present then its value will be overwritten by the given value.
+ ///
+ /// Returns an error if the key contains a NUL character.
+ pub fn insert_int(&mut self, key: &str, value: i32) -> Result<(), NulError> {
+ let key = CString::new(key)?;
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
+ // to be valid for the duration of this call.
+ unsafe {
+ APersistableBundle_putInt(self.0.as_ptr(), key.as_ptr(), value);
+ }
+ Ok(())
+ }
+
+ /// Inserts a key-value pair into the bundle.
+ ///
+ /// If the key is already present then its value will be overwritten by the given value.
+ ///
+ /// Returns an error if the key contains a NUL character.
+ pub fn insert_long(&mut self, key: &str, value: i64) -> Result<(), NulError> {
+ let key = CString::new(key)?;
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
+ // to be valid for the duration of this call.
+ unsafe {
+ APersistableBundle_putLong(self.0.as_ptr(), key.as_ptr(), value);
+ }
+ Ok(())
+ }
+
+ /// Inserts a key-value pair into the bundle.
+ ///
+ /// If the key is already present then its value will be overwritten by the given value.
+ ///
+ /// Returns an error if the key contains a NUL character.
+ pub fn insert_double(&mut self, key: &str, value: f64) -> Result<(), NulError> {
+ let key = CString::new(key)?;
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
+ // to be valid for the duration of this call.
+ unsafe {
+ APersistableBundle_putDouble(self.0.as_ptr(), key.as_ptr(), value);
+ }
+ Ok(())
+ }
+
+ /// Inserts a key-value pair into the bundle.
+ ///
+ /// If the key is already present then its value will be overwritten by the given value.
+ ///
+ /// Returns an error if the key or value contains a NUL character.
+ pub fn insert_string(&mut self, key: &str, value: &str) -> Result<(), NulError> {
+ let key = CString::new(key)?;
+ let value = CString::new(value)?;
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. The pointer returned by `CStr::as_ptr` is guaranteed
+ // to be valid for the duration of this call.
+ unsafe {
+ APersistableBundle_putString(self.0.as_ptr(), key.as_ptr(), value.as_ptr());
+ }
+ Ok(())
+ }
+
+ /// Inserts a key-value pair into the bundle.
+ ///
+ /// If the key is already present then its value will be overwritten by the given value.
+ ///
+ /// Returns an error if the key contains a NUL character.
+ pub fn insert_bool_vec(&mut self, key: &str, value: &[bool]) -> Result<(), NulError> {
+ let key = CString::new(key)?;
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
+ // to be valid for the duration of this call, and likewise the pointer returned by
+ // `value.as_ptr()` is guaranteed to be valid for at least `value.len()` values for the
+ // duration of the call.
+ unsafe {
+ APersistableBundle_putBooleanVector(
+ self.0.as_ptr(),
+ key.as_ptr(),
+ value.as_ptr(),
+ value.len().try_into().unwrap(),
+ );
+ }
+ Ok(())
+ }
+
+ /// Inserts a key-value pair into the bundle.
+ ///
+ /// If the key is already present then its value will be overwritten by the given value.
+ ///
+ /// Returns an error if the key contains a NUL character.
+ pub fn insert_int_vec(&mut self, key: &str, value: &[i32]) -> Result<(), NulError> {
+ let key = CString::new(key)?;
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
+ // to be valid for the duration of this call, and likewise the pointer returned by
+ // `value.as_ptr()` is guaranteed to be valid for at least `value.len()` values for the
+ // duration of the call.
+ unsafe {
+ APersistableBundle_putIntVector(
+ self.0.as_ptr(),
+ key.as_ptr(),
+ value.as_ptr(),
+ value.len().try_into().unwrap(),
+ );
+ }
+ Ok(())
+ }
+
+ /// Inserts a key-value pair into the bundle.
+ ///
+ /// If the key is already present then its value will be overwritten by the given value.
+ ///
+ /// Returns an error if the key contains a NUL character.
+ pub fn insert_long_vec(&mut self, key: &str, value: &[i64]) -> Result<(), NulError> {
+ let key = CString::new(key)?;
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
+ // to be valid for the duration of this call, and likewise the pointer returned by
+ // `value.as_ptr()` is guaranteed to be valid for at least `value.len()` values for the
+ // duration of the call.
+ unsafe {
+ APersistableBundle_putLongVector(
+ self.0.as_ptr(),
+ key.as_ptr(),
+ value.as_ptr(),
+ value.len().try_into().unwrap(),
+ );
+ }
+ Ok(())
+ }
+
+ /// Inserts a key-value pair into the bundle.
+ ///
+ /// If the key is already present then its value will be overwritten by the given value.
+ ///
+ /// Returns an error if the key contains a NUL character.
+ pub fn insert_double_vec(&mut self, key: &str, value: &[f64]) -> Result<(), NulError> {
+ let key = CString::new(key)?;
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
+ // to be valid for the duration of this call, and likewise the pointer returned by
+ // `value.as_ptr()` is guaranteed to be valid for at least `value.len()` values for the
+ // duration of the call.
+ unsafe {
+ APersistableBundle_putDoubleVector(
+ self.0.as_ptr(),
+ key.as_ptr(),
+ value.as_ptr(),
+ value.len().try_into().unwrap(),
+ );
+ }
+ Ok(())
+ }
+
+ /// Inserts a key-value pair into the bundle.
+ ///
+ /// If the key is already present then its value will be overwritten by the given value.
+ ///
+ /// Returns an error if the key contains a NUL character.
+ pub fn insert_string_vec<'a, T: ToString + 'a>(
+ &mut self,
+ key: &str,
+ value: impl IntoIterator<Item = &'a T>,
+ ) -> Result<(), NulError> {
+ let key = CString::new(key)?;
+ // We need to collect the new `CString`s into something first so that they live long enough
+ // for their pointers to be valid for the `APersistableBundle_putStringVector` call below.
+ let c_strings = value
+ .into_iter()
+ .map(|s| CString::new(s.to_string()))
+ .collect::<Result<Vec<_>, NulError>>()?;
+ let char_pointers = c_strings.iter().map(|s| s.as_ptr()).collect::<Vec<_>>();
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
+ // to be valid for the duration of this call, and likewise the pointer returned by
+ // `value.as_ptr()` is guaranteed to be valid for at least `value.len()` values for the
+ // duration of the call.
+ unsafe {
+ APersistableBundle_putStringVector(
+ self.0.as_ptr(),
+ key.as_ptr(),
+ char_pointers.as_ptr(),
+ char_pointers.len().try_into().unwrap(),
+ );
+ }
+ Ok(())
+ }
+
+ /// Inserts a key-value pair into the bundle.
+ ///
+ /// If the key is already present then its value will be overwritten by the given value.
+ ///
+ /// Returns an error if the key contains a NUL character.
+ pub fn insert_persistable_bundle(
+ &mut self,
+ key: &str,
+ value: &PersistableBundle,
+ ) -> Result<(), NulError> {
+ let key = CString::new(key)?;
+ // SAFETY: The wrapped `APersistableBundle` pointers are guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`s. The pointer returned by `CStr::as_ptr` is
+ // guaranteed to be valid for the duration of this call, and
+ // `APersistableBundle_putPersistableBundle` does a deep copy so that is all that is
+ // required.
+ unsafe {
+ APersistableBundle_putPersistableBundle(
+ self.0.as_ptr(),
+ key.as_ptr(),
+ value.0.as_ptr(),
+ );
+ }
+ Ok(())
+ }
+
+ /// Gets the boolean value associated with the given key.
+ ///
+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
+ /// in the bundle.
+ pub fn get_bool(&self, key: &str) -> Result<Option<bool>, NulError> {
+ let key = CString::new(key)?;
+ let mut value = false;
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
+ // to be valid for the duration of this call. The value pointer must be valid because it
+ // comes from a reference.
+ if unsafe { APersistableBundle_getBoolean(self.0.as_ptr(), key.as_ptr(), &mut value) } {
+ Ok(Some(value))
+ } else {
+ Ok(None)
+ }
+ }
+
+ /// Gets the i32 value associated with the given key.
+ ///
+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
+ /// in the bundle.
+ pub fn get_int(&self, key: &str) -> Result<Option<i32>, NulError> {
+ let key = CString::new(key)?;
+ let mut value = 0;
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
+ // to be valid for the duration of this call. The value pointer must be valid because it
+ // comes from a reference.
+ if unsafe { APersistableBundle_getInt(self.0.as_ptr(), key.as_ptr(), &mut value) } {
+ Ok(Some(value))
+ } else {
+ Ok(None)
+ }
+ }
+
+ /// Gets the i64 value associated with the given key.
+ ///
+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
+ /// in the bundle.
+ pub fn get_long(&self, key: &str) -> Result<Option<i64>, NulError> {
+ let key = CString::new(key)?;
+ let mut value = 0;
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
+ // to be valid for the duration of this call. The value pointer must be valid because it
+ // comes from a reference.
+ if unsafe { APersistableBundle_getLong(self.0.as_ptr(), key.as_ptr(), &mut value) } {
+ Ok(Some(value))
+ } else {
+ Ok(None)
+ }
+ }
+
+ /// Gets the f64 value associated with the given key.
+ ///
+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
+ /// in the bundle.
+ pub fn get_double(&self, key: &str) -> Result<Option<f64>, NulError> {
+ let key = CString::new(key)?;
+ let mut value = 0.0;
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
+ // to be valid for the duration of this call. The value pointer must be valid because it
+ // comes from a reference.
+ if unsafe { APersistableBundle_getDouble(self.0.as_ptr(), key.as_ptr(), &mut value) } {
+ Ok(Some(value))
+ } else {
+ Ok(None)
+ }
+ }
+
+ /// Gets the string value associated with the given key.
+ ///
+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
+ /// in the bundle.
+ pub fn get_string(&self, key: &str) -> Result<Option<String>, NulError> {
+ let key = CString::new(key)?;
+ let mut value = null_mut();
+ let mut allocated_size: usize = 0;
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
+ // to be valid for the lifetime of `key`. The value pointer must be valid because it comes
+ // from a reference.
+ let value_size_bytes = unsafe {
+ APersistableBundle_getString(
+ self.0.as_ptr(),
+ key.as_ptr(),
+ &mut value,
+ Some(string_allocator),
+ (&raw mut allocated_size).cast(),
+ )
+ };
+ match value_size_bytes {
+ APERSISTABLEBUNDLE_KEY_NOT_FOUND => Ok(None),
+ APERSISTABLEBUNDLE_ALLOCATOR_FAILED => {
+ panic!("APersistableBundle_getString failed to allocate string");
+ }
+ _ => {
+ let raw_slice = slice_from_raw_parts_mut(value.cast(), allocated_size);
+ // SAFETY: The pointer was returned from string_allocator, which used
+ // `Box::into_raw`, and we've got the appropriate size back from allocated_size.
+ let boxed_slice: Box<[u8]> = unsafe { Box::from_raw(raw_slice) };
+ assert_eq!(
+ allocated_size,
+ usize::try_from(value_size_bytes)
+ .expect("APersistableBundle_getString returned negative value size")
+ + 1
+ );
+ let c_string = CString::from_vec_with_nul(boxed_slice.into())
+ .expect("APersistableBundle_getString returned string missing NUL byte");
+ let string = c_string
+ .into_string()
+ .expect("APersistableBundle_getString returned invalid UTF-8");
+ Ok(Some(string))
+ }
+ }
+ }
+
+ /// Gets the vector of `T` associated with the given key.
+ ///
+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
+ /// in the bundle.
+ ///
+ /// `get_func` should be one of the `APersistableBundle_get*Vector` functions from
+ /// `binder_ndk_sys`.
+ ///
+ /// # Safety
+ ///
+ /// `get_func` must only require that the pointers it takes are valid for the duration of the
+ /// call. It must allow a null pointer for the buffer, and must return the size in bytes of
+ /// buffer it requires. If it is given a non-null buffer pointer it must write that number of
+ /// bytes to the buffer, which must be a whole number of valid `T` values.
+ unsafe fn get_vec<T: Clone>(
+ &self,
+ key: &str,
+ default: T,
+ get_func: unsafe extern "C" fn(
+ *const APersistableBundle,
+ *const c_char,
+ *mut T,
+ i32,
+ ) -> i32,
+ ) -> Result<Option<Vec<T>>, NulError> {
+ let key = CString::new(key)?;
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
+ // to be valid for the lifetime of `key`. A null pointer is allowed for the buffer.
+ match unsafe { get_func(self.0.as_ptr(), key.as_ptr(), null_mut(), 0) } {
+ APERSISTABLEBUNDLE_KEY_NOT_FOUND => Ok(None),
+ APERSISTABLEBUNDLE_ALLOCATOR_FAILED => {
+ panic!("APersistableBundle_getStringVector failed to allocate string");
+ }
+ required_buffer_size => {
+ let mut value = vec![
+ default;
+ usize::try_from(required_buffer_size).expect(
+ "APersistableBundle_get*Vector returned invalid size"
+ ) / size_of::<T>()
+ ];
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for
+ // the lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()`
+ // is guaranteed to be valid for the lifetime of `key`. The value buffer pointer is
+ // valid as it comes from the Vec we just allocated.
+ match unsafe {
+ get_func(
+ self.0.as_ptr(),
+ key.as_ptr(),
+ value.as_mut_ptr(),
+ (value.len() * size_of::<T>()).try_into().unwrap(),
+ )
+ } {
+ APERSISTABLEBUNDLE_KEY_NOT_FOUND => {
+ panic!("APersistableBundle_get*Vector failed to find key after first finding it");
+ }
+ APERSISTABLEBUNDLE_ALLOCATOR_FAILED => {
+ panic!("APersistableBundle_getStringVector failed to allocate string");
+ }
+ _ => Ok(Some(value)),
+ }
+ }
+ }
+ }
+
+ /// Gets the boolean vector value associated with the given key.
+ ///
+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
+ /// in the bundle.
+ pub fn get_bool_vec(&self, key: &str) -> Result<Option<Vec<bool>>, NulError> {
+ // SAFETY: APersistableBundle_getBooleanVector fulfils all the safety requirements of
+ // `get_vec`.
+ unsafe { self.get_vec(key, Default::default(), APersistableBundle_getBooleanVector) }
+ }
+
+ /// Gets the i32 vector value associated with the given key.
+ ///
+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
+ /// in the bundle.
+ pub fn get_int_vec(&self, key: &str) -> Result<Option<Vec<i32>>, NulError> {
+ // SAFETY: APersistableBundle_getIntVector fulfils all the safety requirements of
+ // `get_vec`.
+ unsafe { self.get_vec(key, Default::default(), APersistableBundle_getIntVector) }
+ }
+
+ /// Gets the i64 vector value associated with the given key.
+ ///
+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
+ /// in the bundle.
+ pub fn get_long_vec(&self, key: &str) -> Result<Option<Vec<i64>>, NulError> {
+ // SAFETY: APersistableBundle_getLongVector fulfils all the safety requirements of
+ // `get_vec`.
+ unsafe { self.get_vec(key, Default::default(), APersistableBundle_getLongVector) }
+ }
+
+ /// Gets the f64 vector value associated with the given key.
+ ///
+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
+ /// in the bundle.
+ pub fn get_double_vec(&self, key: &str) -> Result<Option<Vec<f64>>, NulError> {
+ // SAFETY: APersistableBundle_getDoubleVector fulfils all the safety requirements of
+ // `get_vec`.
+ unsafe { self.get_vec(key, Default::default(), APersistableBundle_getDoubleVector) }
+ }
+
+ /// Gets the string vector value associated with the given key.
+ ///
+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
+ /// in the bundle.
+ pub fn get_string_vec(&self, key: &str) -> Result<Option<Vec<String>>, NulError> {
+ if let Some(value) =
+ // SAFETY: `get_string_vector_with_allocator` fulfils all the safety requirements of
+ // `get_vec`.
+ unsafe { self.get_vec(key, null_mut(), get_string_vector_with_allocator) }?
+ {
+ Ok(Some(
+ value
+ .into_iter()
+ .map(|s| {
+ // SAFETY: The pointer was returned from `string_allocator`, which used
+ // `Box::into_raw`, and `APersistableBundle_getStringVector` should have
+ // written valid bytes to it including a NUL terminator in the last
+ // position.
+ let string_length = unsafe { CStr::from_ptr(s) }.count_bytes();
+ let raw_slice = slice_from_raw_parts_mut(s.cast(), string_length + 1);
+ // SAFETY: The pointer was returned from `string_allocator`, which used
+ // `Box::into_raw`, and we've got the appropriate size back by checking the
+ // length of the string.
+ let boxed_slice: Box<[u8]> = unsafe { Box::from_raw(raw_slice) };
+ let c_string = CString::from_vec_with_nul(boxed_slice.into()).expect(
+ "APersistableBundle_getStringVector returned string missing NUL byte",
+ );
+ c_string
+ .into_string()
+ .expect("APersistableBundle_getStringVector returned invalid UTF-8")
+ })
+ .collect(),
+ ))
+ } else {
+ Ok(None)
+ }
+ }
+
+ /// Gets the `PersistableBundle` value associated with the given key.
+ ///
+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
+ /// in the bundle.
+ pub fn get_persistable_bundle(&self, key: &str) -> Result<Option<Self>, NulError> {
+ let key = CString::new(key)?;
+ let mut value = null_mut();
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
+ // to be valid for the lifetime of `key`. The value pointer must be valid because it comes
+ // from a reference.
+ if unsafe {
+ APersistableBundle_getPersistableBundle(self.0.as_ptr(), key.as_ptr(), &mut value)
+ } {
+ Ok(Some(Self(NonNull::new(value).expect(
+ "APersistableBundle_getPersistableBundle returned true but didn't set outBundle",
+ ))))
+ } else {
+ Ok(None)
+ }
+ }
+
+ /// Calls the appropriate `APersistableBundle_get*Keys` function for the given `value_type`,
+ /// with our `string_allocator` and a null context pointer.
+ ///
+ /// # Safety
+ ///
+ /// `out_keys` must either be null or point to a buffer of at least `buffer_size_bytes` bytes,
+ /// properly aligned for `T`, and not otherwise accessed for the duration of the call.
+ unsafe fn get_keys_raw(
+ &self,
+ value_type: ValueType,
+ out_keys: *mut *mut c_char,
+ buffer_size_bytes: i32,
+ ) -> i32 {
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. Our caller guarantees an appropriate value for
+ // `out_keys` and `buffer_size_bytes`.
+ unsafe {
+ match value_type {
+ ValueType::Boolean => APersistableBundle_getBooleanKeys(
+ self.0.as_ptr(),
+ out_keys,
+ buffer_size_bytes,
+ Some(string_allocator),
+ null_mut(),
+ ),
+ ValueType::Integer => APersistableBundle_getIntKeys(
+ self.0.as_ptr(),
+ out_keys,
+ buffer_size_bytes,
+ Some(string_allocator),
+ null_mut(),
+ ),
+ ValueType::Long => APersistableBundle_getLongKeys(
+ self.0.as_ptr(),
+ out_keys,
+ buffer_size_bytes,
+ Some(string_allocator),
+ null_mut(),
+ ),
+ ValueType::Double => APersistableBundle_getDoubleKeys(
+ self.0.as_ptr(),
+ out_keys,
+ buffer_size_bytes,
+ Some(string_allocator),
+ null_mut(),
+ ),
+ ValueType::String => APersistableBundle_getStringKeys(
+ self.0.as_ptr(),
+ out_keys,
+ buffer_size_bytes,
+ Some(string_allocator),
+ null_mut(),
+ ),
+ ValueType::BooleanVector => APersistableBundle_getBooleanVectorKeys(
+ self.0.as_ptr(),
+ out_keys,
+ buffer_size_bytes,
+ Some(string_allocator),
+ null_mut(),
+ ),
+ ValueType::IntegerVector => APersistableBundle_getIntVectorKeys(
+ self.0.as_ptr(),
+ out_keys,
+ buffer_size_bytes,
+ Some(string_allocator),
+ null_mut(),
+ ),
+ ValueType::LongVector => APersistableBundle_getLongVectorKeys(
+ self.0.as_ptr(),
+ out_keys,
+ buffer_size_bytes,
+ Some(string_allocator),
+ null_mut(),
+ ),
+ ValueType::DoubleVector => APersistableBundle_getDoubleVectorKeys(
+ self.0.as_ptr(),
+ out_keys,
+ buffer_size_bytes,
+ Some(string_allocator),
+ null_mut(),
+ ),
+ ValueType::StringVector => APersistableBundle_getStringVectorKeys(
+ self.0.as_ptr(),
+ out_keys,
+ buffer_size_bytes,
+ Some(string_allocator),
+ null_mut(),
+ ),
+ ValueType::PersistableBundle => APersistableBundle_getPersistableBundleKeys(
+ self.0.as_ptr(),
+ out_keys,
+ buffer_size_bytes,
+ Some(string_allocator),
+ null_mut(),
+ ),
+ }
+ }
+ }
+
+ /// Gets all the keys associated with values of the given type.
+ pub fn keys_for_type(&self, value_type: ValueType) -> Vec<String> {
+ // SAFETY: A null pointer is allowed for the buffer.
+ match unsafe { self.get_keys_raw(value_type, null_mut(), 0) } {
+ APERSISTABLEBUNDLE_ALLOCATOR_FAILED => {
+ panic!("APersistableBundle_get*Keys failed to allocate string");
+ }
+ required_buffer_size => {
+ let required_buffer_size_usize = usize::try_from(required_buffer_size)
+ .expect("APersistableBundle_get*Keys returned invalid size");
+ assert_eq!(required_buffer_size_usize % size_of::<*mut c_char>(), 0);
+ let mut keys =
+ vec![null_mut(); required_buffer_size_usize / size_of::<*mut c_char>()];
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for
+ // the lifetime of the `PersistableBundle`. The keys buffer pointer is valid as it
+ // comes from the Vec we just allocated.
+ if unsafe { self.get_keys_raw(value_type, keys.as_mut_ptr(), required_buffer_size) }
+ == APERSISTABLEBUNDLE_ALLOCATOR_FAILED
+ {
+ panic!("APersistableBundle_get*Keys failed to allocate string");
+ }
+ keys.into_iter()
+ .map(|key| {
+ // SAFETY: The pointer was returned from `string_allocator`, which used
+ // `Box::into_raw`, and `APersistableBundle_getStringVector` should have
+ // written valid bytes to it including a NUL terminator in the last
+ // position.
+ let string_length = unsafe { CStr::from_ptr(key) }.count_bytes();
+ let raw_slice = slice_from_raw_parts_mut(key.cast(), string_length + 1);
+ // SAFETY: The pointer was returned from `string_allocator`, which used
+ // `Box::into_raw`, and we've got the appropriate size back by checking the
+ // length of the string.
+ let boxed_slice: Box<[u8]> = unsafe { Box::from_raw(raw_slice) };
+ let c_string = CString::from_vec_with_nul(boxed_slice.into())
+ .expect("APersistableBundle_get*Keys returned string missing NUL byte");
+ c_string
+ .into_string()
+ .expect("APersistableBundle_get*Keys returned invalid UTF-8")
+ })
+ .collect()
+ }
+ }
+ }
+
+ /// Returns an iterator over all keys in the bundle, along with the type of their associated
+ /// value.
+ pub fn keys(&self) -> impl Iterator<Item = (String, ValueType)> + use<'_> {
+ [
+ ValueType::Boolean,
+ ValueType::Integer,
+ ValueType::Long,
+ ValueType::Double,
+ ValueType::String,
+ ValueType::BooleanVector,
+ ValueType::IntegerVector,
+ ValueType::LongVector,
+ ValueType::DoubleVector,
+ ValueType::StringVector,
+ ValueType::PersistableBundle,
+ ]
+ .iter()
+ .flat_map(|value_type| {
+ self.keys_for_type(*value_type).into_iter().map(|key| (key, *value_type))
+ })
+ }
+}
+
+/// Wrapper around `APersistableBundle_getStringVector` to pass `string_allocator` and a null
+/// context pointer.
+///
+/// # Safety
+///
+/// * `bundle` must point to a valid `APersistableBundle` which is not modified for the duration of
+/// the call.
+/// * `key` must point to a valid NUL-terminated C string.
+/// * `buffer` must either be null or point to a buffer of at least `buffer_size_bytes` bytes,
+/// properly aligned for `T`, and not otherwise accessed for the duration of the call.
+unsafe extern "C" fn get_string_vector_with_allocator(
+ bundle: *const APersistableBundle,
+ key: *const c_char,
+ buffer: *mut *mut c_char,
+ buffer_size_bytes: i32,
+) -> i32 {
+ // SAFETY: The safety requirements are all guaranteed by our caller according to the safety
+ // documentation above.
+ unsafe {
+ APersistableBundle_getStringVector(
+ bundle,
+ key,
+ buffer,
+ buffer_size_bytes,
+ Some(string_allocator),
+ null_mut(),
+ )
+ }
+}
+
+// SAFETY: The underlying *APersistableBundle can be moved between threads.
+unsafe impl Send for PersistableBundle {}
+
+// SAFETY: The underlying *APersistableBundle can be read from multiple threads, and we require
+// `&mut PersistableBundle` for any operations which mutate it.
+unsafe impl Sync for PersistableBundle {}
+
+impl Default for PersistableBundle {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl Drop for PersistableBundle {
+ fn drop(&mut self) {
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of this `PersistableBundle`.
+ unsafe { APersistableBundle_delete(self.0.as_ptr()) };
+ }
+}
+
+impl Clone for PersistableBundle {
+ fn clone(&self) -> Self {
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`.
+ let duplicate = unsafe { APersistableBundle_dup(self.0.as_ptr()) };
+ Self(NonNull::new(duplicate).expect("Duplicated APersistableBundle was null"))
+ }
+}
+
+impl PartialEq for PersistableBundle {
+ fn eq(&self, other: &Self) -> bool {
+ // SAFETY: The wrapped `APersistableBundle` pointers are guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`s.
+ unsafe { APersistableBundle_isEqual(self.0.as_ptr(), other.0.as_ptr()) }
+ }
+}
+
+impl UnstructuredParcelable for PersistableBundle {
+ fn write_to_parcel(&self, parcel: &mut BorrowedParcel) -> Result<(), StatusCode> {
+ let status =
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. `parcel.as_native_mut()` always returns a valid
+ // parcel pointer.
+ unsafe { APersistableBundle_writeToParcel(self.0.as_ptr(), parcel.as_native_mut()) };
+ status_result(status)
+ }
+
+ fn from_parcel(parcel: &BorrowedParcel) -> Result<Self, StatusCode> {
+ let mut bundle = null_mut();
+
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. `parcel.as_native()` always returns a valid parcel
+ // pointer.
+ let status = unsafe { APersistableBundle_readFromParcel(parcel.as_native(), &mut bundle) };
+ status_result(status)?;
+
+ Ok(Self(NonNull::new(bundle).expect(
+ "APersistableBundle_readFromParcel returned success but didn't allocate bundle",
+ )))
+ }
+}
+
+/// Allocates a boxed slice of the given size in bytes, returns a pointer to it and writes its size
+/// to `*context`.
+///
+/// # Safety
+///
+/// `context` must either be null or point to a `usize` to which we can write.
+unsafe extern "C" fn string_allocator(size: i32, context: *mut c_void) -> *mut c_char {
+ let Ok(size) = size.try_into() else {
+ return null_mut();
+ };
+ let Ok(boxed_slice) = <[c_char]>::new_box_zeroed_with_elems(size) else {
+ return null_mut();
+ };
+ if !context.is_null() {
+ // SAFETY: The caller promised that `context` is either null or points to a `usize` to which
+ // we can write, and we just checked that it's not null.
+ unsafe {
+ *context.cast::<usize>() = size;
+ }
+ }
+ Box::into_raw(boxed_slice).cast()
+}
+
+impl_deserialize_for_unstructured_parcelable!(PersistableBundle);
+impl_serialize_for_unstructured_parcelable!(PersistableBundle);
+
+/// The types which may be stored as values in a [`PersistableBundle`].
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum ValueType {
+ /// A `bool`.
+ Boolean,
+ /// An `i32`.
+ Integer,
+ /// An `i64`.
+ Long,
+ /// An `f64`.
+ Double,
+ /// A string.
+ String,
+ /// A vector of `bool`s.
+ BooleanVector,
+ /// A vector of `i32`s.
+ IntegerVector,
+ /// A vector of `i64`s.
+ LongVector,
+ /// A vector of `f64`s.
+ DoubleVector,
+ /// A vector of strings.
+ StringVector,
+ /// A nested `PersistableBundle`.
+ PersistableBundle,
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn create_delete() {
+ let bundle = PersistableBundle::new();
+ drop(bundle);
+ }
+
+ #[test]
+ fn duplicate_equal() {
+ let bundle = PersistableBundle::new();
+ let duplicate = bundle.clone();
+ assert_eq!(bundle, duplicate);
+ }
+
+ #[test]
+ fn get_empty() {
+ let bundle = PersistableBundle::new();
+ assert_eq!(bundle.get_bool("foo"), Ok(None));
+ assert_eq!(bundle.get_int("foo"), Ok(None));
+ assert_eq!(bundle.get_long("foo"), Ok(None));
+ assert_eq!(bundle.get_double("foo"), Ok(None));
+ assert_eq!(bundle.get_bool_vec("foo"), Ok(None));
+ assert_eq!(bundle.get_int_vec("foo"), Ok(None));
+ assert_eq!(bundle.get_long_vec("foo"), Ok(None));
+ assert_eq!(bundle.get_double_vec("foo"), Ok(None));
+ assert_eq!(bundle.get_string("foo"), Ok(None));
+ }
+
+ #[test]
+ fn remove_empty() {
+ let mut bundle = PersistableBundle::new();
+ assert_eq!(bundle.remove("foo"), Ok(false));
+ }
+
+ #[test]
+ fn insert_get_primitives() {
+ let mut bundle = PersistableBundle::new();
+
+ assert_eq!(bundle.insert_bool("bool", true), Ok(()));
+ assert_eq!(bundle.insert_int("int", 42), Ok(()));
+ assert_eq!(bundle.insert_long("long", 66), Ok(()));
+ assert_eq!(bundle.insert_double("double", 123.4), Ok(()));
+
+ assert_eq!(bundle.get_bool("bool"), Ok(Some(true)));
+ assert_eq!(bundle.get_int("int"), Ok(Some(42)));
+ assert_eq!(bundle.get_long("long"), Ok(Some(66)));
+ assert_eq!(bundle.get_double("double"), Ok(Some(123.4)));
+ assert_eq!(bundle.size(), 4);
+
+ // Getting the wrong type should return nothing.
+ assert_eq!(bundle.get_int("bool"), Ok(None));
+ assert_eq!(bundle.get_long("bool"), Ok(None));
+ assert_eq!(bundle.get_double("bool"), Ok(None));
+ assert_eq!(bundle.get_bool("int"), Ok(None));
+ assert_eq!(bundle.get_long("int"), Ok(None));
+ assert_eq!(bundle.get_double("int"), Ok(None));
+ assert_eq!(bundle.get_bool("long"), Ok(None));
+ assert_eq!(bundle.get_int("long"), Ok(None));
+ assert_eq!(bundle.get_double("long"), Ok(None));
+ assert_eq!(bundle.get_bool("double"), Ok(None));
+ assert_eq!(bundle.get_int("double"), Ok(None));
+ assert_eq!(bundle.get_long("double"), Ok(None));
+
+ // If they are removed they should no longer be present.
+ assert_eq!(bundle.remove("bool"), Ok(true));
+ assert_eq!(bundle.remove("int"), Ok(true));
+ assert_eq!(bundle.remove("long"), Ok(true));
+ assert_eq!(bundle.remove("double"), Ok(true));
+ assert_eq!(bundle.get_bool("bool"), Ok(None));
+ assert_eq!(bundle.get_int("int"), Ok(None));
+ assert_eq!(bundle.get_long("long"), Ok(None));
+ assert_eq!(bundle.get_double("double"), Ok(None));
+ assert_eq!(bundle.size(), 0);
+ }
+
+ #[test]
+ fn insert_get_string() {
+ let mut bundle = PersistableBundle::new();
+
+ assert_eq!(bundle.insert_string("string", "foo"), Ok(()));
+ assert_eq!(bundle.insert_string("empty", ""), Ok(()));
+ assert_eq!(bundle.size(), 2);
+
+ assert_eq!(bundle.get_string("string"), Ok(Some("foo".to_string())));
+ assert_eq!(bundle.get_string("empty"), Ok(Some("".to_string())));
+ }
+
+ #[test]
+ fn insert_get_vec() {
+ let mut bundle = PersistableBundle::new();
+
+ assert_eq!(bundle.insert_bool_vec("bool", &[]), Ok(()));
+ assert_eq!(bundle.insert_int_vec("int", &[42]), Ok(()));
+ assert_eq!(bundle.insert_long_vec("long", &[66, 67, 68]), Ok(()));
+ assert_eq!(bundle.insert_double_vec("double", &[123.4]), Ok(()));
+ assert_eq!(bundle.insert_string_vec("string", &["foo", "bar", "baz"]), Ok(()));
+ assert_eq!(
+ bundle.insert_string_vec(
+ "string",
+ &[&"foo".to_string(), &"bar".to_string(), &"baz".to_string()]
+ ),
+ Ok(())
+ );
+ assert_eq!(
+ bundle.insert_string_vec(
+ "string",
+ &["foo".to_string(), "bar".to_string(), "baz".to_string()]
+ ),
+ Ok(())
+ );
+
+ assert_eq!(bundle.size(), 5);
+
+ assert_eq!(bundle.get_bool_vec("bool"), Ok(Some(vec![])));
+ assert_eq!(bundle.get_int_vec("int"), Ok(Some(vec![42])));
+ assert_eq!(bundle.get_long_vec("long"), Ok(Some(vec![66, 67, 68])));
+ assert_eq!(bundle.get_double_vec("double"), Ok(Some(vec![123.4])));
+ assert_eq!(
+ bundle.get_string_vec("string"),
+ Ok(Some(vec!["foo".to_string(), "bar".to_string(), "baz".to_string()]))
+ );
+ }
+
+ #[test]
+ fn insert_get_bundle() {
+ let mut bundle = PersistableBundle::new();
+
+ let mut sub_bundle = PersistableBundle::new();
+ assert_eq!(sub_bundle.insert_int("int", 42), Ok(()));
+ assert_eq!(sub_bundle.size(), 1);
+ assert_eq!(bundle.insert_persistable_bundle("bundle", &sub_bundle), Ok(()));
+
+ assert_eq!(bundle.get_persistable_bundle("bundle"), Ok(Some(sub_bundle)));
+ }
+
+ #[test]
+ fn get_keys() {
+ let mut bundle = PersistableBundle::new();
+
+ assert_eq!(bundle.keys_for_type(ValueType::Boolean), Vec::<String>::new());
+ assert_eq!(bundle.keys_for_type(ValueType::Integer), Vec::<String>::new());
+ assert_eq!(bundle.keys_for_type(ValueType::StringVector), Vec::<String>::new());
+
+ assert_eq!(bundle.insert_bool("bool1", false), Ok(()));
+ assert_eq!(bundle.insert_bool("bool2", true), Ok(()));
+ assert_eq!(bundle.insert_int("int", 42), Ok(()));
+
+ assert_eq!(
+ bundle.keys_for_type(ValueType::Boolean),
+ vec!["bool1".to_string(), "bool2".to_string()]
+ );
+ assert_eq!(bundle.keys_for_type(ValueType::Integer), vec!["int".to_string()]);
+ assert_eq!(bundle.keys_for_type(ValueType::StringVector), Vec::<String>::new());
+
+ assert_eq!(
+ bundle.keys().collect::<Vec<_>>(),
+ vec![
+ ("bool1".to_string(), ValueType::Boolean),
+ ("bool2".to_string(), ValueType::Boolean),
+ ("int".to_string(), ValueType::Integer),
+ ]
+ );
+ }
+}
diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs
index 04f1517..593d12c 100644
--- a/libs/binder/rust/src/proxy.rs
+++ b/libs/binder/rust/src/proxy.rs
@@ -298,7 +298,7 @@
unsafe { sys::AIBinder_isAlive(self.as_native()) }
}
- #[cfg(not(android_vndk))]
+ #[cfg(not(any(android_vndk, android_ndk)))]
fn set_requesting_sid(&mut self, enable: bool) {
// Safety: `SpIBinder` guarantees that `self` always contains a valid
// pointer to an `AIBinder`.
diff --git a/libs/binder/rust/src/service.rs b/libs/binder/rust/src/service.rs
index 29dd8e1..f4fdcf5 100644
--- a/libs/binder/rust/src/service.rs
+++ b/libs/binder/rust/src/service.rs
@@ -176,6 +176,7 @@
/// seconds if it doesn't yet exist.
#[deprecated = "this polls 5s, use wait_for_interface or check_interface"]
pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
+ #[allow(deprecated)]
interface_cast(get_service(name))
}
diff --git a/libs/binder/rust/src/state.rs b/libs/binder/rust/src/state.rs
index 8a06274..609334e 100644
--- a/libs/binder/rust/src/state.rs
+++ b/libs/binder/rust/src/state.rs
@@ -28,8 +28,9 @@
/// `num_threads` additional threads as specified by
/// [`set_thread_pool_max_thread_count`](Self::set_thread_pool_max_thread_count).
///
- /// This should be done before creating any Binder client or server. If
- /// neither this nor [`join_thread_pool`](Self::join_thread_pool) are
+ /// If this is called, it must be done before creating any Binder client or server.
+ ///
+ /// If neither this nor [`join_thread_pool`](Self::join_thread_pool) are
/// called, then some things (such as callbacks and
/// [`IBinder::link_to_death`](crate::IBinder::link_to_death)) will silently
/// not work: the callbacks will be queued but never called as there is no
@@ -101,7 +102,10 @@
/// dies and is replaced with another process with elevated permissions and
/// the same PID.
///
- /// Warning: oneway transactions do not receive PID. Even if you expect
+ /// Warning: do not use this as a security identifier! PID is unreliable
+ /// as it may be re-used. This should mostly be used for debugging.
+ ///
+ /// oneway transactions do not receive PID. Even if you expect
/// a transaction to be synchronous, a misbehaving client could send it
/// as a synchronous call and result in a 0 PID here. Additionally, if
/// there is a race and the calling process dies, the PID may still be
diff --git a/libs/binder/rust/src/system_only.rs b/libs/binder/rust/src/system_only.rs
index 08582ab..50aa336 100644
--- a/libs/binder/rust/src/system_only.rs
+++ b/libs/binder/rust/src/system_only.rs
@@ -22,31 +22,25 @@
use std::ffi::{c_void, CStr, CString};
use std::os::raw::c_char;
-use libc::sockaddr;
-use nix::sys::socket::{SockaddrLike, UnixAddr, VsockAddr};
-use std::sync::Arc;
-use std::{fmt, ptr};
+use libc::{sockaddr, sockaddr_un, sockaddr_vm, socklen_t};
+use std::boxed::Box;
+use std::{mem, ptr};
/// Rust wrapper around ABinderRpc_Accessor objects for RPC binder service management.
///
/// Dropping the `Accessor` will drop the underlying object and the binder it owns.
+#[derive(Debug)]
pub struct Accessor {
accessor: *mut sys::ABinderRpc_Accessor,
}
-impl fmt::Debug for Accessor {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "ABinderRpc_Accessor({:p})", self.accessor)
- }
-}
-
/// Socket connection info required for libbinder to connect to a service.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConnectionInfo {
/// For vsock connection
- Vsock(VsockAddr),
+ Vsock(sockaddr_vm),
/// For unix domain socket connection
- Unix(UnixAddr),
+ Unix(sockaddr_un),
}
/// Safety: A `Accessor` is a wrapper around `ABinderRpc_Accessor` which is
@@ -71,7 +65,7 @@
where
F: Fn(&str) -> Option<ConnectionInfo> + Send + Sync + 'static,
{
- let callback: *mut c_void = Arc::into_raw(Arc::new(callback)) as *mut c_void;
+ let callback: *mut c_void = Box::into_raw(Box::new(callback)) as *mut c_void;
let inst = CString::new(instance).unwrap();
// Safety: The function pointer is a valid connection_info callback.
@@ -92,6 +86,32 @@
Accessor { accessor }
}
+ /// Creates a new Accessor instance based on an existing Accessor's binder.
+ /// This is useful when the Accessor instance is hosted in another process
+ /// that has the permissions to create the socket connection FD.
+ ///
+ /// The `instance` argument must match the instance that the original Accessor
+ /// is responsible for.
+ /// `instance` must not contain null bytes and is used to create a CString to
+ /// pass through FFI.
+ /// The `binder` argument must be a valid binder from an Accessor
+ pub fn from_binder(instance: &str, binder: SpIBinder) -> Option<Accessor> {
+ let inst = CString::new(instance).unwrap();
+
+ // Safety: All `SpIBinder` objects (the `binder` argument) hold a valid pointer
+ // to an `AIBinder` that is guaranteed to remain valid for the lifetime of the
+ // SpIBinder. `ABinderRpc_Accessor_fromBinder` creates a new pointer to that binder
+ // that it is responsible for.
+ // The `inst` argument is a new CString that will copied by
+ // `ABinderRpc_Accessor_fromBinder` and not modified.
+ let accessor =
+ unsafe { sys::ABinderRpc_Accessor_fromBinder(inst.as_ptr(), binder.as_raw()) };
+ if accessor.is_null() {
+ return None;
+ }
+ Some(Accessor { accessor })
+ }
+
/// Get the underlying binder for this Accessor for when it needs to be either
/// registered with service manager or sent to another process.
pub fn as_binder(&self) -> Option<SpIBinder> {
@@ -101,17 +121,36 @@
unsafe { SpIBinder::from_raw(sys::ABinderRpc_Accessor_asBinder(self.accessor)) }
}
+ /// Release the underlying ABinderRpc_Accessor pointer for use with the ndk API
+ /// This gives up ownership of the ABinderRpc_Accessor and it is the responsibility of
+ /// the caller to delete it with ABinderRpc_Accessor_delete
+ ///
+ /// # Safety
+ ///
+ /// - The returned `ABinderRpc_Accessor` pointer is now owned by the caller, who must
+ /// call `ABinderRpc_Accessor_delete` to delete the object.
+ /// - This `Accessor` object is now useless after `release` so it can be dropped.
+ unsafe fn release(mut self) -> *mut sys::ABinderRpc_Accessor {
+ if self.accessor.is_null() {
+ log::error!("Attempting to release an Accessor that was already released");
+ return ptr::null_mut();
+ }
+ let ptr = self.accessor;
+ self.accessor = ptr::null_mut();
+ ptr
+ }
+
/// Callback invoked from C++ when the connection info is needed.
///
/// # Safety
///
- /// The `instance` parameter must be a non-null pointer to a valid C string for
- /// CStr::from_ptr. The memory must contain a valid null terminator at the end of
- /// the string within isize::MAX from the pointer. The memory must not be mutated for
- /// the duration of this function call and must be valid for reads from the pointer
- /// to the null terminator.
- /// The `cookie` parameter must be the cookie for an `Arc<F>` and
- /// the caller must hold a ref-count to it.
+ /// - The `instance` parameter must be a non-null pointer to a valid C string for
+ /// CStr::from_ptr. The memory must contain a valid null terminator at the end of
+ /// the string within isize::MAX from the pointer. The memory must not be mutated for
+ /// the duration of this function call and must be valid for reads from the pointer
+ /// to the null terminator.
+ /// - The `cookie` parameter must be the cookie for a `Box<F>` and
+ /// the caller must hold a ref-count to it.
unsafe extern "C" fn connection_info<F>(
instance: *const c_char,
cookie: *mut c_void,
@@ -123,7 +162,7 @@
log::error!("Cookie({cookie:p}) or instance({instance:p}) is null!");
return ptr::null_mut();
}
- // Safety: The caller promises that `cookie` is for an Arc<F>.
+ // Safety: The caller promises that `cookie` is for a Box<F>.
let callback = unsafe { (cookie as *const F).as_ref().unwrap() };
// Safety: The caller in libbinder_ndk will have already verified this is a valid
@@ -148,36 +187,48 @@
match connection {
ConnectionInfo::Vsock(addr) => {
// Safety: The sockaddr is being copied in the NDK API
- unsafe { sys::ABinderRpc_ConnectionInfo_new(addr.as_ptr(), addr.len()) }
+ unsafe {
+ sys::ABinderRpc_ConnectionInfo_new(
+ &addr as *const sockaddr_vm as *const sockaddr,
+ mem::size_of::<sockaddr_vm>() as socklen_t,
+ )
+ }
}
ConnectionInfo::Unix(addr) => {
// Safety: The sockaddr is being copied in the NDK API
// The cast is from sockaddr_un* to sockaddr*.
unsafe {
- sys::ABinderRpc_ConnectionInfo_new(addr.as_ptr() as *const sockaddr, addr.len())
+ sys::ABinderRpc_ConnectionInfo_new(
+ &addr as *const sockaddr_un as *const sockaddr,
+ mem::size_of::<sockaddr_un>() as socklen_t,
+ )
}
}
}
}
- /// Callback that decrements the ref-count.
+ /// Callback that drops the `Box<F>`.
/// This is invoked from C++ when a binder is unlinked.
///
/// # Safety
///
- /// The `cookie` parameter must be the cookie for an `Arc<F>` and
- /// the owner must give up a ref-count to it.
+ /// - The `cookie` parameter must be the cookie for a `Box<F>` and
+ /// the owner must give up a ref-count to it.
unsafe extern "C" fn cookie_decr_refcount<F>(cookie: *mut c_void)
where
F: Fn(&str) -> Option<ConnectionInfo> + Send + Sync + 'static,
{
- // Safety: The caller promises that `cookie` is for an Arc<F>.
- unsafe { Arc::decrement_strong_count(cookie as *const F) };
+ // Safety: The caller promises that `cookie` is for a Box<F>.
+ unsafe { std::mem::drop(Box::from_raw(cookie as *mut F)) };
}
}
impl Drop for Accessor {
fn drop(&mut self) {
+ if self.accessor.is_null() {
+ // This Accessor was already released.
+ return;
+ }
// Safety: `self.accessor` is always a valid, owned
// `ABinderRpc_Accessor` pointer returned by
// `ABinderRpc_Accessor_new` when `self` was created. This delete
@@ -211,3 +262,140 @@
// point, so can be safely passed to `SpIBinder::from_raw`.
Ok(unsafe { SpIBinder::from_raw(delegator).expect("Expected valid binder at this point") })
}
+
+/// Rust wrapper around ABinderRpc_AccessorProvider objects for RPC binder service management.
+///
+/// Dropping the `AccessorProvider` will drop/unregister the underlying object.
+#[derive(Debug)]
+pub struct AccessorProvider {
+ accessor_provider: *mut sys::ABinderRpc_AccessorProvider,
+}
+
+/// Safety: A `AccessorProvider` is a wrapper around `ABinderRpc_AccessorProvider` which is
+/// `Sync` and `Send`. As
+/// `ABinderRpc_AccessorProvider` is threadsafe, this structure is too.
+/// The Fn owned the AccessorProvider has `Sync` and `Send` properties
+unsafe impl Send for AccessorProvider {}
+
+/// Safety: A `AccessorProvider` is a wrapper around `ABinderRpc_AccessorProvider` which is
+/// `Sync` and `Send`. As `ABinderRpc_AccessorProvider` is threadsafe, this structure is too.
+/// The Fn owned the AccessorProvider has `Sync` and `Send` properties
+unsafe impl Sync for AccessorProvider {}
+
+impl AccessorProvider {
+ /// Create a new `AccessorProvider` that will give libbinder `Accessors` in order to
+ /// connect to binder services over sockets.
+ ///
+ /// `instances` is a list of all instances that this `AccessorProvider` is responsible for.
+ /// It is declaring these instances as available to this process and will return
+ /// `Accessor` objects for them when libbinder calls the `provider` callback.
+ /// `provider` is the callback that libbinder will call when a service is being requested.
+ /// The callback takes a `&str` argument representing the service that is being requested.
+ /// See the `ABinderRpc_AccessorProvider_getAccessorCallback` for the C++ equivalent.
+ pub fn new<F>(instances: &[String], provider: F) -> Option<AccessorProvider>
+ where
+ F: Fn(&str) -> Option<Accessor> + Send + Sync + 'static,
+ {
+ let callback: *mut c_void = Box::into_raw(Box::new(provider)) as *mut c_void;
+ let c_str_instances: Vec<CString> =
+ instances.iter().map(|s| CString::new(s.as_bytes()).unwrap()).collect();
+ let mut c_instances: Vec<*const c_char> =
+ c_str_instances.iter().map(|s| s.as_ptr()).collect();
+ let num_instances: usize = c_instances.len();
+ // Safety:
+ // - The function pointer for the first argument is a valid `get_accessor` callback.
+ // - This call returns an owned `ABinderRpc_AccessorProvider` pointer which
+ // must be destroyed via `ABinderRpc_unregisterAccessorProvider` when no longer
+ // needed.
+ // - When the underlying ABinderRpc_AccessorProvider is deleted, it will call
+ // the `cookie_decr_refcount` callback on the `callback` pointer to release its
+ // strong ref.
+ // - The `c_instances` vector is not modified by the function
+ let accessor_provider = unsafe {
+ sys::ABinderRpc_registerAccessorProvider(
+ Some(Self::get_accessor::<F>),
+ c_instances.as_mut_ptr(),
+ num_instances,
+ callback,
+ Some(Self::accessor_cookie_decr_refcount::<F>),
+ )
+ };
+
+ if accessor_provider.is_null() {
+ return None;
+ }
+ Some(AccessorProvider { accessor_provider })
+ }
+
+ /// Callback invoked from C++ when an Accessor is needed.
+ ///
+ /// # Safety
+ ///
+ /// - libbinder guarantees the `instance` argument is a valid C string if it's not null.
+ /// - The `cookie` pointer is same pointer that we pass to ABinderRpc_registerAccessorProvider
+ /// in AccessorProvider.new() which is the closure that we will delete with
+ /// self.accessor_cookie_decr_refcount when unregistering the AccessorProvider.
+ unsafe extern "C" fn get_accessor<F>(
+ instance: *const c_char,
+ cookie: *mut c_void,
+ ) -> *mut binder_ndk_sys::ABinderRpc_Accessor
+ where
+ F: Fn(&str) -> Option<Accessor> + Send + Sync + 'static,
+ {
+ if cookie.is_null() || instance.is_null() {
+ log::error!("Cookie({cookie:p}) or instance({instance:p}) is null!");
+ return ptr::null_mut();
+ }
+ // Safety: The caller promises that `cookie` is for a Box<F>.
+ let callback = unsafe { (cookie as *const F).as_ref().unwrap() };
+
+ let inst = {
+ // Safety: The caller in libbinder_ndk will have already verified this is a valid
+ // C string
+ match unsafe { CStr::from_ptr(instance) }.to_str() {
+ Ok(s) => s,
+ Err(err) => {
+ log::error!("Failed to get a valid C string! {err:?}");
+ return ptr::null_mut();
+ }
+ }
+ };
+
+ match callback(inst) {
+ Some(a) => {
+ // Safety: This is giving up ownership of this ABinderRpc_Accessor
+ // to the caller of this function (libbinder) and it is responsible
+ // for deleting it.
+ unsafe { a.release() }
+ }
+ None => ptr::null_mut(),
+ }
+ }
+
+ /// Callback that decrements the ref-count.
+ /// This is invoked from C++ when the provider is unregistered.
+ ///
+ /// # Safety
+ ///
+ /// - The `cookie` parameter must be the cookie for a `Box<F>` and
+ /// the owner must give up a ref-count to it.
+ unsafe extern "C" fn accessor_cookie_decr_refcount<F>(cookie: *mut c_void)
+ where
+ F: Fn(&str) -> Option<Accessor> + Send + Sync + 'static,
+ {
+ // Safety: The caller promises that `cookie` is for a Box<F>.
+ unsafe { std::mem::drop(Box::from_raw(cookie as *mut F)) };
+ }
+}
+
+impl Drop for AccessorProvider {
+ fn drop(&mut self) {
+ // Safety: `self.accessor_provider` is always a valid, owned
+ // `ABinderRpc_AccessorProvider` pointer returned by
+ // `ABinderRpc_registerAccessorProvider` when `self` was created. This delete
+ // method can only be called once when `self` is dropped.
+ unsafe {
+ sys::ABinderRpc_unregisterAccessorProvider(self.accessor_provider);
+ }
+ }
+}
diff --git a/libs/binder/rust/sys/BinderBindings.hpp b/libs/binder/rust/sys/BinderBindings.hpp
index bd666fe..c19e375 100644
--- a/libs/binder/rust/sys/BinderBindings.hpp
+++ b/libs/binder/rust/sys/BinderBindings.hpp
@@ -15,15 +15,20 @@
*/
#include <android/binder_ibinder.h>
+#include <android/binder_parcel.h>
+#include <android/binder_status.h>
+#include <android/persistable_bundle.h>
+
+/* Platform only */
+#if defined(ANDROID_PLATFORM) || defined(__ANDROID_VENDOR__)
#include <android/binder_ibinder_platform.h>
#include <android/binder_manager.h>
-#include <android/binder_parcel.h>
#include <android/binder_parcel_platform.h>
#include <android/binder_process.h>
#include <android/binder_rpc.h>
#include <android/binder_shell.h>
#include <android/binder_stability.h>
-#include <android/binder_status.h>
+#endif
namespace android {
@@ -81,8 +86,15 @@
enum {
FLAG_ONEWAY = FLAG_ONEWAY,
+#if defined(ANDROID_PLATFORM) || defined(__ANDROID_VENDOR__)
FLAG_CLEAR_BUF = FLAG_CLEAR_BUF,
FLAG_PRIVATE_LOCAL = FLAG_PRIVATE_LOCAL,
+#endif
+};
+
+enum {
+ APERSISTABLEBUNDLE_KEY_NOT_FOUND = APERSISTABLEBUNDLE_KEY_NOT_FOUND,
+ APERSISTABLEBUNDLE_ALLOCATOR_FAILED = APERSISTABLEBUNDLE_ALLOCATOR_FAILED,
};
} // namespace consts
diff --git a/libs/binder/rust/sys/Cargo.toml b/libs/binder/rust/sys/Cargo.toml
new file mode 100644
index 0000000..ad8e9c2
--- /dev/null
+++ b/libs/binder/rust/sys/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "android-binder-ndk-sys"
+version = "0.1.0"
+edition = "2021"
+description = "Bindgen bindings to android binder, restricted to the NDK"
+license = "Apache-2.0"
+
+[dependencies]
+
+[lib]
+path = "lib.rs"
+
+[build-dependencies]
+bindgen = "0.70.1"
diff --git a/libs/binder/rust/sys/build.rs b/libs/binder/rust/sys/build.rs
new file mode 100644
index 0000000..cb9c65b
--- /dev/null
+++ b/libs/binder/rust/sys/build.rs
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+use std::env;
+use std::path::PathBuf;
+
+fn main() {
+ let ndk_home = PathBuf::from(env::var("ANDROID_NDK_HOME").unwrap());
+ let toolchain = ndk_home.join("toolchains/llvm/prebuilt/linux-x86_64/");
+ let sysroot = toolchain.join("sysroot");
+ let bindings = bindgen::Builder::default()
+ .clang_arg(format!("--sysroot={}", sysroot.display()))
+ // TODO figure out what the "standard" #define is and use that instead
+ .header("BinderBindings.hpp")
+ .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
+ // Keep in sync with libbinder_ndk_bindgen_flags.txt
+ .default_enum_style(bindgen::EnumVariation::Rust { non_exhaustive: true })
+ .constified_enum("android::c_interface::consts::.*")
+ .allowlist_type("android::c_interface::.*")
+ .allowlist_type("AStatus")
+ .allowlist_type("AIBinder_Class")
+ .allowlist_type("AIBinder")
+ .allowlist_type("AIBinder_Weak")
+ .allowlist_type("AIBinder_DeathRecipient")
+ .allowlist_type("AParcel")
+ .allowlist_type("binder_status_t")
+ .blocklist_function("vprintf")
+ .blocklist_function("strtold")
+ .blocklist_function("_vtlog")
+ .blocklist_function("vscanf")
+ .blocklist_function("vfprintf_worker")
+ .blocklist_function("vsprintf")
+ .blocklist_function("vsnprintf")
+ .blocklist_function("vsnprintf_filtered")
+ .blocklist_function("vfscanf")
+ .blocklist_function("vsscanf")
+ .blocklist_function("vdprintf")
+ .blocklist_function("vasprintf")
+ .blocklist_function("strtold_l")
+ .allowlist_function(".*")
+ .generate()
+ .expect("Couldn't generate bindings");
+ let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
+ bindings.write_to_file(out_path.join("bindings.rs")).expect("Couldn't write bindings.");
+ println!("cargo::rustc-link-lib=binder_ndk");
+}
diff --git a/libs/binder/rust/sys/lib.rs b/libs/binder/rust/sys/lib.rs
index 5352473..349e5a9 100644
--- a/libs/binder/rust/sys/lib.rs
+++ b/libs/binder/rust/sys/lib.rs
@@ -20,6 +20,7 @@
use std::fmt;
#[cfg(not(target_os = "trusty"))]
+#[allow(bad_style)]
mod bindings {
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
}
diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs
index 489fa0a..da4f128 100644
--- a/libs/binder/rust/tests/integration.rs
+++ b/libs/binder/rust/tests/integration.rs
@@ -384,8 +384,8 @@
use std::time::Duration;
use binder::{
- Accessor, BinderFeatures, DeathRecipient, FromIBinder, IBinder, Interface, SpIBinder,
- StatusCode, Strong,
+ Accessor, AccessorProvider, BinderFeatures, DeathRecipient, FromIBinder, IBinder,
+ Interface, SpIBinder, StatusCode, Strong,
};
// Import from impl API for testing only, should not be necessary as long as
// you are using AIDL.
@@ -982,6 +982,90 @@
assert_eq!(delegator_binder, Err(StatusCode::NAME_NOT_FOUND));
}
+ #[test]
+ fn test_accessor_provider_simple() {
+ let instances: Vec<String> = vec!["foo.service".to_owned(), "foo.other_service".to_owned()];
+ let accessor = AccessorProvider::new(&instances, move |_inst: &str| None);
+ assert!(accessor.is_some());
+ }
+
+ #[test]
+ fn test_accessor_provider_no_instance() {
+ let instances: Vec<String> = vec![];
+ let accessor = AccessorProvider::new(&instances, move |_inst: &str| None);
+ assert!(accessor.is_none());
+ }
+
+ #[test]
+ fn test_accessor_provider_double_register() {
+ let instances: Vec<String> = vec!["foo.service".to_owned(), "foo.other_service".to_owned()];
+ let accessor = AccessorProvider::new(&instances, move |_inst: &str| None);
+ assert!(accessor.is_some());
+ let accessor2 = AccessorProvider::new(&instances, move |_inst: &str| None);
+ assert!(accessor2.is_none());
+ }
+
+ #[test]
+ fn test_accessor_provider_register_drop_register() {
+ let instances: Vec<String> = vec!["foo.service".to_owned(), "foo.other_service".to_owned()];
+ {
+ let accessor = AccessorProvider::new(&instances, move |_inst: &str| None);
+ assert!(accessor.is_some());
+ // accessor drops and unregisters the provider
+ }
+ {
+ let accessor = AccessorProvider::new(&instances, move |_inst: &str| None);
+ assert!(accessor.is_some());
+ }
+ }
+
+ #[test]
+ fn test_accessor_provider_callback_destruction() {
+ let deleted: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));
+ let instances: Vec<String> = vec!["foo.service".to_owned(), "foo.other_service".to_owned()];
+ {
+ let accessor: Option<AccessorProvider>;
+ {
+ let helper = ToBeDeleted { deleted: deleted.clone() };
+ accessor = AccessorProvider::new(&instances, move |_inst: &str| {
+ let _ = &helper;
+ None
+ });
+ }
+ assert!(accessor.is_some());
+ assert!(!deleted.load(Ordering::Relaxed));
+ }
+ assert!(deleted.load(Ordering::Relaxed));
+ }
+
+ #[test]
+ fn test_accessor_from_accessor_binder() {
+ let get_connection_info = move |_instance: &str| None;
+ let accessor = Accessor::new("foo.service", get_connection_info);
+ let accessor2 =
+ Accessor::from_binder("foo.service", accessor.as_binder().unwrap()).unwrap();
+ assert_eq!(accessor.as_binder(), accessor2.as_binder());
+ }
+
+ #[test]
+ fn test_accessor_from_non_accessor_binder() {
+ let service_name = "rust_test_ibinder";
+ let _process = ScopedServiceProcess::new(service_name);
+ let binder = binder::get_service(service_name).unwrap();
+ assert!(binder.is_binder_alive());
+
+ let accessor = Accessor::from_binder("rust_test_ibinder", binder);
+ assert!(accessor.is_none());
+ }
+
+ #[test]
+ fn test_accessor_from_wrong_accessor_binder() {
+ let get_connection_info = move |_instance: &str| None;
+ let accessor = Accessor::new("foo.service", get_connection_info);
+ let accessor2 = Accessor::from_binder("NOT.foo.service", accessor.as_binder().unwrap());
+ assert!(accessor2.is_none());
+ }
+
#[tokio::test]
async fn reassociate_rust_binder_async() {
let service_name = "testing_service";
diff --git a/libs/binder/servicedispatcher.cpp b/libs/binder/servicedispatcher.cpp
index be99065..78fe2a8 100644
--- a/libs/binder/servicedispatcher.cpp
+++ b/libs/binder/servicedispatcher.cpp
@@ -127,7 +127,12 @@
// We can't send BpBinder for regular binder over RPC.
return android::binder::Status::fromStatusT(android::INVALID_OPERATION);
}
- android::binder::Status checkService(const std::string&, android::os::Service*) override {
+ android::binder::Status checkService(const std::string&,
+ android::sp<android::IBinder>*) override {
+ // We can't send BpBinder for regular binder over RPC.
+ return android::binder::Status::fromStatusT(android::INVALID_OPERATION);
+ }
+ android::binder::Status checkService2(const std::string&, android::os::Service*) override {
// We can't send BpBinder for regular binder over RPC.
return android::binder::Status::fromStatusT(android::INVALID_OPERATION);
}
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 28a3f65..f412dfb 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -70,7 +70,11 @@
static_libs: [
"libfakeservicemanager",
],
- defaults: ["libbinder_client_cache_flag"],
+ defaults: [
+ "libbinder_client_cache_flag",
+ "libbinder_addservice_cache_flag",
+ "libbinder_remove_cache_static_list_flag",
+ ],
test_suites: ["general-tests"],
require_root: true,
}
@@ -799,6 +803,28 @@
}
cc_test {
+ name: "binderStabilityIntegrationTest",
+ defaults: ["binder_test_defaults"],
+ srcs: [
+ "binderStabilityIntegrationTest.cpp",
+ ],
+
+ shared_libs: [
+ "libbinder",
+ "libutils",
+ ],
+ static_libs: [
+ "libprocpartition",
+ ],
+
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+ require_root: true,
+}
+
+cc_test {
name: "binderAllocationLimits",
defaults: ["binder_test_defaults"],
srcs: ["binderAllocationLimits.cpp"],
diff --git a/libs/binder/tests/IBinderRpcTest.aidl b/libs/binder/tests/IBinderRpcTest.aidl
index 1164767..dcd6461 100644
--- a/libs/binder/tests/IBinderRpcTest.aidl
+++ b/libs/binder/tests/IBinderRpcTest.aidl
@@ -34,6 +34,8 @@
void holdBinder(@nullable IBinder binder);
@nullable IBinder getHeldBinder();
+ byte[] repeatBytes(in byte[] bytes);
+
// Idea is client creates its own instance of IBinderRpcTest and calls this,
// and the server calls 'binder' with (calls - 1) passing itself as 'binder',
// going back and forth until calls = 0
diff --git a/libs/binder/tests/binderAllocationLimits.cpp b/libs/binder/tests/binderAllocationLimits.cpp
index c0c0aae..339ce4b 100644
--- a/libs/binder/tests/binderAllocationLimits.cpp
+++ b/libs/binder/tests/binderAllocationLimits.cpp
@@ -22,17 +22,33 @@
#include <binder/RpcServer.h>
#include <binder/RpcSession.h>
#include <cutils/trace.h>
+#include <gtest/gtest-spi.h>
#include <gtest/gtest.h>
#include <utils/CallStack.h>
#include <malloc.h>
+#include <atomic>
#include <functional>
+#include <numeric>
#include <vector>
using namespace android::binder::impl;
static android::String8 gEmpty(""); // make sure first allocation from optimization runs
+struct State {
+ State(std::vector<size_t>&& expectedMallocs) : expectedMallocs(std::move(expectedMallocs)) {}
+ ~State() {
+ size_t num = numMallocs.load();
+ if (expectedMallocs.size() != num) {
+ ADD_FAILURE() << "Expected " << expectedMallocs.size() << " allocations, but got "
+ << num;
+ }
+ }
+ const std::vector<size_t> expectedMallocs;
+ std::atomic<size_t> numMallocs;
+};
+
struct DestructionAction {
DestructionAction(std::function<void()> f) : mF(std::move(f)) {}
~DestructionAction() { mF(); };
@@ -95,8 +111,7 @@
// Action to execute when malloc is hit. Supports nesting. Malloc is not
// restricted when the allocation hook is being processed.
-__attribute__((warn_unused_result))
-DestructionAction OnMalloc(LambdaHooks::AllocationHook f) {
+__attribute__((warn_unused_result)) DestructionAction OnMalloc(LambdaHooks::AllocationHook f) {
MallocHooks before = MallocHooks::save();
LambdaHooks::lambdas.emplace_back(std::move(f));
LambdaHooks::lambda_malloc_hooks.overwrite();
@@ -106,6 +121,22 @@
});
}
+DestructionAction setExpectedMallocs(std::vector<size_t>&& expected) {
+ auto state = std::make_shared<State>(std::move(expected));
+ return OnMalloc([state = state](size_t bytes) {
+ size_t num = state->numMallocs.fetch_add(1);
+ if (num >= state->expectedMallocs.size() || state->expectedMallocs[num] != bytes) {
+ ADD_FAILURE() << "Unexpected allocation number " << num << " of size " << bytes
+ << " bytes" << std::endl
+ << android::CallStack::stackToString("UNEXPECTED ALLOCATION",
+ android::CallStack::getCurrent(
+ 4 /*ignoreDepth*/)
+ .get())
+ << std::endl;
+ }
+ });
+}
+
// exported symbol, to force compiler not to optimize away pointers we set here
const void* imaginary_use;
@@ -119,16 +150,53 @@
imaginary_use = new int[10];
}
+ delete[] reinterpret_cast<const int*>(imaginary_use);
EXPECT_EQ(mallocs, 1u);
}
+TEST(TestTheTest, OnMallocWithExpectedMallocs) {
+ std::vector<size_t> expectedMallocs = {
+ 4,
+ 16,
+ 8,
+ };
+ {
+ const auto on_malloc = setExpectedMallocs(std::move(expectedMallocs));
+ imaginary_use = new int32_t[1];
+ delete[] reinterpret_cast<const int*>(imaginary_use);
+ imaginary_use = new int32_t[4];
+ delete[] reinterpret_cast<const int*>(imaginary_use);
+ imaginary_use = new int32_t[2];
+ delete[] reinterpret_cast<const int*>(imaginary_use);
+ }
+}
+
+TEST(TestTheTest, OnMallocWithExpectedMallocsWrongSize) {
+ std::vector<size_t> expectedMallocs = {
+ 4,
+ 16,
+ 100000,
+ };
+ EXPECT_NONFATAL_FAILURE(
+ {
+ const auto on_malloc = setExpectedMallocs(std::move(expectedMallocs));
+ imaginary_use = new int32_t[1];
+ delete[] reinterpret_cast<const int*>(imaginary_use);
+ imaginary_use = new int32_t[4];
+ delete[] reinterpret_cast<const int*>(imaginary_use);
+ imaginary_use = new int32_t[2];
+ delete[] reinterpret_cast<const int*>(imaginary_use);
+ },
+ "Unexpected allocation number 2 of size 8 bytes");
+}
__attribute__((warn_unused_result))
DestructionAction ScopeDisallowMalloc() {
return OnMalloc([&](size_t bytes) {
- ADD_FAILURE() << "Unexpected allocation: " << bytes;
+ FAIL() << "Unexpected allocation: " << bytes;
using android::CallStack;
- std::cout << CallStack::stackToString("UNEXPECTED ALLOCATION", CallStack::getCurrent(4 /*ignoreDepth*/).get())
+ std::cout << CallStack::stackToString("UNEXPECTED ALLOCATION",
+ CallStack::getCurrent(4 /*ignoreDepth*/).get())
<< std::endl;
});
}
@@ -224,6 +292,51 @@
EXPECT_EQ(mallocs, 1u);
}
+TEST(BinderAccessorAllocation, AddAccessorCheckService) {
+ // Need to call defaultServiceManager() before checking malloc because it
+ // will allocate an instance in the call_once
+ const auto sm = defaultServiceManager();
+ const std::string kInstanceName1 = "foo.bar.IFoo/default";
+ const std::string kInstanceName2 = "foo.bar.IFoo2/default";
+ const String16 kInstanceName16(kInstanceName1.c_str());
+ std::vector<size_t> expectedMallocs = {
+ // addAccessorProvider
+ 112, // new AccessorProvider
+ 16, // new AccessorProviderEntry
+ // checkService
+ 45, // String8 from String16 in CppShim::checkService
+ 128, // writeInterfaceToken
+ 16, // getInjectedAccessor, new AccessorProviderEntry
+ 66, // getInjectedAccessor, String16
+ 45, // String8 from String16 in AccessorProvider::provide
+ };
+ std::set<std::string> supportedInstances = {kInstanceName1, kInstanceName2};
+ auto onMalloc = setExpectedMallocs(std::move(expectedMallocs));
+
+ auto receipt =
+ android::addAccessorProvider(std::move(supportedInstances),
+ [&](const String16&) -> sp<IBinder> { return nullptr; });
+ EXPECT_FALSE(receipt.expired());
+
+ sp<IBinder> binder = sm->checkService(kInstanceName16);
+
+ status_t status = android::removeAccessorProvider(receipt);
+}
+
+TEST(BinderAccessorAllocation, AddAccessorEmpty) {
+ std::vector<size_t> expectedMallocs = {
+ 48, // From ALOGE with empty set of instances
+ };
+ std::set<std::string> supportedInstances = {};
+ auto onMalloc = setExpectedMallocs(std::move(expectedMallocs));
+
+ auto receipt =
+ android::addAccessorProvider(std::move(supportedInstances),
+ [&](const String16&) -> sp<IBinder> { return nullptr; });
+
+ EXPECT_TRUE(receipt.expired());
+}
+
TEST(RpcBinderAllocation, SetupRpcServer) {
std::string tmp = getenv("TMPDIR") ?: "/tmp";
std::string addr = tmp + "/binderRpcBenchmark";
@@ -255,6 +368,7 @@
}
int main(int argc, char** argv) {
+ LOG(INFO) << "Priming static log variables for binderAllocationLimits.";
if (getenv("LIBC_HOOKS_ENABLE") == nullptr) {
CHECK(0 == setenv("LIBC_HOOKS_ENABLE", "1", true /*overwrite*/));
execv(argv[0], argv);
diff --git a/libs/binder/tests/binderCacheUnitTest.cpp b/libs/binder/tests/binderCacheUnitTest.cpp
index c5ad793..121e5ae 100644
--- a/libs/binder/tests/binderCacheUnitTest.cpp
+++ b/libs/binder/tests/binderCacheUnitTest.cpp
@@ -34,6 +34,18 @@
constexpr bool kUseLibbinderCache = false;
#endif
+#ifdef LIBBINDER_ADDSERVICE_CACHE
+constexpr bool kUseCacheInAddService = true;
+#else
+constexpr bool kUseCacheInAddService = false;
+#endif
+
+#ifdef LIBBINDER_REMOVE_CACHE_STATIC_LIST
+constexpr bool kRemoveStaticList = true;
+#else
+constexpr bool kRemoveStaticList = false;
+#endif
+
// A service name which is in the static list of cachable services
const String16 kCachedServiceName = String16("isub");
@@ -62,9 +74,11 @@
public:
MockAidlServiceManager() : innerSm() {}
- binder::Status checkService(const ::std::string& name, os::Service* _out) override {
- sp<IBinder> binder = innerSm.getService(String16(name.c_str()));
- *_out = os::Service::make<os::Service::Tag::binder>(binder);
+ binder::Status checkService2(const ::std::string& name, os::Service* _out) override {
+ os::ServiceWithMetadata serviceWithMetadata = os::ServiceWithMetadata();
+ serviceWithMetadata.service = innerSm.getService(String16(name.c_str()));
+ serviceWithMetadata.isLazyService = false;
+ *_out = os::Service::make<os::Service::Tag::serviceWithMetadata>(serviceWithMetadata);
return binder::Status::ok();
}
@@ -74,14 +88,127 @@
innerSm.addService(String16(name.c_str()), service, allowIsolated, dumpPriority));
}
+ void clearServices() { innerSm.clear(); }
+
FakeServiceManager innerSm;
};
+// Returns services with isLazyService flag as true.
+class MockAidlServiceManager2 : public os::IServiceManagerDefault {
+public:
+ MockAidlServiceManager2() : innerSm() {}
+
+ binder::Status checkService2(const ::std::string& name, os::Service* _out) override {
+ os::ServiceWithMetadata serviceWithMetadata = os::ServiceWithMetadata();
+ serviceWithMetadata.service = innerSm.getService(String16(name.c_str()));
+ serviceWithMetadata.isLazyService = true;
+ *_out = os::Service::make<os::Service::Tag::serviceWithMetadata>(serviceWithMetadata);
+ return binder::Status::ok();
+ }
+
+ binder::Status addService(const std::string& name, const sp<IBinder>& service,
+ bool allowIsolated, int32_t dumpPriority) override {
+ return binder::Status::fromStatusT(
+ innerSm.addService(String16(name.c_str()), service, allowIsolated, dumpPriority));
+ }
+
+ void clearServices() { innerSm.clear(); }
+
+ FakeServiceManager innerSm;
+};
+
+class LibbinderCacheRemoveStaticList : public ::testing::Test {
+protected:
+ void SetUp() override {
+ fakeServiceManager = sp<MockAidlServiceManager2>::make();
+ mServiceManager = getServiceManagerShimFromAidlServiceManagerForTests(fakeServiceManager);
+ mServiceManager->enableAddServiceCache(true);
+ }
+ void TearDown() override {}
+
+public:
+ void cacheAddServiceAndConfirmCacheMiss(const sp<IBinder>& binder1) {
+ // Add a service. This shouldn't cache it.
+ EXPECT_EQ(OK,
+ mServiceManager->addService(kCachedServiceName, binder1,
+ /*allowIsolated = */ false,
+ android::os::IServiceManager::FLAG_IS_LAZY_SERVICE));
+ // Try to populate cache. Cache shouldn't be updated.
+ EXPECT_EQ(binder1, mServiceManager->checkService(kCachedServiceName));
+ fakeServiceManager->clearServices();
+ EXPECT_EQ(nullptr, mServiceManager->checkService(kCachedServiceName));
+ }
+
+ sp<MockAidlServiceManager2> fakeServiceManager;
+ sp<android::IServiceManager> mServiceManager;
+};
+
+TEST_F(LibbinderCacheRemoveStaticList, AddLocalServiceAndConfirmCacheMiss) {
+ if (!kRemoveStaticList) {
+ GTEST_SKIP() << "Skipping as feature is not enabled";
+ return;
+ }
+ sp<IBinder> binder1 = sp<BBinder>::make();
+ cacheAddServiceAndConfirmCacheMiss(binder1);
+}
+
+TEST_F(LibbinderCacheRemoveStaticList, AddRemoteServiceAndConfirmCacheMiss) {
+ if (!kRemoveStaticList) {
+ GTEST_SKIP() << "Skipping as feature is not enabled";
+ return;
+ }
+ sp<IBinder> binder1 = defaultServiceManager()->checkService(kServerName);
+ ASSERT_NE(binder1, nullptr);
+ cacheAddServiceAndConfirmCacheMiss(binder1);
+}
+
+class LibbinderCacheAddServiceTest : public ::testing::Test {
+protected:
+ void SetUp() override {
+ fakeServiceManager = sp<MockAidlServiceManager>::make();
+ mServiceManager = getServiceManagerShimFromAidlServiceManagerForTests(fakeServiceManager);
+ mServiceManager->enableAddServiceCache(true);
+ }
+
+ void TearDown() override {}
+
+public:
+ void cacheAddServiceAndConfirmCacheHit(const sp<IBinder>& binder1) {
+ // Add a service. This also caches it.
+ EXPECT_EQ(OK, mServiceManager->addService(kCachedServiceName, binder1));
+ // remove services from fakeservicemanager
+ fakeServiceManager->clearServices();
+
+ sp<IBinder> result = mServiceManager->checkService(kCachedServiceName);
+ if (kUseCacheInAddService && kUseLibbinderCache) {
+ // If cache is enabled, we should get the binder.
+ EXPECT_EQ(binder1, result);
+ } else {
+ // If cache is disabled, then we should get the null binder
+ EXPECT_EQ(nullptr, result);
+ }
+ }
+ sp<MockAidlServiceManager> fakeServiceManager;
+ sp<android::IServiceManager> mServiceManager;
+};
+
+TEST_F(LibbinderCacheAddServiceTest, AddLocalServiceAndConfirmCacheHit) {
+ sp<IBinder> binder1 = sp<BBinder>::make();
+ cacheAddServiceAndConfirmCacheHit(binder1);
+}
+
+TEST_F(LibbinderCacheAddServiceTest, AddRemoteServiceAndConfirmCacheHit) {
+ sp<IBinder> binder1 = defaultServiceManager()->checkService(kServerName);
+ ASSERT_NE(binder1, nullptr);
+ cacheAddServiceAndConfirmCacheHit(binder1);
+}
+
class LibbinderCacheTest : public ::testing::Test {
protected:
void SetUp() override {
- sp<MockAidlServiceManager> sm = sp<MockAidlServiceManager>::make();
- mServiceManager = getServiceManagerShimFromAidlServiceManagerForTests(sm);
+ fakeServiceManager = sp<MockAidlServiceManager>::make();
+ mServiceManager = getServiceManagerShimFromAidlServiceManagerForTests(fakeServiceManager);
+ mServiceManager->enableAddServiceCache(false);
}
void TearDown() override {}
@@ -108,6 +235,7 @@
}
}
+ sp<MockAidlServiceManager> fakeServiceManager;
sp<android::IServiceManager> mServiceManager;
};
@@ -180,7 +308,13 @@
EXPECT_EQ(binder2, result);
}
+// TODO(b/333854840): Remove this test removing the static list
TEST_F(LibbinderCacheTest, DoNotCacheServiceNotInList) {
+ if (kRemoveStaticList) {
+ GTEST_SKIP() << "Skipping test as static list is disabled";
+ return;
+ }
+
sp<IBinder> binder1 = sp<BBinder>::make();
sp<IBinder> binder2 = sp<BBinder>::make();
String16 serviceName = String16("NewLibbinderCacheTest");
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 970852c..891c0a2 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -43,6 +43,8 @@
#include <input/BlockingQueue.h>
#include <processgroup/processgroup.h>
#include <utils/Flattenable.h>
+#include <utils/SystemClock.h>
+#include "binder/IServiceManagerUnitTestHelper.h"
#include <linux/sched.h>
#include <sys/epoll.h>
@@ -223,6 +225,8 @@
ASSERT_GT(m_serverpid, 0);
sp<IServiceManager> sm = defaultServiceManager();
+ // disable caching during addService.
+ sm->enableAddServiceCache(false);
//printf("%s: pid %d, get service\n", __func__, m_pid);
LIBBINDER_IGNORE("-Wdeprecated-declarations")
m_server = sm->getService(binderLibTestServiceName);
@@ -298,6 +302,9 @@
virtual void SetUp() {
m_server = static_cast<BinderLibTestEnv *>(binder_env)->getServer();
IPCThreadState::self()->restoreCallingWorkSource(0);
+ sp<IServiceManager> sm = defaultServiceManager();
+ // disable caching during addService.
+ sm->enableAddServiceCache(false);
}
virtual void TearDown() {
}
@@ -338,7 +345,12 @@
}
bool checkFreezeSupport() {
- std::ifstream freezer_file("/sys/fs/cgroup/uid_0/cgroup.freeze");
+ std::string path;
+ if (!CgroupGetAttributePathForTask("FreezerState", getpid(), &path)) {
+ return false;
+ }
+
+ std::ifstream freezer_file(path);
// Pass test on devices where the cgroup v2 freezer is not supported
if (freezer_file.fail()) {
return false;
@@ -574,14 +586,14 @@
EXPECT_EQ(NO_ERROR, sm->addService(String16("binderLibTest-manager"), binder));
}
+class LocalRegistrationCallbackImpl : public virtual IServiceManager::LocalRegistrationCallback {
+ void onServiceRegistration(const String16&, const sp<IBinder>&) override {}
+ virtual ~LocalRegistrationCallbackImpl() {}
+};
+
TEST_F(BinderLibTest, RegisterForNotificationsFailure) {
auto sm = defaultServiceManager();
- using LocalRegistrationCallback = IServiceManager::LocalRegistrationCallback;
- class LocalRegistrationCallbackImpl : public virtual LocalRegistrationCallback {
- void onServiceRegistration(const String16&, const sp<IBinder>&) override {}
- virtual ~LocalRegistrationCallbackImpl() {}
- };
- sp<LocalRegistrationCallback> cb = sp<LocalRegistrationCallbackImpl>::make();
+ sp<IServiceManager::LocalRegistrationCallback> cb = sp<LocalRegistrationCallbackImpl>::make();
EXPECT_EQ(BAD_VALUE, sm->registerForNotifications(String16("ValidName"), nullptr));
EXPECT_EQ(UNKNOWN_ERROR, sm->registerForNotifications(String16("InvalidName!$"), cb));
@@ -589,12 +601,7 @@
TEST_F(BinderLibTest, UnregisterForNotificationsFailure) {
auto sm = defaultServiceManager();
- using LocalRegistrationCallback = IServiceManager::LocalRegistrationCallback;
- class LocalRegistrationCallbackImpl : public virtual LocalRegistrationCallback {
- void onServiceRegistration(const String16&, const sp<IBinder>&) override {}
- virtual ~LocalRegistrationCallbackImpl() {}
- };
- sp<LocalRegistrationCallback> cb = sp<LocalRegistrationCallbackImpl>::make();
+ sp<IServiceManager::LocalRegistrationCallback> cb = sp<LocalRegistrationCallbackImpl>::make();
EXPECT_EQ(OK, sm->registerForNotifications(String16("ValidName"), cb));
@@ -1765,6 +1772,7 @@
TEST(ServiceNotifications, Unregister) {
auto sm = defaultServiceManager();
+ sm->enableAddServiceCache(false);
using LocalRegistrationCallback = IServiceManager::LocalRegistrationCallback;
class LocalRegistrationCallbackImpl : public virtual LocalRegistrationCallback {
void onServiceRegistration(const String16 &, const sp<IBinder> &) override {}
@@ -1776,6 +1784,43 @@
EXPECT_EQ(sm->unregisterForNotifications(String16("RogerRafa"), cb), OK);
}
+// Make sure all IServiceManager APIs will function without an AIDL service
+// manager registered on the device.
+TEST(ServiceManagerNoAidlServer, SanityCheck) {
+ String16 kServiceName("no_services_exist");
+ // This is what clients will see when there is no servicemanager process
+ // that registers itself as context object 0.
+ // Can't use setDefaultServiceManager() here because these test cases run in
+ // the same process and will abort when called twice or before/after
+ // defaultServiceManager().
+ sp<IServiceManager> sm = getServiceManagerShimFromAidlServiceManagerForTests(nullptr);
+ auto status = sm->addService(kServiceName, sp<BBinder>::make());
+ // CppBackendShim returns Status::exceptionCode as the status_t
+ EXPECT_EQ(status, Status::Exception::EX_UNSUPPORTED_OPERATION) << statusToString(status);
+ auto service = sm->checkService(String16("no_services_exist"));
+ EXPECT_TRUE(service == nullptr);
+ auto list = sm->listServices(android::IServiceManager::DUMP_FLAG_PRIORITY_ALL);
+ EXPECT_TRUE(list.isEmpty());
+ bool declared = sm->isDeclared(kServiceName);
+ EXPECT_FALSE(declared);
+ list = sm->getDeclaredInstances(kServiceName);
+ EXPECT_TRUE(list.isEmpty());
+ auto updatable = sm->updatableViaApex(kServiceName);
+ EXPECT_EQ(updatable, std::nullopt);
+ list = sm->getUpdatableNames(kServiceName);
+ EXPECT_TRUE(list.isEmpty());
+ auto conInfo = sm->getConnectionInfo(kServiceName);
+ EXPECT_EQ(conInfo, std::nullopt);
+ auto cb = sp<LocalRegistrationCallbackImpl>::make();
+ status = sm->registerForNotifications(kServiceName, cb);
+ EXPECT_EQ(status, UNKNOWN_ERROR) << statusToString(status);
+ status = sm->unregisterForNotifications(kServiceName, cb);
+ EXPECT_EQ(status, BAD_VALUE) << statusToString(status);
+ auto dbgInfos = sm->getServiceDebugInfo();
+ EXPECT_TRUE(dbgInfos.empty());
+ sm->enableAddServiceCache(true);
+}
+
TEST_F(BinderLibTest, ThreadPoolAvailableThreads) {
Parcel data, reply;
sp<IBinder> server = addServer();
@@ -1831,14 +1876,6 @@
EXPECT_TRUE(reply.readBool());
}
-size_t epochMillis() {
- using std::chrono::duration_cast;
- using std::chrono::milliseconds;
- using std::chrono::seconds;
- using std::chrono::system_clock;
- return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
-}
-
TEST_F(BinderLibTest, HangingServices) {
Parcel data, reply;
sp<IBinder> server = addServer();
@@ -1847,7 +1884,7 @@
data.writeInt32(delay);
// b/266537959 - must take before taking lock, since countdown is started in the remote
// process there.
- size_t epochMsBefore = epochMillis();
+ int64_t timeBefore = uptimeMillis();
EXPECT_THAT(server->transact(BINDER_LIB_TEST_PROCESS_TEMPORARY_LOCK, data, &reply), NO_ERROR);
std::vector<std::thread> ts;
for (size_t i = 0; i < kKernelThreads + 1; i++) {
@@ -1861,10 +1898,10 @@
for (auto &t : ts) {
t.join();
}
- size_t epochMsAfter = epochMillis();
+ int64_t timeAfter = uptimeMillis();
// deadlock occurred and threads only finished after 1s passed.
- EXPECT_GE(epochMsAfter, epochMsBefore + delay);
+ EXPECT_GE(timeAfter, timeBefore + delay);
}
TEST_F(BinderLibTest, BinderProxyCount) {
@@ -2529,6 +2566,8 @@
status_t ret;
sp<IServiceManager> sm = defaultServiceManager();
+ sm->enableAddServiceCache(false);
+
BinderLibTestService* testServicePtr;
{
sp<BinderLibTestService> testService = new BinderLibTestService(index);
diff --git a/libs/binder/tests/binderParcelUnitTest.cpp b/libs/binder/tests/binderParcelUnitTest.cpp
index 32a70e5..6259d9d 100644
--- a/libs/binder/tests/binderParcelUnitTest.cpp
+++ b/libs/binder/tests/binderParcelUnitTest.cpp
@@ -33,6 +33,38 @@
using android::binder::Status;
using android::binder::unique_fd;
+static void checkCString(const char* str) {
+ for (size_t i = 0; i < 3; i++) {
+ Parcel p;
+
+ for (size_t j = 0; j < i; j++) p.writeInt32(3);
+
+ p.writeCString(str);
+ int32_t pos = p.dataPosition();
+
+ p.setDataPosition(0);
+
+ for (size_t j = 0; j < i; j++) p.readInt32();
+ const char* str2 = p.readCString();
+
+ ASSERT_EQ(std::string(str), str2);
+ ASSERT_EQ(pos, p.dataPosition());
+ }
+}
+
+TEST(Parcel, TestReadCString) {
+ // we should remove the *CString APIs, but testing them until
+ // they are deleted.
+ checkCString("");
+ checkCString("a");
+ checkCString("\n");
+ checkCString("32");
+ checkCString("321");
+ checkCString("3210");
+ checkCString("3210b");
+ checkCString("123434");
+}
+
TEST(Parcel, NonNullTerminatedString8) {
String8 kTestString = String8("test-is-good");
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 506fc71..170b2ad 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -711,6 +711,35 @@
proc.proc->sessions.erase(proc.proc->sessions.begin() + 1);
}
+// TODO(b/392717039): can we move this to universal tests?
+TEST_P(BinderRpc, SendTooLargeVector) {
+ if (GetParam().singleThreaded) {
+ GTEST_SKIP() << "Requires multi-threaded server to test one of the sessions crashing.";
+ }
+
+ auto proc = createRpcTestSocketServerProcess({.numSessions = 2});
+
+ // need a working transaction
+ EXPECT_EQ(OK, proc.rootBinder->pingBinder());
+
+ // see libbinder internal Constants.h
+ const size_t kTooLargeSize = 650 * 1024;
+ const std::vector<uint8_t> kTestValue(kTooLargeSize / sizeof(uint8_t), 42);
+
+ // TODO(b/392717039): Telling a server to allocate too much data currently causes the session to
+ // close since RpcServer treats any transaction error as a failure. We likely want to change
+ // this behavior to be a soft failure, since it isn't hard to keep track of this state.
+ sp<IBinderRpcTest> rootIface2 = interface_cast<IBinderRpcTest>(proc.proc->sessions.at(1).root);
+ std::vector<uint8_t> result;
+ status_t res = rootIface2->repeatBytes(kTestValue, &result).transactionError();
+
+ // TODO(b/392717039): consistent error results always
+ EXPECT_TRUE(res == -ECONNRESET || res == DEAD_OBJECT) << statusToString(res);
+
+ // died, so remove it for checks in destructor of proc
+ proc.proc->sessions.erase(proc.proc->sessions.begin() + 1);
+}
+
TEST_P(BinderRpc, SessionWithIncomingThreadpoolDoesntLeak) {
if (clientOrServerSingleThreaded()) {
GTEST_SKIP() << "This test requires multiple threads";
@@ -1328,6 +1357,109 @@
EXPECT_EQ(status, OK);
}
+class BinderRpcAccessorNoConnection : public ::testing::Test {};
+
+TEST_F(BinderRpcAccessorNoConnection, listServices) {
+ const String16 kInstanceName("super.cool.service/better_than_default");
+ const String16 kInstanceName2("super.cool.service/better_than_default2");
+
+ auto receipt =
+ addAccessorProvider({String8(kInstanceName).c_str(), String8(kInstanceName2).c_str()},
+ [&](const String16&) -> sp<IBinder> { return nullptr; });
+ EXPECT_FALSE(receipt.expired());
+ Vector<String16> list =
+ defaultServiceManager()->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL);
+ bool name1 = false;
+ bool name2 = false;
+ for (auto name : list) {
+ if (name == kInstanceName) name1 = true;
+ if (name == kInstanceName2) name2 = true;
+ }
+ EXPECT_TRUE(name1);
+ EXPECT_TRUE(name2);
+ status_t status = removeAccessorProvider(receipt);
+ EXPECT_EQ(status, OK);
+}
+
+TEST_F(BinderRpcAccessorNoConnection, isDeclared) {
+ const String16 kInstanceName("super.cool.service/default");
+ const String16 kInstanceName2("still_counts_as_declared");
+
+ auto receipt =
+ addAccessorProvider({String8(kInstanceName).c_str(), String8(kInstanceName2).c_str()},
+ [&](const String16&) -> sp<IBinder> { return nullptr; });
+ EXPECT_FALSE(receipt.expired());
+ EXPECT_TRUE(defaultServiceManager()->isDeclared(kInstanceName));
+ EXPECT_TRUE(defaultServiceManager()->isDeclared(kInstanceName2));
+ EXPECT_FALSE(defaultServiceManager()->isDeclared(String16("doesnt_exist")));
+ status_t status = removeAccessorProvider(receipt);
+ EXPECT_EQ(status, OK);
+}
+
+TEST_F(BinderRpcAccessorNoConnection, getDeclaredInstances) {
+ const String16 kInstanceName("super.cool.service.IFoo/default");
+ const String16 kInstanceName2("super.cool.service.IFoo/extra/default");
+ const String16 kInstanceName3("super.cool.service.IFoo");
+
+ auto receipt =
+ addAccessorProvider({String8(kInstanceName).c_str(), String8(kInstanceName2).c_str(),
+ String8(kInstanceName3).c_str()},
+ [&](const String16&) -> sp<IBinder> { return nullptr; });
+ EXPECT_FALSE(receipt.expired());
+ Vector<String16> list =
+ defaultServiceManager()->getDeclaredInstances(String16("super.cool.service.IFoo"));
+ // We would prefer ASSERT_EQ here, but we must call removeAccessorProvider
+ EXPECT_EQ(list.size(), 3u);
+ if (list.size() == 3) {
+ bool name1 = false;
+ bool name2 = false;
+ bool name3 = false;
+ for (auto name : list) {
+ if (name == String16("default")) name1 = true;
+ if (name == String16("extra/default")) name2 = true;
+ if (name == String16()) name3 = true;
+ }
+ EXPECT_TRUE(name1) << String8(list[0]);
+ EXPECT_TRUE(name2) << String8(list[1]);
+ EXPECT_TRUE(name3) << String8(list[2]);
+ }
+
+ status_t status = removeAccessorProvider(receipt);
+ EXPECT_EQ(status, OK);
+}
+
+TEST_F(BinderRpcAccessorNoConnection, getDeclaredWrongInstances) {
+ const String16 kInstanceName("super.cool.service.IFoo");
+
+ auto receipt = addAccessorProvider({String8(kInstanceName).c_str()},
+ [&](const String16&) -> sp<IBinder> { return nullptr; });
+ EXPECT_FALSE(receipt.expired());
+ Vector<String16> list = defaultServiceManager()->getDeclaredInstances(String16("unknown"));
+ EXPECT_TRUE(list.empty());
+
+ status_t status = removeAccessorProvider(receipt);
+ EXPECT_EQ(status, OK);
+}
+
+TEST_F(BinderRpcAccessorNoConnection, getDeclaredInstancesSlash) {
+ // This is treated as if there were no '/' and the declared instance is ""
+ const String16 kInstanceName("super.cool.service.IFoo/");
+
+ auto receipt = addAccessorProvider({String8(kInstanceName).c_str()},
+ [&](const String16&) -> sp<IBinder> { return nullptr; });
+ EXPECT_FALSE(receipt.expired());
+ Vector<String16> list =
+ defaultServiceManager()->getDeclaredInstances(String16("super.cool.service.IFoo"));
+ bool name1 = false;
+ for (auto name : list) {
+ if (name == String16("")) name1 = true;
+ }
+ EXPECT_TRUE(name1);
+
+ status_t status = removeAccessorProvider(receipt);
+ EXPECT_EQ(status, OK);
+}
+
constexpr const char* kARpcInstance = "some.instance.name.IFoo/default";
const char* kARpcSupportedServices[] = {
kARpcInstance,
@@ -1400,6 +1532,26 @@
EXPECT_TRUE(isDeleted);
}
+TEST_F(BinderARpcNdk, ARpcProviderDeleteOnError) {
+ bool isDeleted = false;
+ AccessorProviderData* data = new AccessorProviderData{{}, 0, &isDeleted};
+
+ ABinderRpc_AccessorProvider* provider =
+ ABinderRpc_registerAccessorProvider(getAccessor, kARpcSupportedServices, 0, data,
+ accessorProviderDataOnDelete);
+
+ ASSERT_EQ(provider, nullptr);
+ EXPECT_TRUE(isDeleted);
+}
+
+TEST_F(BinderARpcNdk, ARpcProvideOnErrorNoDeleteCbNoCrash) {
+ ABinderRpc_AccessorProvider* provider =
+ ABinderRpc_registerAccessorProvider(getAccessor, kARpcSupportedServices, 0, nullptr,
+ nullptr);
+
+ ASSERT_EQ(provider, nullptr);
+}
+
TEST_F(BinderARpcNdk, ARpcProviderDuplicateInstance) {
const char* instance = "some.instance.name.IFoo/default";
const uint32_t numInstances = 2;
@@ -2619,7 +2771,9 @@
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
+#ifndef __ANDROID__
__android_log_set_logger(__android_log_stderr_logger);
+#endif
return RUN_ALL_TESTS();
}
diff --git a/libs/binder/tests/binderRpcTestCommon.h b/libs/binder/tests/binderRpcTestCommon.h
index dc22647..6e00246 100644
--- a/libs/binder/tests/binderRpcTestCommon.h
+++ b/libs/binder/tests/binderRpcTestCommon.h
@@ -348,6 +348,10 @@
*out = binder;
return Status::ok();
}
+ Status repeatBytes(const std::vector<uint8_t>& bytes, std::vector<uint8_t>* out) override {
+ *out = bytes;
+ return Status::ok();
+ }
static sp<IBinder> mHeldBinder;
Status holdBinder(const sp<IBinder>& binder) override {
mHeldBinder = binder;
diff --git a/libs/binder/tests/binderRpcTestService.cpp b/libs/binder/tests/binderRpcTestService.cpp
index aef9464..0084b9a 100644
--- a/libs/binder/tests/binderRpcTestService.cpp
+++ b/libs/binder/tests/binderRpcTestService.cpp
@@ -100,7 +100,9 @@
};
int main(int argc, char* argv[]) {
+#ifndef __ANDROID__
__android_log_set_logger(__android_log_stderr_logger);
+#endif
LOG_ALWAYS_FATAL_IF(argc != 3, "Invalid number of arguments: %d", argc);
unique_fd writeEnd(atoi(argv[1]));
diff --git a/libs/binder/tests/binderRpcUniversalTests.cpp b/libs/binder/tests/binderRpcUniversalTests.cpp
index c6fd487..d227e6e 100644
--- a/libs/binder/tests/binderRpcUniversalTests.cpp
+++ b/libs/binder/tests/binderRpcUniversalTests.cpp
@@ -209,6 +209,18 @@
EXPECT_EQ(0, MyBinderRpcSession::gNum);
}
+TEST_P(BinderRpc, SendLargeVector) {
+ auto proc = createRpcTestSocketServerProcess({});
+
+ // see libbinder internal Constants.h
+ const size_t kLargeSize = 550 * 1024;
+ const std::vector<uint8_t> kTestValue(kLargeSize / sizeof(uint8_t), 42);
+
+ std::vector<uint8_t> result;
+ EXPECT_OK(proc.rootIface->repeatBytes(kTestValue, &result));
+ EXPECT_EQ(result, kTestValue);
+}
+
TEST_P(BinderRpc, RepeatTheirBinder) {
auto proc = createRpcTestSocketServerProcess({});
@@ -498,9 +510,9 @@
// same thread, everything should have happened in a nested call. Otherwise,
// the callback will be processed on another thread.
if (callIsOneway || callbackIsOneway || delayed) {
- using std::literals::chrono_literals::operator""s;
+ using std::literals::chrono_literals::operator""ms;
RpcMutexUniqueLock _l(cb->mMutex);
- cb->mCv.wait_for(_l, 1s, [&] { return !cb->mValues.empty(); });
+ cb->mCv.wait_for(_l, 1500ms, [&] { return !cb->mValues.empty(); });
}
EXPECT_EQ(cb->mValues.size(), 1UL)
diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
index 849dc7c..45b2103 100644
--- a/libs/binder/tests/binderSafeInterfaceTest.cpp
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -789,7 +789,7 @@
std::optional<int32_t> waitForCallback() {
std::unique_lock<decltype(mMutex)> lock(mMutex);
bool success =
- mCondition.wait_for(lock, 100ms, [&]() { return static_cast<bool>(mValue); });
+ mCondition.wait_for(lock, 1000ms, [&]() { return static_cast<bool>(mValue); });
return success ? mValue : std::nullopt;
}
@@ -858,7 +858,13 @@
ASSERT_EQ(b + 1, bPlusOne);
}
-extern "C" int main(int argc, char **argv) {
+} // namespace tests
+} // namespace android
+
+int main(int argc, char** argv) {
+ using namespace android;
+ using namespace android::tests;
+
testing::InitGoogleTest(&argc, argv);
if (fork() == 0) {
@@ -875,6 +881,3 @@
return RUN_ALL_TESTS();
}
-
-} // namespace tests
-} // namespace android
diff --git a/libs/binder/tests/binderStabilityIntegrationTest.cpp b/libs/binder/tests/binderStabilityIntegrationTest.cpp
new file mode 100644
index 0000000..cbc4180
--- /dev/null
+++ b/libs/binder/tests/binderStabilityIntegrationTest.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2025 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 <binder/Binder.h>
+#include <binder/IServiceManager.h>
+#include <binder/Stability.h>
+#include <gtest/gtest.h>
+#include <procpartition/procpartition.h>
+
+using namespace android;
+using android::internal::Stability; // for testing only!
+using android::procpartition::getPartition;
+using android::procpartition::Partition;
+
+class BinderStabilityIntegrationTest : public testing::Test,
+ public ::testing::WithParamInterface<String16> {
+public:
+ virtual ~BinderStabilityIntegrationTest() {}
+};
+
+TEST_P(BinderStabilityIntegrationTest, ExpectedStabilityForItsPartition) {
+ const String16& serviceName = GetParam();
+
+ sp<IBinder> binder = defaultServiceManager()->checkService(serviceName);
+ if (!binder) GTEST_SKIP() << "Could not get service, may have gone away.";
+
+ pid_t pid;
+ status_t res = binder->getDebugPid(&pid);
+ if (res != OK) {
+ GTEST_SKIP() << "Could not talk to service to get PID, res: " << statusToString(res);
+ }
+
+ Partition partition = getPartition(pid);
+
+ Stability::Level level = Stability::Level::UNDECLARED;
+ switch (partition) {
+ case Partition::PRODUCT:
+ case Partition::SYSTEM:
+ case Partition::SYSTEM_EXT:
+ level = Stability::Level::SYSTEM;
+ break;
+ case Partition::VENDOR:
+ case Partition::ODM:
+ level = Stability::Level::VENDOR;
+ break;
+ case Partition::UNKNOWN:
+ GTEST_SKIP() << "Not sure of partition of process.";
+ return;
+ default:
+ ADD_FAILURE() << "Unrecognized partition for service: " << partition;
+ return;
+ }
+
+ ASSERT_TRUE(Stability::check(Stability::getRepr(binder.get()), level))
+ << "Binder hosted on partition " << partition
+ << " should have corresponding stability set.";
+}
+
+std::string PrintTestParam(
+ const testing::TestParamInfo<BinderStabilityIntegrationTest::ParamType>& info) {
+ std::string name = String8(info.param).c_str();
+ for (size_t i = 0; i < name.size(); i++) {
+ bool alnum = false;
+ alnum |= (name[i] >= 'a' && name[i] <= 'z');
+ alnum |= (name[i] >= 'A' && name[i] <= 'Z');
+ alnum |= (name[i] >= '0' && name[i] <= '9');
+ alnum |= (name[i] == '_');
+ if (!alnum) name[i] = '_';
+ }
+
+ // index for uniqueness
+ return std::to_string(info.index) + "__" + name;
+}
+
+INSTANTIATE_TEST_CASE_P(RegisteredServices, BinderStabilityIntegrationTest,
+ ::testing::ValuesIn(defaultServiceManager()->listServices()),
+ PrintTestParam);
diff --git a/libs/binder/tests/binderUtilsHostTest.cpp b/libs/binder/tests/binderUtilsHostTest.cpp
index 6301c74..ca70b66 100644
--- a/libs/binder/tests/binderUtilsHostTest.cpp
+++ b/libs/binder/tests/binderUtilsHostTest.cpp
@@ -56,7 +56,7 @@
});
auto elapsedMs = millisSince(start);
EXPECT_GE(elapsedMs, 1000);
- EXPECT_LT(elapsedMs, 2000);
+ EXPECT_LT(elapsedMs, 3000); // b/377571547: higher to reduce flake
ASSERT_TRUE(result.has_value());
EXPECT_EQ(std::nullopt, result->exitCode);
@@ -65,7 +65,7 @@
// ~CommandResult() called, child process is killed.
// Assert that the second sleep does not finish.
- EXPECT_LT(millisSince(start), 2000);
+ EXPECT_LT(millisSince(start), 3000);
}
TEST(UtilsHost, ExecuteLongRunning2) {
@@ -89,8 +89,8 @@
}
// ~CommandResult() called, child process is killed.
- // Assert that the second sleep does not finish.
- EXPECT_LT(millisSince(start), 6000);
+ // Assert that the last sleep does not finish.
+ EXPECT_LT(millisSince(start), 8000);
}
TEST(UtilsHost, KillWithSigKill) {
diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
index 07f0143..b2ba1ae 100644
--- a/libs/binder/tests/parcel_fuzzer/binder.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder.cpp
@@ -121,6 +121,11 @@
PARCEL_READ_NO_STATUS(size_t, hasFileDescriptors),
PARCEL_READ_NO_STATUS(std::vector<android::sp<android::IBinder>>, debugReadAllStrongBinders),
PARCEL_READ_NO_STATUS(std::vector<int>, debugReadAllFileDescriptors),
+ [] (const ::android::Parcel& p, FuzzedDataProvider&) {
+ FUZZ_LOG() << "about to markSensitive";
+ p.markSensitive();
+ FUZZ_LOG() << "markSensitive done";
+ },
[] (const ::android::Parcel& p, FuzzedDataProvider& provider) {
std::string interface = provider.ConsumeRandomLengthString();
FUZZ_LOG() << "about to enforceInterface: " << interface;
@@ -312,8 +317,6 @@
PARCEL_READ_NO_STATUS(int, readParcelFileDescriptor),
PARCEL_READ_WITH_STATUS(unique_fd, readUniqueFileDescriptor),
- PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<unique_fd>>,
- readUniqueFileDescriptorVector),
PARCEL_READ_WITH_STATUS(std::optional<std::vector<unique_fd>>, readUniqueFileDescriptorVector),
PARCEL_READ_WITH_STATUS(std::vector<unique_fd>, readUniqueFileDescriptorVector),
diff --git a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
index 2812da7..11fcb06 100644
--- a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
+++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
@@ -28,6 +28,9 @@
std::function<void(Parcel* p, FuzzedDataProvider& provider)> writeHeader;
std::vector<sp<IBinder>> extraBinders;
std::vector<binder::unique_fd> extraFds;
+
+ // internal state owned by fillRandomParcel, for Parcel views
+ std::vector<std::unique_ptr<Parcel>> extraParcels;
};
/**
diff --git a/libs/binder/tests/parcel_fuzzer/main.cpp b/libs/binder/tests/parcel_fuzzer/main.cpp
index 192f9d5..d06b2d9 100644
--- a/libs/binder/tests/parcel_fuzzer/main.cpp
+++ b/libs/binder/tests/parcel_fuzzer/main.cpp
@@ -70,7 +70,7 @@
uint32_t code = provider.ConsumeIntegral<uint32_t>();
uint32_t flag = provider.ConsumeIntegral<uint32_t>();
- FUZZ_LOG() << "backend: " << backend;
+ FUZZ_LOG() << "doTransactFuzz backend: " << backend;
RandomParcelOptions options;
@@ -101,7 +101,7 @@
// since we are only using a byte to index
CHECK_LE(reads.size(), 255u) << reads.size();
- FUZZ_LOG() << "backend: " << backend;
+ FUZZ_LOG() << "doReadFuzz backend: " << backend;
FUZZ_LOG() << "input: " << HexString(p.data(), p.dataSize());
FUZZ_LOG() << "instructions: " << HexString(instructions.data(), instructions.size());
@@ -122,10 +122,15 @@
RandomParcelOptions options;
P p;
+ // small amount of initial Parcel data, since fillRandomParcel uses makeDangerousViewOf
+ std::vector<uint8_t> parcelData =
+ provider.ConsumeBytes<uint8_t>(provider.ConsumeIntegralInRange<size_t>(0, 20));
+ fillRandomParcel(&p, FuzzedDataProvider(parcelData.data(), parcelData.size()), &options);
+
// since we are only using a byte to index
CHECK_LE(reads.size() + writes.size(), 255u) << reads.size();
- FUZZ_LOG() << "backend: " << backend;
+ FUZZ_LOG() << "doReadWriteFuzz backend: " << backend;
while (provider.remaining_bytes() > 0) {
uint8_t idx = provider.ConsumeIntegralInRange<uint8_t>(0, reads.size() + writes.size() - 1);
diff --git a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
index 7c19614..61b9612 100644
--- a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
+++ b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
@@ -17,6 +17,7 @@
#include <fuzzbinder/random_parcel.h>
#include <android-base/logging.h>
+#include <binder/Functional.h>
#include <binder/RpcSession.h>
#include <binder/RpcTransportRaw.h>
#include <fuzzbinder/random_binder.h>
@@ -32,10 +33,39 @@
CHECK(OK == p->write(data.data(), data.size()));
}
-void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider, RandomParcelOptions* options) {
+void fillRandomParcel(Parcel* outputParcel, FuzzedDataProvider&& provider,
+ RandomParcelOptions* options) {
CHECK_NE(options, nullptr);
- if (provider.ConsumeBool()) {
+ const uint8_t fuzzerParcelOptions = provider.ConsumeIntegral<uint8_t>();
+ const bool resultShouldBeView = fuzzerParcelOptions & 1;
+ const bool resultShouldBeRpc = fuzzerParcelOptions & 2;
+ const bool resultShouldMarkSensitive = fuzzerParcelOptions & 4;
+
+ auto sensitivity_guard = binder::impl::make_scope_guard([&]() {
+ if (resultShouldMarkSensitive) {
+ outputParcel->markSensitive();
+ }
+ });
+
+ Parcel* p;
+ if (resultShouldBeView) {
+ options->extraParcels.push_back(std::make_unique<Parcel>());
+ // held for duration of test, so that view will be valid
+ p = options->extraParcels[options->extraParcels.size() - 1].get();
+ } else {
+ p = outputParcel; // directly fill out the output Parcel
+ }
+
+ // must be last guard, so outputParcel gets setup as view before
+ // other guards
+ auto viewify_guard = binder::impl::make_scope_guard([&]() {
+ if (resultShouldBeView) {
+ outputParcel->makeDangerousViewOf(p);
+ }
+ });
+
+ if (resultShouldBeRpc) {
auto session = RpcSession::make(RpcTransportCtxFactoryRaw::make());
CHECK_EQ(OK, session->addNullDebuggingClient());
// Set the protocol version so that we don't crash if the session
diff --git a/libs/binder/tests/parcel_fuzzer/random_parcel_seeds.cpp b/libs/binder/tests/parcel_fuzzer/random_parcel_seeds.cpp
index 0ed8a55..3cb6289 100644
--- a/libs/binder/tests/parcel_fuzzer/random_parcel_seeds.cpp
+++ b/libs/binder/tests/parcel_fuzzer/random_parcel_seeds.cpp
@@ -281,9 +281,9 @@
// This buffer holds the bytes which will be used for fillRandomParcel API
std::vector<uint8_t> fillParcelBuffer;
- // Don't take rpc path
- uint8_t rpcBranch = 0;
- impl::writeReversedBuffer(fillParcelBuffer, rpcBranch);
+ // Use all default options.
+ uint8_t parcelOptions = 0;
+ impl::writeReversedBuffer(fillParcelBuffer, parcelOptions);
// Implicit branch on this path -> options->writeHeader(p, provider)
uint8_t writeHeaderInternal = 0;
diff --git a/libs/binder/tests/parcel_fuzzer/test_fuzzer/Android.bp b/libs/binder/tests/parcel_fuzzer/test_fuzzer/Android.bp
index 690c39a..4008c56 100644
--- a/libs/binder/tests/parcel_fuzzer/test_fuzzer/Android.bp
+++ b/libs/binder/tests/parcel_fuzzer/test_fuzzer/Android.bp
@@ -59,6 +59,11 @@
darwin: {
enabled: false,
},
+ host: {
+ data_libs: [
+ "libc++",
+ ],
+ },
},
test_suites: ["general-tests"],
}
diff --git a/libs/binder/tests/parcel_fuzzer/test_fuzzer/run_fuzz_service_test.sh b/libs/binder/tests/parcel_fuzzer/test_fuzzer/run_fuzz_service_test.sh
index 5d68fe1..b623c5f 100755
--- a/libs/binder/tests/parcel_fuzzer/test_fuzzer/run_fuzz_service_test.sh
+++ b/libs/binder/tests/parcel_fuzzer/test_fuzzer/run_fuzz_service_test.sh
@@ -39,6 +39,7 @@
else
echo -e "${color_failed}Failed: Unable to find successful fuzzing output from test_service_fuzzer_should_crash"
echo "${color_reset}"
+ cat "$FUZZER_OUT"
exit 1
fi
done
diff --git a/libs/binder/trusty/RpcServerTrusty.cpp b/libs/binder/trusty/RpcServerTrusty.cpp
index 17919c2..0580046 100644
--- a/libs/binder/trusty/RpcServerTrusty.cpp
+++ b/libs/binder/trusty/RpcServerTrusty.cpp
@@ -151,8 +151,10 @@
int RpcServerTrusty::handleMessageInternal(void* ctx) {
auto* channelContext = reinterpret_cast<ChannelContext*>(ctx);
- LOG_ALWAYS_FATAL_IF(channelContext == nullptr,
- "bad state: message received on uninitialized channel");
+ if (channelContext == nullptr) {
+ LOG_RPC_DETAIL("bad state: message received on uninitialized channel");
+ return ERR_BAD_STATE;
+ }
auto& session = channelContext->session;
auto& connection = channelContext->connection;
diff --git a/libs/binder/trusty/RpcTransportTipcTrusty.cpp b/libs/binder/trusty/RpcTransportTipcTrusty.cpp
index c74ba0a..65ad896 100644
--- a/libs/binder/trusty/RpcTransportTipcTrusty.cpp
+++ b/libs/binder/trusty/RpcTransportTipcTrusty.cpp
@@ -47,6 +47,71 @@
return mHaveMessage ? OK : WOULD_BLOCK;
}
+ void moveMsgStart(ipc_msg_t* msg, size_t msg_size, size_t offset) {
+ LOG_ALWAYS_FATAL_IF(offset > msg_size, "tried to move message past its end %zd>%zd", offset,
+ msg_size);
+ while (true) {
+ if (offset == 0) {
+ break;
+ }
+ if (offset >= msg->iov[0].iov_len) {
+ // Move to the next iov, this one was sent already
+ offset -= msg->iov[0].iov_len;
+ msg->iov++;
+ msg->num_iov -= 1;
+ } else {
+ // We need to move the base of the current iov
+ msg->iov[0].iov_len -= offset;
+ msg->iov[0].iov_base = static_cast<char*>(msg->iov[0].iov_base) + offset;
+ offset = 0;
+ }
+ }
+ // We only send handles on the first message. This can be changed in the future if we want
+ // to send more handles than the maximum per message limit (which would require sending
+ // multiple messages). The current code makes sure that we send less handles than the
+ // maximum trusty allows.
+ msg->num_handles = 0;
+ }
+
+ status_t sendTrustyMsg(ipc_msg_t* msg, size_t msg_size) {
+ do {
+ ssize_t rc = send_msg(mSocket.fd.get(), msg);
+ if (rc == ERR_NOT_ENOUGH_BUFFER) {
+ // Peer is blocked, wait until it unblocks.
+ // TODO: when tipc supports a send-unblocked handler,
+ // save the message here in a queue and retry it asynchronously
+ // when the handler gets called by the library
+ uevent uevt;
+ do {
+ rc = ::wait(mSocket.fd.get(), &uevt, INFINITE_TIME);
+ if (rc < 0) {
+ return statusFromTrusty(rc);
+ }
+ if (uevt.event & IPC_HANDLE_POLL_HUP) {
+ return DEAD_OBJECT;
+ }
+ } while (!(uevt.event & IPC_HANDLE_POLL_SEND_UNBLOCKED));
+
+ // Retry the send, it should go through this time because
+ // sending is now unblocked
+ rc = send_msg(mSocket.fd.get(), msg);
+ }
+ if (rc < 0) {
+ return statusFromTrusty(rc);
+ }
+ size_t sent_bytes = static_cast<size_t>(rc);
+ if (sent_bytes < msg_size) {
+ moveMsgStart(msg, msg_size, static_cast<size_t>(sent_bytes));
+ msg_size -= sent_bytes;
+ } else {
+ LOG_ALWAYS_FATAL_IF(static_cast<size_t>(rc) != msg_size,
+ "Sent the wrong number of bytes %zd!=%zu", rc, msg_size);
+ break;
+ }
+ } while (true);
+ return OK;
+ }
+
status_t interruptableWriteFully(
FdTrigger* /*fdTrigger*/, iovec* iovs, int niovs,
const std::optional<SmallFunction<status_t()>>& /*altPoll*/,
@@ -86,34 +151,7 @@
msg.handles = msgHandles;
}
- ssize_t rc = send_msg(mSocket.fd.get(), &msg);
- if (rc == ERR_NOT_ENOUGH_BUFFER) {
- // Peer is blocked, wait until it unblocks.
- // TODO: when tipc supports a send-unblocked handler,
- // save the message here in a queue and retry it asynchronously
- // when the handler gets called by the library
- uevent uevt;
- do {
- rc = ::wait(mSocket.fd.get(), &uevt, INFINITE_TIME);
- if (rc < 0) {
- return statusFromTrusty(rc);
- }
- if (uevt.event & IPC_HANDLE_POLL_HUP) {
- return DEAD_OBJECT;
- }
- } while (!(uevt.event & IPC_HANDLE_POLL_SEND_UNBLOCKED));
-
- // Retry the send, it should go through this time because
- // sending is now unblocked
- rc = send_msg(mSocket.fd.get(), &msg);
- }
- if (rc < 0) {
- return statusFromTrusty(rc);
- }
- LOG_ALWAYS_FATAL_IF(static_cast<size_t>(rc) != size,
- "Sent the wrong number of bytes %zd!=%zu", rc, size);
-
- return OK;
+ return sendTrustyMsg(&msg, size);
}
status_t interruptableReadFully(
diff --git a/libs/binder/trusty/binderRpcTest/manifest.json b/libs/binder/trusty/binderRpcTest/manifest.json
index 6e20b8a..da0f2ed 100644
--- a/libs/binder/trusty/binderRpcTest/manifest.json
+++ b/libs/binder/trusty/binderRpcTest/manifest.json
@@ -1,6 +1,6 @@
{
"uuid": "9dbe9fb8-60fd-4bdd-af86-03e95d7ad78b",
"app_name": "binderRpcTest",
- "min_heap": 262144,
+ "min_heap": 4194304,
"min_stack": 20480
}
diff --git a/libs/binder/trusty/binderRpcTest/service/manifest.json b/libs/binder/trusty/binderRpcTest/service/manifest.json
index d2a1fc0..55ff49c 100644
--- a/libs/binder/trusty/binderRpcTest/service/manifest.json
+++ b/libs/binder/trusty/binderRpcTest/service/manifest.json
@@ -1,7 +1,7 @@
{
"uuid": "87e424e5-69d7-4bbd-8b7c-7e24812cbc94",
"app_name": "binderRpcTestService",
- "min_heap": 65536,
+ "min_heap": 4194304,
"min_stack": 20480,
"mgmt_flags": {
"restart_on_exit": true,
diff --git a/libs/binder/trusty/rules.mk b/libs/binder/trusty/rules.mk
index 5e38ad0..dd9d4d1 100644
--- a/libs/binder/trusty/rules.mk
+++ b/libs/binder/trusty/rules.mk
@@ -64,14 +64,24 @@
MODULE_EXPORT_INCLUDES += \
$(LIBBINDER_DIR)/ndk/include_cpp \
+ifeq (false,$(call TOBOOL,$(USE_SYSTEM_BINDER)))
+BINDER_EXTRA_COMPILE_FLAGS := \
+ -D__ANDROID_VENDOR__ \
+ -D__ANDROID_VNDK__ \
+
+else
+BINDER_EXTRA_COMPILE_FLAGS := \
+ -DANDROID_PLATFORM \
+
+endif
+
MODULE_EXPORT_COMPILEFLAGS += \
-DBINDER_RPC_SINGLE_THREADED \
-DBINDER_ENABLE_LIBLOG_ASSERT \
-DBINDER_DISABLE_NATIVE_HANDLE \
-DBINDER_DISABLE_BLOB \
-DBINDER_NO_LIBBASE \
- -D__ANDROID_VENDOR__ \
- -D__ANDROID_VNDK__ \
+ $(BINDER_EXTRA_COMPILE_FLAGS)
# libbinder has some deprecated declarations that we want to produce warnings
# not errors
diff --git a/libs/binder/trusty/rust/binder_ndk_sys/rules.mk b/libs/binder/trusty/rust/binder_ndk_sys/rules.mk
index 2aaa061..56d711e 100644
--- a/libs/binder/trusty/rust/binder_ndk_sys/rules.mk
+++ b/libs/binder/trusty/rust/binder_ndk_sys/rules.mk
@@ -30,9 +30,14 @@
trusty/user/base/lib/trusty-sys \
MODULE_RUSTFLAGS += \
- --cfg 'android_vendor' \
--cfg 'trusty' \
+ifeq (false,$(call TOBOOL,$(USE_SYSTEM_BINDER)))
+MODULE_RUSTFLAGS += \
+ --cfg 'android_vendor' \
+
+endif
+
MODULE_BINDGEN_SRC_HEADER := $(LIBBINDER_DIR)/rust/sys/BinderBindings.hpp
# Add the flags from the flag file
diff --git a/libs/binder/trusty/rust/binder_rpc_test/binder_rpc_test_session/lib.rs b/libs/binder/trusty/rust/binder_rpc_test/binder_rpc_test_session/lib.rs
index 22cba44..caf3117 100644
--- a/libs/binder/trusty/rust/binder_rpc_test/binder_rpc_test_session/lib.rs
+++ b/libs/binder/trusty/rust/binder_rpc_test/binder_rpc_test_session/lib.rs
@@ -82,6 +82,9 @@
fn repeatBinder(&self, _binder: Option<&SpIBinder>) -> Result<Option<SpIBinder>, Status> {
todo!()
}
+ fn repeatBytes(&self, _bytes: &[u8]) -> Result<Vec<u8>, Status> {
+ todo!()
+ }
fn holdBinder(&self, _binder: Option<&SpIBinder>) -> Result<(), Status> {
todo!()
}
diff --git a/libs/binder/trusty/rust/binder_rpc_test/service/main.rs b/libs/binder/trusty/rust/binder_rpc_test/service/main.rs
index c4a758a..6f454be 100644
--- a/libs/binder/trusty/rust/binder_rpc_test/service/main.rs
+++ b/libs/binder/trusty/rust/binder_rpc_test/service/main.rs
@@ -96,6 +96,9 @@
None => Err(Status::from(StatusCode::BAD_VALUE)),
}
}
+ fn repeatBytes(&self, _bytes: &[u8]) -> Result<Vec<u8>, Status> {
+ todo!()
+ }
fn holdBinder(&self, binder: Option<&SpIBinder>) -> Result<(), Status> {
*HOLD_BINDER.lock().unwrap() = binder.cloned();
Ok(())
diff --git a/libs/binder/trusty/rust/rules.mk b/libs/binder/trusty/rust/rules.mk
index e622b22..acd74d2 100644
--- a/libs/binder/trusty/rust/rules.mk
+++ b/libs/binder/trusty/rust/rules.mk
@@ -32,9 +32,15 @@
trusty/user/base/lib/trusty-sys \
MODULE_RUSTFLAGS += \
- --cfg 'android_vendor' \
--cfg 'trusty' \
+ifeq (false,$(call TOBOOL,$(USE_SYSTEM_BINDER)))
+MODULE_RUSTFLAGS += \
+ --cfg 'android_vendor' \
+
+endif
+
+
# Trusty does not have `ProcessState`, so there are a few
# doc links in `IBinder` that are still broken.
MODULE_RUSTFLAGS += \
diff --git a/libs/binderdebug/stats.cpp b/libs/binderdebug/stats.cpp
index 9c26afa..972fbd5 100644
--- a/libs/binderdebug/stats.cpp
+++ b/libs/binderdebug/stats.cpp
@@ -22,9 +22,9 @@
#include <inttypes.h>
-namespace android {
+int main() {
+ using namespace android;
-extern "C" int main() {
// ignore args - we only print csv
// we should use a csv library here for escaping, because
@@ -58,5 +58,3 @@
}
return 0;
}
-
-} // namespace android
diff --git a/libs/binderdebug/tests/binderdebug_test.cpp b/libs/binderdebug/tests/binderdebug_test.cpp
index ea799c0..ad2b581 100644
--- a/libs/binderdebug/tests/binderdebug_test.cpp
+++ b/libs/binderdebug/tests/binderdebug_test.cpp
@@ -60,8 +60,15 @@
EXPECT_GE(pidInfo.threadCount, 1);
}
-extern "C" {
+} // namespace test
+} // namespace binderdebug
+} // namespace android
+
int main(int argc, char** argv) {
+ using namespace android;
+ using namespace android::binderdebug;
+ using namespace android::binderdebug::test;
+
::testing::InitGoogleTest(&argc, argv);
// Create a child/client process to call into the main process so we can ensure
@@ -84,7 +91,3 @@
return RUN_ALL_TESTS();
}
-} // extern "C"
-} // namespace test
-} // namespace binderdebug
-} // namespace android
diff --git a/libs/debugstore/rust/src/core.rs b/libs/debugstore/rust/src/core.rs
index 6bf79d4..16147dd 100644
--- a/libs/debugstore/rust/src/core.rs
+++ b/libs/debugstore/rust/src/core.rs
@@ -48,7 +48,7 @@
///
/// This constant is used as a part of the debug store's data format,
/// allowing for version tracking and compatibility checks.
- const ENCODE_VERSION: u32 = 1;
+ const ENCODE_VERSION: u32 = 3;
/// Creates a new instance of `DebugStore` with specified event limit and maximum delay.
fn new() -> Self {
@@ -123,20 +123,25 @@
impl fmt::Display for DebugStore {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // Write the debug store header information
let uptime_now = uptimeMillis();
write!(f, "{},{},{}::", Self::ENCODE_VERSION, self.event_store.len(), uptime_now)?;
+ // Join events with a separator
write!(
f,
"{}",
- self.event_store.fold(String::new(), |mut acc, event| {
+ self.event_store.rfold(String::new(), |mut acc, event| {
if !acc.is_empty() {
acc.push_str("||");
}
acc.push_str(&event.to_string());
acc
})
- )
+ )?;
+
+ // Write the debug store footer
+ write!(f, ";;")
}
}
diff --git a/libs/debugstore/rust/src/storage.rs b/libs/debugstore/rust/src/storage.rs
index 2ad7f4e..47760f3 100644
--- a/libs/debugstore/rust/src/storage.rs
+++ b/libs/debugstore/rust/src/storage.rs
@@ -32,14 +32,18 @@
self.insertion_buffer.force_push(value);
}
- /// Folds over the elements in the storage using the provided function.
- pub fn fold<U, F>(&self, init: U, mut func: F) -> U
+ /// Folds over the elements in the storage in reverse order using the provided function.
+ pub fn rfold<U, F>(&self, init: U, mut func: F) -> U
where
F: FnMut(U, &T) -> U,
{
- let mut acc = init;
+ let mut items = Vec::new();
while let Some(value) = self.insertion_buffer.pop() {
- acc = func(acc, &value);
+ items.push(value);
+ }
+ let mut acc = init;
+ for value in items.iter().rev() {
+ acc = func(acc, value);
}
acc
}
@@ -59,18 +63,18 @@
let storage = Storage::<i32, 10>::new();
storage.insert(7);
- let sum = storage.fold(0, |acc, &x| acc + x);
+ let sum = storage.rfold(0, |acc, &x| acc + x);
assert_eq!(sum, 7, "The sum of the elements should be equal to the inserted value.");
}
#[test]
- fn test_fold_functionality() {
+ fn test_rfold_functionality() {
let storage = Storage::<i32, 5>::new();
storage.insert(1);
storage.insert(2);
storage.insert(3);
- let sum = storage.fold(0, |acc, &x| acc + x);
+ let sum = storage.rfold(0, |acc, &x| acc + x);
assert_eq!(
sum, 6,
"The sum of the elements should be equal to the sum of inserted values."
@@ -84,13 +88,13 @@
storage.insert(2);
storage.insert(5);
- let first_sum = storage.fold(0, |acc, &x| acc + x);
+ let first_sum = storage.rfold(0, |acc, &x| acc + x);
assert_eq!(first_sum, 8, "The sum of the elements should be equal to the inserted values.");
storage.insert(30);
storage.insert(22);
- let second_sum = storage.fold(0, |acc, &x| acc + x);
+ let second_sum = storage.rfold(0, |acc, &x| acc + x);
assert_eq!(
second_sum, 52,
"The sum of the elements should be equal to the inserted values."
@@ -103,7 +107,7 @@
storage.insert(1);
// This value should overwrite the previously inserted value (1).
storage.insert(4);
- let sum = storage.fold(0, |acc, &x| acc + x);
+ let sum = storage.rfold(0, |acc, &x| acc + x);
assert_eq!(sum, 4, "The sum of the elements should be equal to the inserted values.");
}
@@ -128,7 +132,24 @@
thread.join().expect("Thread should finish without panicking");
}
- let count = storage.fold(0, |acc, _| acc + 1);
+ let count = storage.rfold(0, |acc, _| acc + 1);
assert_eq!(count, 100, "Storage should be filled to its limit with concurrent insertions.");
}
+
+ #[test]
+ fn test_rfold_order() {
+ let storage = Storage::<i32, 5>::new();
+ storage.insert(1);
+ storage.insert(2);
+ storage.insert(3);
+
+ let mut result = Vec::new();
+ storage.rfold((), |_, &x| result.push(x));
+
+ assert_eq!(
+ result,
+ vec![3, 2, 1],
+ "Elements should be processed in reverse order of insertion"
+ );
+ }
}
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index a9bd11e..43ee33e 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -101,7 +101,7 @@
"android.hardware.automotive.remoteaccess.IRemoteAccess",
"android.hardware.automotive.vehicle.IVehicle",
"android.hardware.biometrics.face.IBiometricsFace",
- "android.hardware.biometrics.fingerprint.IBiometricsFingerprint",
+ "android.hardware.biometrics.fingerprint.IFingerprint",
"android.hardware.camera.provider.ICameraProvider",
"android.hardware.drm.IDrmFactory",
"android.hardware.graphics.allocator.IAllocator",
diff --git a/libs/fakeservicemanager/include/fakeservicemanager/FakeServiceManager.h b/libs/fakeservicemanager/include/fakeservicemanager/FakeServiceManager.h
index f62241d..f2b2aa7 100644
--- a/libs/fakeservicemanager/include/fakeservicemanager/FakeServiceManager.h
+++ b/libs/fakeservicemanager/include/fakeservicemanager/FakeServiceManager.h
@@ -65,6 +65,7 @@
std::vector<IServiceManager::ServiceDebugInfo> getServiceDebugInfo() override;
+ void enableAddServiceCache(bool /*value*/) override {}
// Clear all of the registered services
void clear();
diff --git a/libs/ftl/Android.bp b/libs/ftl/Android.bp
index 368f5e0..5244442 100644
--- a/libs/ftl/Android.bp
+++ b/libs/ftl/Android.bp
@@ -21,10 +21,12 @@
"enum_test.cpp",
"expected_test.cpp",
"fake_guard_test.cpp",
+ "finalizer_test.cpp",
"flags_test.cpp",
"function_test.cpp",
"future_test.cpp",
"hash_test.cpp",
+ "ignore_test.cpp",
"match_test.cpp",
"mixins_test.cpp",
"non_null_test.cpp",
diff --git a/libs/ftl/finalizer_test.cpp b/libs/ftl/finalizer_test.cpp
new file mode 100644
index 0000000..4f5c225
--- /dev/null
+++ b/libs/ftl/finalizer_test.cpp
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2024 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 <memory>
+#include <type_traits>
+#include <utility>
+
+#include <ftl/finalizer.h>
+#include <gtest/gtest.h>
+
+namespace android::test {
+
+namespace {
+
+struct Counter {
+ constexpr auto increment_fn() {
+ return [this] { ++value_; };
+ }
+
+ auto increment_finalizer() {
+ return ftl::Finalizer([this] { ++value_; });
+ }
+
+ [[nodiscard]] constexpr auto value() const -> int { return value_; }
+
+ private:
+ int value_ = 0;
+};
+
+struct CounterPair {
+ constexpr auto increment_first_fn() { return first.increment_fn(); }
+ constexpr auto increment_second_fn() { return second.increment_fn(); }
+ [[nodiscard]] constexpr auto values() const -> std::pair<int, int> {
+ return {first.value(), second.value()};
+ }
+
+ private:
+ Counter first;
+ Counter second;
+};
+
+} // namespace
+
+TEST(Finalizer, DefaultConstructionAndNoOpDestructionWhenPolymorphicType) {
+ ftl::FinalizerStd finalizer1;
+ ftl::FinalizerFtl finalizer2;
+ ftl::FinalizerFtl1 finalizer3;
+ ftl::FinalizerFtl2 finalizer4;
+ ftl::FinalizerFtl3 finalizer5;
+}
+
+TEST(Finalizer, InvokesTheFunctionOnDestruction) {
+ Counter counter;
+ {
+ const auto finalizer = counter.increment_finalizer();
+ EXPECT_EQ(counter.value(), 0);
+ }
+ EXPECT_EQ(counter.value(), 1);
+}
+
+TEST(Finalizer, InvocationCanBeCanceled) {
+ Counter counter;
+ {
+ auto finalizer = counter.increment_finalizer();
+ EXPECT_EQ(counter.value(), 0);
+ finalizer.cancel();
+ EXPECT_EQ(counter.value(), 0);
+ }
+ EXPECT_EQ(counter.value(), 0);
+}
+
+TEST(Finalizer, InvokesTheFunctionOnce) {
+ Counter counter;
+ {
+ auto finalizer = counter.increment_finalizer();
+ EXPECT_EQ(counter.value(), 0);
+ finalizer();
+ EXPECT_EQ(counter.value(), 1);
+ finalizer();
+ EXPECT_EQ(counter.value(), 1);
+ }
+ EXPECT_EQ(counter.value(), 1);
+}
+
+TEST(Finalizer, SelfInvocationIsAllowedAndANoOp) {
+ Counter counter;
+ ftl::FinalizerStd finalizer;
+ finalizer = ftl::Finalizer([&]() {
+ counter.increment_fn()();
+ finalizer(); // recursive invocation should do nothing.
+ });
+ EXPECT_EQ(counter.value(), 0);
+ finalizer();
+ EXPECT_EQ(counter.value(), 1);
+}
+
+TEST(Finalizer, MoveConstruction) {
+ Counter counter;
+ {
+ ftl::FinalizerStd outer_finalizer = counter.increment_finalizer();
+ EXPECT_EQ(counter.value(), 0);
+ {
+ ftl::FinalizerStd inner_finalizer = std::move(outer_finalizer);
+ static_assert(std::is_same_v<decltype(inner_finalizer), decltype(outer_finalizer)>);
+ EXPECT_EQ(counter.value(), 0);
+ }
+ EXPECT_EQ(counter.value(), 1);
+ }
+ EXPECT_EQ(counter.value(), 1);
+}
+
+TEST(Finalizer, MoveConstructionWithImplicitConversion) {
+ Counter counter;
+ {
+ auto outer_finalizer = counter.increment_finalizer();
+ EXPECT_EQ(counter.value(), 0);
+ {
+ ftl::FinalizerStd inner_finalizer = std::move(outer_finalizer);
+ static_assert(!std::is_same_v<decltype(inner_finalizer), decltype(outer_finalizer)>);
+ EXPECT_EQ(counter.value(), 0);
+ }
+ EXPECT_EQ(counter.value(), 1);
+ }
+ EXPECT_EQ(counter.value(), 1);
+}
+
+TEST(Finalizer, MoveAssignment) {
+ CounterPair pair;
+ {
+ ftl::FinalizerStd outer_finalizer = ftl::Finalizer(pair.increment_first_fn());
+ EXPECT_EQ(pair.values(), std::make_pair(0, 0));
+
+ {
+ ftl::FinalizerStd inner_finalizer = ftl::Finalizer(pair.increment_second_fn());
+ static_assert(std::is_same_v<decltype(inner_finalizer), decltype(outer_finalizer)>);
+ EXPECT_EQ(pair.values(), std::make_pair(0, 0));
+ inner_finalizer = std::move(outer_finalizer);
+ EXPECT_EQ(pair.values(), std::make_pair(0, 1));
+ }
+ EXPECT_EQ(pair.values(), std::make_pair(1, 1));
+ }
+ EXPECT_EQ(pair.values(), std::make_pair(1, 1));
+}
+
+TEST(Finalizer, MoveAssignmentWithImplicitConversion) {
+ CounterPair pair;
+ {
+ auto outer_finalizer = ftl::Finalizer(pair.increment_first_fn());
+ EXPECT_EQ(pair.values(), std::make_pair(0, 0));
+
+ {
+ ftl::FinalizerStd inner_finalizer = ftl::Finalizer(pair.increment_second_fn());
+ static_assert(!std::is_same_v<decltype(inner_finalizer), decltype(outer_finalizer)>);
+ EXPECT_EQ(pair.values(), std::make_pair(0, 0));
+ inner_finalizer = std::move(outer_finalizer);
+ EXPECT_EQ(pair.values(), std::make_pair(0, 1));
+ }
+ EXPECT_EQ(pair.values(), std::make_pair(1, 1));
+ }
+ EXPECT_EQ(pair.values(), std::make_pair(1, 1));
+}
+
+TEST(Finalizer, NullifiesTheFunctionWhenInvokedIfPossible) {
+ auto shared = std::make_shared<int>(0);
+ std::weak_ptr<int> weak = shared;
+
+ int count = 0;
+ {
+ auto lambda = [capture = std::move(shared)]() {};
+ auto finalizer = ftl::Finalizer(std::move(lambda));
+ EXPECT_FALSE(weak.expired());
+
+ // A lambda is not nullable. Invoking the finalizer cannot destroy it to destroy the lambda's
+ // capture.
+ finalizer();
+ EXPECT_FALSE(weak.expired());
+ }
+ // The lambda is only destroyed when the finalizer instance is destroyed.
+ EXPECT_TRUE(weak.expired());
+
+ shared = std::make_shared<int>(0);
+ weak = shared;
+
+ {
+ auto lambda = [capture = std::move(shared)]() {};
+ auto finalizer = ftl::FinalizerStd(std::move(lambda));
+ EXPECT_FALSE(weak.expired());
+
+ // Since std::function is used, and is nullable, invoking the finalizer will destroy the
+ // contained function, which will destroy the lambda's capture.
+ finalizer();
+ EXPECT_TRUE(weak.expired());
+ }
+}
+
+} // namespace android::test
diff --git a/libs/ftl/flags_test.cpp b/libs/ftl/flags_test.cpp
index 1279d11..bb43e8d 100644
--- a/libs/ftl/flags_test.cpp
+++ b/libs/ftl/flags_test.cpp
@@ -17,7 +17,7 @@
#include <ftl/flags.h>
#include <gtest/gtest.h>
-#include <type_traits>
+#include <initializer_list>
namespace android::test {
@@ -59,6 +59,18 @@
ASSERT_FALSE(flags.all(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE));
}
+TEST(Flags, ImplicitConstructionAndAssignmentFromInitializerList) {
+ Flags<TestFlags> flags = {TestFlags::ONE, TestFlags::THREE};
+ ASSERT_TRUE(flags.test(TestFlags::ONE));
+ ASSERT_FALSE(flags.test(TestFlags::TWO));
+ ASSERT_TRUE(flags.test(TestFlags::THREE));
+
+ flags = {};
+ ASSERT_FALSE(flags.test(TestFlags::ONE));
+ ASSERT_FALSE(flags.test(TestFlags::TWO));
+ ASSERT_FALSE(flags.test(TestFlags::THREE));
+}
+
TEST(Flags, DefaultConstructor_hasNoFlagsSet) {
Flags<TestFlags> flags;
ASSERT_FALSE(flags.any(TestFlags::ONE | TestFlags::TWO | TestFlags::THREE));
diff --git a/libs/ftl/ignore_test.cpp b/libs/ftl/ignore_test.cpp
new file mode 100644
index 0000000..5d5c67b
--- /dev/null
+++ b/libs/ftl/ignore_test.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2025 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 <string>
+
+#include <ftl/ignore.h>
+#include <gtest/gtest.h>
+
+namespace android::test {
+namespace {
+
+// Keep in sync with the example usage in the header file.
+
+void ftl_ignore_multiple(int arg1, const char* arg2, std::string arg3) {
+ // When invoked, all the arguments are ignored.
+ ftl::ignore(arg1, arg2, arg3);
+}
+
+void ftl_ignore_single(int arg) {
+ // It can be used like std::ignore to ignore a single value
+ ftl::ignore = arg;
+}
+
+} // namespace
+
+TEST(Ignore, Example) {
+ // The real example test is that there are no compiler warnings for unused arguments above.
+
+ // Use the example functions to avoid a compiler warning about unused functions.
+ ftl_ignore_multiple(0, "a", "b");
+ ftl_ignore_single(0);
+}
+
+} // namespace android::test
diff --git a/libs/gralloc/types/Android.bp b/libs/gralloc/types/Android.bp
index 8dabc2c..f9f304a 100644
--- a/libs/gralloc/types/Android.bp
+++ b/libs/gralloc/types/Android.bp
@@ -56,7 +56,7 @@
],
export_shared_lib_headers: [
- "android.hardware.graphics.common-V5-ndk",
+ "android.hardware.graphics.common-V6-ndk",
"android.hardware.graphics.mapper@4.0",
"libhidlbase",
],
diff --git a/libs/graphicsenv/Android.bp b/libs/graphicsenv/Android.bp
index af50a29..dce7778 100644
--- a/libs/graphicsenv/Android.bp
+++ b/libs/graphicsenv/Android.bp
@@ -21,10 +21,27 @@
default_applicable_licenses: ["frameworks_native_license"],
}
+aconfig_declarations {
+ name: "graphicsenv_flags",
+ package: "com.android.graphics.graphicsenv.flags",
+ container: "system",
+ srcs: ["graphicsenv_flags.aconfig"],
+}
+
+cc_aconfig_library {
+ name: "graphicsenv_flags_c_lib",
+ aconfig_declarations: "graphicsenv_flags",
+}
+
cc_library_shared {
name: "libgraphicsenv",
+ defaults: [
+ "aconfig_lib_cc_static_link.defaults",
+ ],
+
srcs: [
+ "FeatureOverrides.cpp",
"GpuStatsInfo.cpp",
"GraphicsEnv.cpp",
"IGpuService.cpp",
@@ -35,6 +52,10 @@
"-Werror",
],
+ static_libs: [
+ "graphicsenv_flags_c_lib",
+ ],
+
shared_libs: [
"libbase",
"libbinder",
@@ -42,6 +63,7 @@
"libdl_android",
"liblog",
"libutils",
+ "server_configurable_flags",
],
header_libs: [
diff --git a/libs/graphicsenv/FeatureOverrides.cpp b/libs/graphicsenv/FeatureOverrides.cpp
new file mode 100644
index 0000000..9e7a4cf
--- /dev/null
+++ b/libs/graphicsenv/FeatureOverrides.cpp
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2025 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 <cinttypes>
+
+#include <android-base/stringprintf.h>
+#include <binder/Parcel.h>
+#include <graphicsenv/FeatureOverrides.h>
+
+namespace android {
+
+using base::StringAppendF;
+
+status_t FeatureConfig::writeToParcel(Parcel* parcel) const {
+ status_t status;
+
+ status = parcel->writeUtf8AsUtf16(mFeatureName);
+ if (status != OK) {
+ return status;
+ }
+ status = parcel->writeBool(mEnabled);
+ if (status != OK) {
+ return status;
+ }
+ // Number of GPU vendor IDs.
+ status = parcel->writeVectorSize(mGpuVendorIDs);
+ if (status != OK) {
+ return status;
+ }
+ // GPU vendor IDs.
+ for (const auto& vendorID : mGpuVendorIDs) {
+ status = parcel->writeUint32(vendorID);
+ if (status != OK) {
+ return status;
+ }
+ }
+
+ return OK;
+}
+
+status_t FeatureConfig::readFromParcel(const Parcel* parcel) {
+ status_t status;
+
+ status = parcel->readUtf8FromUtf16(&mFeatureName);
+ if (status != OK) {
+ return status;
+ }
+ status = parcel->readBool(&mEnabled);
+ if (status != OK) {
+ return status;
+ }
+ // Number of GPU vendor IDs.
+ int numGpuVendorIDs;
+ status = parcel->readInt32(&numGpuVendorIDs);
+ if (status != OK) {
+ return status;
+ }
+ // GPU vendor IDs.
+ for (int i = 0; i < numGpuVendorIDs; i++) {
+ uint32_t gpuVendorIdUint;
+ status = parcel->readUint32(&gpuVendorIdUint);
+ if (status != OK) {
+ return status;
+ }
+ mGpuVendorIDs.emplace_back(gpuVendorIdUint);
+ }
+
+ return OK;
+}
+
+std::string FeatureConfig::toString() const {
+ std::string result;
+ StringAppendF(&result, "Feature: %s\n", mFeatureName.c_str());
+ StringAppendF(&result, " Status: %s\n", mEnabled ? "enabled" : "disabled");
+ for (const auto& vendorID : mGpuVendorIDs) {
+ // vkjson outputs decimal, so print both formats.
+ StringAppendF(&result, " GPU Vendor ID: 0x%04X (%d)\n", vendorID, vendorID);
+ }
+
+ return result;
+}
+
+status_t FeatureOverrides::writeToParcel(Parcel* parcel) const {
+ status_t status;
+ // Number of global feature configs.
+ status = parcel->writeVectorSize(mGlobalFeatures);
+ if (status != OK) {
+ return status;
+ }
+ // Global feature configs.
+ for (const auto& cfg : mGlobalFeatures) {
+ status = cfg.writeToParcel(parcel);
+ if (status != OK) {
+ return status;
+ }
+ }
+ // Number of package feature overrides.
+ status = parcel->writeInt32(static_cast<int32_t>(mPackageFeatures.size()));
+ if (status != OK) {
+ return status;
+ }
+ for (const auto& feature : mPackageFeatures) {
+ // Package name.
+ status = parcel->writeUtf8AsUtf16(feature.first);
+ if (status != OK) {
+ return status;
+ }
+ // Number of package feature configs.
+ status = parcel->writeVectorSize(feature.second);
+ if (status != OK) {
+ return status;
+ }
+ // Package feature configs.
+ for (const auto& cfg : feature.second) {
+ status = cfg.writeToParcel(parcel);
+ if (status != OK) {
+ return status;
+ }
+ }
+ }
+
+ return OK;
+}
+
+status_t FeatureOverrides::readFromParcel(const Parcel* parcel) {
+ status_t status;
+
+ // Number of global feature configs.
+ status = parcel->resizeOutVector(&mGlobalFeatures);
+ if (status != OK) {
+ return status;
+ }
+ // Global feature configs.
+ for (FeatureConfig& cfg : mGlobalFeatures) {
+ status = cfg.readFromParcel(parcel);
+ if (status != OK) {
+ return status;
+ }
+ }
+
+ // Number of package feature overrides.
+ int numPkgOverrides;
+ status = parcel->readInt32(&numPkgOverrides);
+ if (status != OK) {
+ return status;
+ }
+ // Package feature overrides.
+ for (int i = 0; i < numPkgOverrides; i++) {
+ // Package name.
+ std::string name;
+ status = parcel->readUtf8FromUtf16(&name);
+ if (status != OK) {
+ return status;
+ }
+ std::vector<FeatureConfig> cfgs;
+ // Number of package feature configs.
+ int numCfgs;
+ status = parcel->readInt32(&numCfgs);
+ if (status != OK) {
+ return status;
+ }
+ // Package feature configs.
+ for (int j = 0; j < numCfgs; j++) {
+ FeatureConfig cfg;
+ status = cfg.readFromParcel(parcel);
+ if (status != OK) {
+ return status;
+ }
+ cfgs.emplace_back(cfg);
+ }
+ mPackageFeatures[name] = cfgs;
+ }
+
+ return OK;
+}
+
+std::string FeatureOverrides::toString() const {
+ std::string result;
+ result.append("Global Features:\n");
+ for (auto& cfg : mGlobalFeatures) {
+ result.append(" " + cfg.toString());
+ }
+ result.append("\n");
+ result.append("Package Features:\n");
+ for (const auto& packageFeature : mPackageFeatures) {
+ result.append(" Package:");
+ StringAppendF(&result, " %s\n", packageFeature.first.c_str());
+ for (auto& cfg : packageFeature.second) {
+ result.append(" " + cfg.toString());
+ }
+ }
+
+ return result;
+}
+
+} // namespace android
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index d1a5663..626581c 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -29,6 +29,7 @@
#include <android-base/strings.h>
#include <android/dlext.h>
#include <binder/IServiceManager.h>
+#include <com_android_graphics_graphicsenv_flags.h>
#include <graphicsenv/IGpuService.h>
#include <log/log.h>
#include <nativeloader/dlext_namespaces.h>
@@ -70,6 +71,8 @@
}
} // namespace
+namespace graphicsenv_flags = com::android::graphics::graphicsenv::flags;
+
namespace android {
enum NativeLibrary {
@@ -92,7 +95,7 @@
"android.hardware.common-V2-ndk.so:"
"android.hardware.common.fmq-V1-ndk.so:"
"android.hardware.graphics.allocator-V2-ndk.so:"
- "android.hardware.graphics.common-V5-ndk.so:"
+ "android.hardware.graphics.common-V6-ndk.so:"
"android.hardware.graphics.common@1.0.so:"
"android.hardware.graphics.common@1.1.so:"
"android.hardware.graphics.common@1.2.so:"
@@ -596,7 +599,7 @@
// If path is set to nonempty and shouldUseNativeDriver is true, ANGLE will be used regardless.
void GraphicsEnv::setAngleInfo(const std::string& path, const bool shouldUseNativeDriver,
const std::string& packageName,
- const std::vector<std::string> eglFeatures) {
+ const std::vector<std::string>& eglFeatures) {
if (mShouldUseAngle) {
// ANGLE is already set up for this application process, even if the application
// needs to switch from apk to system or vice versa, the application process must
@@ -606,11 +609,11 @@
return;
}
- mAngleEglFeatures = std::move(eglFeatures);
+ mAngleEglFeatures = eglFeatures;
ALOGV("setting ANGLE path to '%s'", path.c_str());
- mAnglePath = std::move(path);
+ mAnglePath = path;
ALOGV("setting app package name to '%s'", packageName.c_str());
- mPackageName = std::move(packageName);
+ mPackageName = packageName;
if (mAnglePath == "system") {
mShouldUseSystemAngle = true;
}
@@ -618,16 +621,62 @@
mShouldUseAngle = true;
}
mShouldUseNativeDriver = shouldUseNativeDriver;
+
+ if (mShouldUseAngle) {
+ updateAngleFeatureOverrides();
+ }
}
std::string& GraphicsEnv::getPackageName() {
return mPackageName;
}
+// List of ANGLE features to enable, specified in the Global.Settings value "angle_egl_features".
const std::vector<std::string>& GraphicsEnv::getAngleEglFeatures() {
return mAngleEglFeatures;
}
+// List of ANGLE features to override (enabled or disable).
+// The list of overrides is loaded and parsed by GpuService.
+void GraphicsEnv::updateAngleFeatureOverrides() {
+ if (!graphicsenv_flags::feature_overrides()) {
+ return;
+ }
+
+ const sp<IGpuService> gpuService = getGpuService();
+ if (!gpuService) {
+ ALOGE("No GPU service");
+ return;
+ }
+
+ mFeatureOverrides = gpuService->getFeatureOverrides();
+}
+
+void GraphicsEnv::getAngleFeatureOverrides(std::vector<const char*>& enabled,
+ std::vector<const char*>& disabled) {
+ if (!graphicsenv_flags::feature_overrides()) {
+ return;
+ }
+
+ for (const FeatureConfig& feature : mFeatureOverrides.mGlobalFeatures) {
+ if (feature.mEnabled) {
+ enabled.push_back(feature.mFeatureName.c_str());
+ } else {
+ disabled.push_back(feature.mFeatureName.c_str());
+ }
+ }
+
+ if (mFeatureOverrides.mPackageFeatures.count(mPackageName)) {
+ for (const FeatureConfig& feature : mFeatureOverrides.mPackageFeatures[mPackageName]) {
+ if (feature.mEnabled) {
+ enabled.push_back(feature.mFeatureName.c_str());
+ } else {
+ disabled.push_back(feature.mFeatureName.c_str());
+ }
+ }
+ }
+}
+
android_namespace_t* GraphicsEnv::getAngleNamespace() {
std::lock_guard<std::mutex> lock(mNamespaceMutex);
diff --git a/libs/graphicsenv/IGpuService.cpp b/libs/graphicsenv/IGpuService.cpp
index 42e7c37..9a34aff 100644
--- a/libs/graphicsenv/IGpuService.cpp
+++ b/libs/graphicsenv/IGpuService.cpp
@@ -119,6 +119,21 @@
}
return driverPath;
}
+
+ FeatureOverrides getFeatureOverrides() override {
+ Parcel data, reply;
+ data.writeInterfaceToken(IGpuService::getInterfaceDescriptor());
+
+ FeatureOverrides featureOverrides;
+ status_t error =
+ remote()->transact(BnGpuService::GET_FEATURE_CONFIG_OVERRIDES, data, &reply);
+ if (error != OK) {
+ return featureOverrides;
+ }
+
+ featureOverrides.readFromParcel(&reply);
+ return featureOverrides;
+ }
};
IMPLEMENT_META_INTERFACE(GpuService, "android.graphicsenv.IGpuService");
@@ -271,6 +286,15 @@
toggleAngleAsSystemDriver(enableAngleAsSystemDriver);
return OK;
}
+ case GET_FEATURE_CONFIG_OVERRIDES: {
+ CHECK_INTERFACE(IGpuService, data, reply);
+
+ // Get the FeatureOverrides from gpuservice, which implements the IGpuService interface
+ // with GpuService::getFeatureOverrides().
+ FeatureOverrides featureOverrides = getFeatureOverrides();
+ featureOverrides.writeToParcel(reply);
+ return OK;
+ }
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/graphicsenv/graphicsenv_flags.aconfig b/libs/graphicsenv/graphicsenv_flags.aconfig
new file mode 100644
index 0000000..ac66362
--- /dev/null
+++ b/libs/graphicsenv/graphicsenv_flags.aconfig
@@ -0,0 +1,9 @@
+package: "com.android.graphics.graphicsenv.flags"
+container: "system"
+
+flag {
+ name: "feature_overrides"
+ namespace: "core_graphics"
+ description: "This flag controls the Feature Overrides in GraphicsEnv."
+ bug: "372694741"
+}
diff --git a/libs/graphicsenv/include/graphicsenv/FeatureOverrides.h b/libs/graphicsenv/include/graphicsenv/FeatureOverrides.h
new file mode 100644
index 0000000..5dc613b
--- /dev/null
+++ b/libs/graphicsenv/include/graphicsenv/FeatureOverrides.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2024 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 <map>
+#include <string>
+#include <vector>
+
+#include <binder/Parcelable.h>
+
+namespace android {
+
+class FeatureConfig : public Parcelable {
+public:
+ FeatureConfig() = default;
+ FeatureConfig(const FeatureConfig&) = default;
+ virtual ~FeatureConfig() = default;
+ virtual status_t writeToParcel(Parcel* parcel) const;
+ virtual status_t readFromParcel(const Parcel* parcel);
+ std::string toString() const;
+
+ std::string mFeatureName;
+ bool mEnabled;
+ std::vector<uint32_t> mGpuVendorIDs;
+};
+
+/*
+ * Class for transporting OpenGL ES Feature configurations from GpuService to authorized
+ * recipients.
+ */
+class FeatureOverrides : public Parcelable {
+public:
+ FeatureOverrides() = default;
+ FeatureOverrides(const FeatureOverrides&) = default;
+ virtual ~FeatureOverrides() = default;
+ virtual status_t writeToParcel(Parcel* parcel) const;
+ virtual status_t readFromParcel(const Parcel* parcel);
+ std::string toString() const;
+
+ std::vector<FeatureConfig> mGlobalFeatures;
+ /* Key: Package Name, Value: Package's Feature Configs */
+ std::map<std::string, std::vector<FeatureConfig>> mPackageFeatures;
+};
+
+} // namespace android
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index b0ab0b9..6821900 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_UI_GRAPHICS_ENV_H
#define ANDROID_UI_GRAPHICS_ENV_H 1
+#include <graphicsenv/FeatureOverrides.h>
#include <graphicsenv/GpuStatsInfo.h>
#include <mutex>
@@ -114,12 +115,15 @@
// If shouldUseNativeDriver is true, it means native GLES drivers must be used for the process.
// If path is set to nonempty and shouldUseNativeDriver is true, ANGLE will be used regardless.
void setAngleInfo(const std::string& path, const bool shouldUseNativeDriver,
- const std::string& packageName, const std::vector<std::string> eglFeatures);
+ const std::string& packageName, const std::vector<std::string>& eglFeatures);
// Get the ANGLE driver namespace.
android_namespace_t* getAngleNamespace();
// Get the app package name.
std::string& getPackageName();
const std::vector<std::string>& getAngleEglFeatures();
+ void updateAngleFeatureOverrides();
+ void getAngleFeatureOverrides(std::vector<const char*>& enabled,
+ std::vector<const char*>& disabled);
// Set the persist.graphics.egl system property value.
void nativeToggleAngleAsSystemDriver(bool enabled);
bool shouldUseSystemAngle();
@@ -177,6 +181,7 @@
std::string mPackageName;
// ANGLE EGL features;
std::vector<std::string> mAngleEglFeatures;
+ FeatureOverrides mFeatureOverrides;
// Whether ANGLE should be used.
bool mShouldUseAngle = false;
// Whether loader should load system ANGLE.
diff --git a/libs/graphicsenv/include/graphicsenv/IGpuService.h b/libs/graphicsenv/include/graphicsenv/IGpuService.h
index a0d6e37..442683a 100644
--- a/libs/graphicsenv/include/graphicsenv/IGpuService.h
+++ b/libs/graphicsenv/include/graphicsenv/IGpuService.h
@@ -18,6 +18,7 @@
#include <binder/IInterface.h>
#include <cutils/compiler.h>
+#include <graphicsenv/FeatureOverrides.h>
#include <graphicsenv/GpuStatsInfo.h>
#include <vector>
@@ -55,6 +56,9 @@
// sets ANGLE as system GLES driver if enabled==true by setting persist.graphics.egl to true.
virtual void toggleAngleAsSystemDriver(bool enabled) = 0;
+
+ // Get the list of features to override.
+ virtual FeatureOverrides getFeatureOverrides() = 0;
};
class BnGpuService : public BnInterface<IGpuService> {
@@ -67,6 +71,7 @@
TOGGLE_ANGLE_AS_SYSTEM_DRIVER,
SET_TARGET_STATS_ARRAY,
ADD_VULKAN_ENGINE_NAME,
+ GET_FEATURE_CONFIG_OVERRIDES,
// Always append new enum to the end.
};
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 1243b21..5ab31db 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -264,9 +264,8 @@
"DisplayEventDispatcher.cpp",
"DisplayEventReceiver.cpp",
"FenceMonitor.cpp",
+ "Flags.cpp",
"GLConsumer.cpp",
- "IConsumerListener.cpp",
- "IGraphicBufferConsumer.cpp",
"IGraphicBufferProducer.cpp",
"IProducerListener.cpp",
"ISurfaceComposer.cpp",
@@ -274,6 +273,7 @@
"LayerMetadata.cpp",
"LayerStatePermissions.cpp",
"LayerState.cpp",
+ "DisplayLuts.cpp",
"OccupancyTracker.cpp",
"StreamSplitter.cpp",
"ScreenCaptureResults.cpp",
@@ -341,6 +341,10 @@
"libgui_aidl_headers",
],
+ static_libs: [
+ "libsurfaceflingerflags",
+ ],
+
afdo: true,
lto: {
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 25e6a52..fa97142 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -50,9 +50,27 @@
using namespace std::chrono_literals;
namespace {
+
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+template <class Mutex>
+class UnlockGuard {
+public:
+ explicit UnlockGuard(Mutex& lock) : mLock{lock} { mLock.unlock(); }
+
+ ~UnlockGuard() { mLock.lock(); }
+
+ UnlockGuard(const UnlockGuard&) = delete;
+ UnlockGuard& operator=(const UnlockGuard&) = delete;
+
+private:
+ Mutex& mLock;
+};
+#endif
+
inline const char* boolToString(bool b) {
return b ? "true" : "false";
}
+
} // namespace
namespace android {
@@ -77,12 +95,6 @@
std::unique_lock _lock{mutex}; \
base::ScopedLockAssertion assumeLocked(mutex);
-#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
-static ReleaseBufferCallback EMPTY_RELEASE_CALLBACK =
- [](const ReleaseCallbackId&, const sp<Fence>& /*releaseFence*/,
- std::optional<uint32_t> /*currentMaxAcquiredBufferCount*/) {};
-#endif
-
void BLASTBufferItemConsumer::onDisconnect() {
Mutex::Autolock lock(mMutex);
mPreviouslyConnected = mCurrentlyConnected;
@@ -185,15 +197,15 @@
mUpdateDestinationFrame(updateDestinationFrame) {
createBufferQueue(&mProducer, &mConsumer);
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
- mBufferItemConsumer = new BLASTBufferItemConsumer(mProducer, mConsumer,
- GraphicBuffer::USAGE_HW_COMPOSER |
- GraphicBuffer::USAGE_HW_TEXTURE,
- 1, false, this);
+ mBufferItemConsumer = sp<BLASTBufferItemConsumer>::make(mProducer, mConsumer,
+ GraphicBuffer::USAGE_HW_COMPOSER |
+ GraphicBuffer::USAGE_HW_TEXTURE,
+ 1, false, this);
#else
- mBufferItemConsumer = new BLASTBufferItemConsumer(mConsumer,
- GraphicBuffer::USAGE_HW_COMPOSER |
- GraphicBuffer::USAGE_HW_TEXTURE,
- 1, false, this);
+ mBufferItemConsumer = sp<BLASTBufferItemConsumer>::make(mConsumer,
+ GraphicBuffer::USAGE_HW_COMPOSER |
+ GraphicBuffer::USAGE_HW_TEXTURE,
+ 1, false, this);
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
// since the adapter is in the client process, set dequeue timeout
// explicitly so that dequeueBuffer will block
@@ -210,8 +222,6 @@
ComposerServiceAIDL::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers);
mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBuffers);
mCurrentMaxAcquiredBufferCount = mMaxAcquiredBuffers;
- mNumAcquired = 0;
- mNumFrameAvailable = 0;
TransactionCompletedListener::getInstance()->addQueueStallListener(
[&](const std::string& reason) {
@@ -225,20 +235,13 @@
this);
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
- std::unique_ptr<gui::BufferReleaseChannel::ConsumerEndpoint> bufferReleaseConsumer;
- gui::BufferReleaseChannel::open(mName, bufferReleaseConsumer, mBufferReleaseProducer);
- mBufferReleaseReader = std::make_shared<BufferReleaseReader>(std::move(bufferReleaseConsumer));
+ gui::BufferReleaseChannel::open(mName, mBufferReleaseConsumer, mBufferReleaseProducer);
+ mBufferReleaseReader.emplace(*this);
#endif
BQA_LOGV("BLASTBufferQueue created");
}
-BLASTBufferQueue::BLASTBufferQueue(const std::string& name, const sp<SurfaceControl>& surface,
- int width, int height, int32_t format)
- : BLASTBufferQueue(name) {
- update(surface, width, height, format);
-}
-
BLASTBufferQueue::~BLASTBufferQueue() {
TransactionCompletedListener::getInstance()->removeQueueStallListener(this);
if (mPendingTransactions.empty()) {
@@ -259,9 +262,6 @@
void BLASTBufferQueue::onFirstRef() {
// safe default, most producers are expected to override this
mProducer->setMaxDequeuedBufferCount(2);
-#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
- mBufferReleaseThread.start(sp<BLASTBufferQueue>::fromExisting(this));
-#endif
}
void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height,
@@ -278,18 +278,23 @@
if (surfaceControlChanged && mSurfaceControl != nullptr) {
BQA_LOGD("Updating SurfaceControl without recreating BBQ");
}
- bool applyTransaction = false;
// Always update the native object even though they might have the same layer handle, so we can
// get the updated transform hint from WM.
mSurfaceControl = surface;
SurfaceComposerClient::Transaction t;
+ bool applyTransaction = false;
if (surfaceControlChanged) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ updateBufferReleaseProducer();
+#endif
t.setFlags(mSurfaceControl, layer_state_t::eEnableBackpressure,
layer_state_t::eEnableBackpressure);
-#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
- t.setBufferReleaseChannel(mSurfaceControl, mBufferReleaseProducer);
-#endif
+ // Migrate the picture profile handle to the new surface control.
+ if (com_android_graphics_libgui_flags_apply_picture_profiles() &&
+ mPictureProfileHandle.has_value()) {
+ t.setPictureProfileHandle(mSurfaceControl, *mPictureProfileHandle);
+ }
applyTransaction = true;
}
mTransformHint = mSurfaceControl->getTransformHint();
@@ -313,7 +318,7 @@
}
if (applyTransaction) {
// All transactions on our apply token are one-way. See comment on mAppliedLastTransaction
- t.setApplyToken(mApplyToken).apply(false, true);
+ t.setApplyToken(mApplyToken).apply(false /* synchronous */, true /* oneWay */);
}
}
@@ -407,23 +412,19 @@
stat.latchTime,
stat.frameEventStats.dequeueReadyTime);
}
-#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
auto currFrameNumber = stat.frameEventStats.frameNumber;
- std::vector<ReleaseCallbackId> staleReleases;
- for (const auto& [key, value]: mSubmitted) {
- if (currFrameNumber > key.framenumber) {
- staleReleases.push_back(key);
+ // Release stale buffers.
+ for (const auto& [key, _] : mSubmitted) {
+ if (currFrameNumber <= key.framenumber) {
+ continue; // not stale.
}
- }
- for (const auto& staleRelease : staleReleases) {
- releaseBufferCallbackLocked(staleRelease,
+ releaseBufferCallbackLocked(key,
stat.previousReleaseFence
? stat.previousReleaseFence
: Fence::NO_FENCE,
stat.currentMaxAcquiredBufferCount,
true /* fakeRelease */);
}
-#endif
} else {
BQA_LOGE("Failed to find matching SurfaceControl in transactionCallback");
}
@@ -436,7 +437,7 @@
void BLASTBufferQueue::flushShadowQueue() {
BQA_LOGV("flushShadowQueue");
- int numFramesToFlush = mNumFrameAvailable;
+ int32_t numFramesToFlush = mNumFrameAvailable;
while (numFramesToFlush > 0) {
acquireNextBufferLocked(std::nullopt);
numFramesToFlush--;
@@ -457,6 +458,9 @@
return;
}
bbq->releaseBufferCallback(id, releaseFence, currentMaxAcquiredBufferCount);
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ bbq->drainBufferReleaseConsumer();
+#endif
};
}
@@ -523,8 +527,6 @@
const sp<Fence>& releaseFence) {
auto it = mSubmitted.find(callbackId);
if (it == mSubmitted.end()) {
- BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %s",
- callbackId.to_string().c_str());
return;
}
mNumAcquired--;
@@ -612,7 +614,7 @@
mNumAcquired++;
mLastAcquiredFrameNumber = bufferItem.mFrameNumber;
ReleaseCallbackId releaseCallbackId(buffer->getId(), mLastAcquiredFrameNumber);
- mSubmitted[releaseCallbackId] = bufferItem;
+ mSubmitted.emplace_or_replace(releaseCallbackId, bufferItem);
bool needsDisconnect = false;
mBufferItemConsumer->getConnectionEvents(bufferItem.mFrameNumber, &needsDisconnect);
@@ -634,13 +636,9 @@
bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform,
bufferItem.mScalingMode, crop);
-#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
- ReleaseBufferCallback releaseBufferCallback =
- applyTransaction ? EMPTY_RELEASE_CALLBACK : makeReleaseBufferCallbackThunk();
-#else
auto releaseBufferCallback = makeReleaseBufferCallbackThunk();
-#endif
- sp<Fence> fence = bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE;
+ sp<Fence> fence =
+ bufferItem.mFence ? sp<Fence>::make(bufferItem.mFence->dup()) : Fence::NO_FENCE;
nsecs_t dequeueTime = -1;
{
@@ -677,6 +675,17 @@
if (!bufferItem.mIsAutoTimestamp) {
t->setDesiredPresentTime(bufferItem.mTimestamp);
}
+ if (com_android_graphics_libgui_flags_apply_picture_profiles() &&
+ bufferItem.mPictureProfileHandle.has_value()) {
+ t->setPictureProfileHandle(mSurfaceControl, *bufferItem.mPictureProfileHandle);
+ // The current picture profile must be maintained in case the BBQ gets its
+ // SurfaceControl switched out.
+ mPictureProfileHandle = bufferItem.mPictureProfileHandle;
+ // Clear out the picture profile if the requestor has asked for it to be cleared
+ if (mPictureProfileHandle == PictureProfileHandle::NONE) {
+ mPictureProfileHandle = std::nullopt;
+ }
+ }
// Drop stale frame timeline infos
while (!mPendingFrameTimelines.empty() &&
@@ -839,7 +848,7 @@
void BLASTBufferQueue::onFrameDequeued(const uint64_t bufferId) {
std::lock_guard _lock{mTimestampMutex};
- mDequeueTimestamps[bufferId] = systemTime();
+ mDequeueTimestamps.emplace_or_replace(bufferId, systemTime());
};
void BLASTBufferQueue::onFrameCancelled(const uint64_t bufferId) {
@@ -1006,7 +1015,7 @@
if (includeSurfaceControlHandle && mSurfaceControl) {
scHandle = mSurfaceControl->getHandle();
}
- return new BBQSurface(mProducer, true, scHandle, this);
+ return sp<BBQSurface>::make(mProducer, true, scHandle, this);
}
void BLASTBufferQueue::mergeWithNextTransaction(SurfaceComposerClient::Transaction* t,
@@ -1014,7 +1023,7 @@
std::lock_guard _lock{mMutex};
if (mLastAcquiredFrameNumber >= frameNumber) {
// Apply the transaction since we have already acquired the desired frame.
- t->apply();
+ t->setApplyToken(mApplyToken).apply();
} else {
mPendingTransactions.emplace_back(frameNumber, *t);
// Clear the transaction so it can't be applied elsewhere.
@@ -1112,10 +1121,10 @@
class AsyncProducerListener : public BnProducerListener {
private:
const sp<IProducerListener> mListener;
+ AsyncProducerListener(const sp<IProducerListener>& listener) : mListener(listener) {}
+ friend class sp<AsyncProducerListener>;
public:
- AsyncProducerListener(const sp<IProducerListener>& listener) : mListener(listener) {}
-
void onBufferReleased() override {
AsyncWorker::getInstance().post([listener = mListener]() { listener->onBufferReleased(); });
}
@@ -1137,6 +1146,24 @@
#endif
};
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+class BBQBufferQueueCore : public BufferQueueCore {
+public:
+ explicit BBQBufferQueueCore(const wp<BLASTBufferQueue>& bbq) : mBLASTBufferQueue{bbq} {}
+
+ void notifyBufferReleased() const override {
+ sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
+ if (!bbq) {
+ return;
+ }
+ bbq->mBufferReleaseReader->interruptBlockingRead();
+ }
+
+private:
+ wp<BLASTBufferQueue> mBLASTBufferQueue;
+};
+#endif
+
// Extends the BufferQueueProducer to create a wrapper around the listener so the listener calls
// can be non-blocking when the producer is in the client process.
class BBQBufferQueueProducer : public BufferQueueProducer {
@@ -1151,7 +1178,7 @@
return BufferQueueProducer::connect(listener, api, producerControlledByApp, output);
}
- return BufferQueueProducer::connect(new AsyncProducerListener(listener), api,
+ return BufferQueueProducer::connect(sp<AsyncProducerListener>::make(listener), api,
producerControlledByApp, output);
}
@@ -1188,6 +1215,48 @@
return BufferQueueProducer::query(what, value);
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ status_t waitForBufferRelease(std::unique_lock<std::mutex>& bufferQueueLock,
+ nsecs_t timeout) const override {
+ const auto startTime = std::chrono::steady_clock::now();
+ sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
+ if (!bbq) {
+ return OK;
+ }
+
+ // BufferQueue has already checked if we have a free buffer. If there's an unread interrupt,
+ // we want to ignore it. This must be done before unlocking the BufferQueue lock to ensure
+ // we don't miss an interrupt.
+ bbq->mBufferReleaseReader->clearInterrupts();
+ UnlockGuard unlockGuard{bufferQueueLock};
+
+ ATRACE_FORMAT("waiting for free buffer");
+ ReleaseCallbackId id;
+ sp<Fence> fence;
+ uint32_t maxAcquiredBufferCount;
+ status_t status =
+ bbq->mBufferReleaseReader->readBlocking(id, fence, maxAcquiredBufferCount, timeout);
+ if (status == TIMED_OUT) {
+ return TIMED_OUT;
+ } else if (status != OK) {
+ // Waiting was interrupted or an error occurred. BufferQueueProducer will check if we
+ // have a free buffer and call this method again if not.
+ return OK;
+ }
+
+ bbq->releaseBufferCallback(id, fence, maxAcquiredBufferCount);
+ const nsecs_t durationNanos = std::chrono::duration_cast<std::chrono::nanoseconds>(
+ std::chrono::steady_clock::now() - startTime)
+ .count();
+ // Provide a callback for Choreographer to start buffer stuffing recovery when blocked
+ // on buffer release.
+ std::function<void(const nsecs_t)> callbackCopy = bbq->getWaitForBufferReleaseCallback();
+ if (callbackCopy) callbackCopy(durationNanos);
+
+ return OK;
+ }
+#endif
+
private:
const wp<BLASTBufferQueue> mBLASTBufferQueue;
};
@@ -1201,14 +1270,18 @@
LOG_ALWAYS_FATAL_IF(outProducer == nullptr, "BLASTBufferQueue: outProducer must not be NULL");
LOG_ALWAYS_FATAL_IF(outConsumer == nullptr, "BLASTBufferQueue: outConsumer must not be NULL");
- sp<BufferQueueCore> core(new BufferQueueCore());
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ auto core = sp<BBQBufferQueueCore>::make(this);
+#else
+ auto core = sp<BufferQueueCore>::make();
+#endif
LOG_ALWAYS_FATAL_IF(core == nullptr, "BLASTBufferQueue: failed to create BufferQueueCore");
- sp<IGraphicBufferProducer> producer(new BBQBufferQueueProducer(core, this));
+ auto producer = sp<BBQBufferQueueProducer>::make(core, this);
LOG_ALWAYS_FATAL_IF(producer == nullptr,
"BLASTBufferQueue: failed to create BBQBufferQueueProducer");
- sp<BufferQueueConsumer> consumer(new BufferQueueConsumer(core));
+ auto consumer = sp<BufferQueueConsumer>::make(core);
consumer->setAllowExtraAcquire(true);
LOG_ALWAYS_FATAL_IF(consumer == nullptr,
"BLASTBufferQueue: failed to create BufferQueueConsumer");
@@ -1271,12 +1344,50 @@
mApplyToken = std::move(applyToken);
}
+void BLASTBufferQueue::setWaitForBufferReleaseCallback(
+ std::function<void(const nsecs_t)> callback) {
+ std::lock_guard _lock{mWaitForBufferReleaseMutex};
+ mWaitForBufferReleaseCallback = std::move(callback);
+}
+
+std::function<void(const nsecs_t)> BLASTBufferQueue::getWaitForBufferReleaseCallback() const {
+ std::lock_guard _lock{mWaitForBufferReleaseMutex};
+ return mWaitForBufferReleaseCallback;
+}
+
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
-BLASTBufferQueue::BufferReleaseReader::BufferReleaseReader(
- std::unique_ptr<gui::BufferReleaseChannel::ConsumerEndpoint> endpoint)
- : mEndpoint{std::move(endpoint)} {
- mEpollFd = android::base::unique_fd{epoll_create1(0)};
+void BLASTBufferQueue::updateBufferReleaseProducer() {
+ // SELinux policy may prevent this process from sending the BufferReleaseChannel's file
+ // descriptor to SurfaceFlinger, causing the entire transaction to be dropped. We send this
+ // transaction independently of any other updates to ensure those updates aren't lost.
+ SurfaceComposerClient::Transaction t;
+ status_t status = t.setApplyToken(mApplyToken)
+ .setBufferReleaseChannel(mSurfaceControl, mBufferReleaseProducer)
+ .apply(false /* synchronous */, true /* oneWay */);
+ if (status != OK) {
+ ALOGW("[%s] %s - failed to set buffer release channel on %s", mName.c_str(),
+ statusToString(status).c_str(), mSurfaceControl->getName().c_str());
+ }
+}
+
+void BLASTBufferQueue::drainBufferReleaseConsumer() {
+ ATRACE_CALL();
+ while (true) {
+ ReleaseCallbackId id;
+ sp<Fence> fence;
+ uint32_t maxAcquiredBufferCount;
+ status_t status =
+ mBufferReleaseConsumer->readReleaseFence(id, fence, maxAcquiredBufferCount);
+ if (status != OK) {
+ return;
+ }
+ releaseBufferCallback(id, fence, maxAcquiredBufferCount);
+ }
+}
+
+BLASTBufferQueue::BufferReleaseReader::BufferReleaseReader(BLASTBufferQueue& bbq) : mBbq{bbq} {
+ mEpollFd = android::base::unique_fd{epoll_create1(EPOLL_CLOEXEC)};
LOG_ALWAYS_FATAL_IF(!mEpollFd.ok(),
"Failed to create buffer release epoll file descriptor. errno=%d "
"message='%s'",
@@ -1284,9 +1395,9 @@
epoll_event registerEndpointFd{};
registerEndpointFd.events = EPOLLIN;
- registerEndpointFd.data.fd = mEndpoint->getFd();
- status_t status =
- epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, mEndpoint->getFd(), ®isterEndpointFd);
+ registerEndpointFd.data.fd = mBbq.mBufferReleaseConsumer->getFd();
+ status_t status = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, mBbq.mBufferReleaseConsumer->getFd(),
+ ®isterEndpointFd);
LOG_ALWAYS_FATAL_IF(status == -1,
"Failed to register buffer release consumer file descriptor with epoll. "
"errno=%d message='%s'",
@@ -1308,78 +1419,64 @@
errno, strerror(errno));
}
-BLASTBufferQueue::BufferReleaseReader& BLASTBufferQueue::BufferReleaseReader::operator=(
- BufferReleaseReader&& other) {
- if (this != &other) {
- ftl::FakeGuard guard{mMutex};
- ftl::FakeGuard otherGuard{other.mMutex};
- mEndpoint = std::move(other.mEndpoint);
- mEpollFd = std::move(other.mEpollFd);
- mEventFd = std::move(other.mEventFd);
- }
- return *this;
-}
-
status_t BLASTBufferQueue::BufferReleaseReader::readBlocking(ReleaseCallbackId& outId,
sp<Fence>& outFence,
- uint32_t& outMaxAcquiredBufferCount) {
+ uint32_t& outMaxAcquiredBufferCount,
+ nsecs_t timeout) {
+ // TODO(b/363290953) epoll_wait only has millisecond timeout precision. If timeout is less than
+ // 1ms, then we round timeout up to 1ms. Otherwise, we round timeout to the nearest
+ // millisecond. Once epoll_pwait2 can be used in libgui, we can specify timeout with nanosecond
+ // precision.
+ int timeoutMs = -1;
+ if (timeout == 0) {
+ timeoutMs = 0;
+ } else if (timeout > 0) {
+ const int nsPerMs = 1000000;
+ if (timeout < nsPerMs) {
+ timeoutMs = 1;
+ } else {
+ timeoutMs = static_cast<int>(
+ std::chrono::round<std::chrono::milliseconds>(std::chrono::nanoseconds{timeout})
+ .count());
+ }
+ }
+
epoll_event event{};
- while (true) {
- int eventCount = epoll_wait(mEpollFd.get(), &event, 1 /* maxevents */, -1 /* timeout */);
- if (eventCount == 1) {
- break;
- }
- if (eventCount == -1 && errno != EINTR) {
- ALOGE("epoll_wait error while waiting for buffer release. errno=%d message='%s'", errno,
- strerror(errno));
- }
+ int eventCount;
+ do {
+ eventCount = epoll_wait(mEpollFd.get(), &event, 1 /*maxevents*/, timeoutMs);
+ } while (eventCount == -1 && errno != EINTR);
+
+ if (eventCount == -1) {
+ ALOGE("epoll_wait error while waiting for buffer release. errno=%d message='%s'", errno,
+ strerror(errno));
+ return UNKNOWN_ERROR;
+ }
+
+ if (eventCount == 0) {
+ return TIMED_OUT;
}
if (event.data.fd == mEventFd.get()) {
- uint64_t value;
- if (read(mEventFd.get(), &value, sizeof(uint64_t)) == -1 && errno != EWOULDBLOCK) {
- ALOGE("error while reading from eventfd. errno=%d message='%s'", errno,
- strerror(errno));
- }
+ clearInterrupts();
return WOULD_BLOCK;
}
- std::lock_guard lock{mMutex};
- return mEndpoint->readReleaseFence(outId, outFence, outMaxAcquiredBufferCount);
+ return mBbq.mBufferReleaseConsumer->readReleaseFence(outId, outFence,
+ outMaxAcquiredBufferCount);
}
void BLASTBufferQueue::BufferReleaseReader::interruptBlockingRead() {
- uint64_t value = 1;
- if (write(mEventFd.get(), &value, sizeof(uint64_t)) == -1) {
+ if (eventfd_write(mEventFd.get(), 1) == -1) {
ALOGE("failed to notify dequeue event. errno=%d message='%s'", errno, strerror(errno));
}
}
-void BLASTBufferQueue::BufferReleaseThread::start(const sp<BLASTBufferQueue>& bbq) {
- mRunning = std::make_shared<std::atomic_bool>(true);
- mReader = bbq->mBufferReleaseReader;
- std::thread([running = mRunning, reader = mReader, weakBbq = wp<BLASTBufferQueue>(bbq)]() {
- pthread_setname_np(pthread_self(), "BufferReleaseThread");
- while (*running) {
- ReleaseCallbackId id;
- sp<Fence> fence;
- uint32_t maxAcquiredBufferCount;
- if (status_t status = reader->readBlocking(id, fence, maxAcquiredBufferCount);
- status != OK) {
- continue;
- }
- sp<BLASTBufferQueue> bbq = weakBbq.promote();
- if (!bbq) {
- return;
- }
- bbq->releaseBufferCallback(id, fence, maxAcquiredBufferCount);
- }
- }).detach();
-}
-
-BLASTBufferQueue::BufferReleaseThread::~BufferReleaseThread() {
- *mRunning = false;
- mReader->interruptBlockingRead();
+void BLASTBufferQueue::BufferReleaseReader::clearInterrupts() {
+ eventfd_t value;
+ if (eventfd_read(mEventFd.get(), &value) == -1 && errno != EWOULDBLOCK) {
+ ALOGE("error while reading from eventfd. errno=%d message='%s'", errno, strerror(errno));
+ }
}
#endif
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp
index 5beba02..9dcd5dc 100644
--- a/libs/gui/BufferItem.cpp
+++ b/libs/gui/BufferItem.cpp
@@ -38,26 +38,25 @@
return static_cast<T>(static_cast<uint64_t>(hi)<<32 | lo);
}
-BufferItem::BufferItem() :
- mGraphicBuffer(nullptr),
- mFence(nullptr),
- mCrop(Rect::INVALID_RECT),
- mTransform(0),
- mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
- mTimestamp(0),
- mIsAutoTimestamp(false),
- mDataSpace(HAL_DATASPACE_UNKNOWN),
- mFrameNumber(0),
- mSlot(INVALID_BUFFER_SLOT),
- mIsDroppable(false),
- mAcquireCalled(false),
- mTransformToDisplayInverse(false),
- mSurfaceDamage(),
- mAutoRefresh(false),
- mQueuedBuffer(true),
- mIsStale(false),
- mApi(0) {
-}
+BufferItem::BufferItem()
+ : mGraphicBuffer(nullptr),
+ mFence(nullptr),
+ mCrop(Rect::INVALID_RECT),
+ mTransform(0),
+ mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
+ mTimestamp(0),
+ mIsAutoTimestamp(false),
+ mDataSpace(HAL_DATASPACE_UNKNOWN),
+ mFrameNumber(0),
+ mSlot(INVALID_BUFFER_SLOT),
+ mIsDroppable(false),
+ mAcquireCalled(false),
+ mTransformToDisplayInverse(false),
+ mSurfaceDamage(),
+ mAutoRefresh(false),
+ mQueuedBuffer(true),
+ mIsStale(false),
+ mApi(0) {}
BufferItem::~BufferItem() {}
@@ -76,6 +75,11 @@
addAligned(size, high32(mTimestamp));
addAligned(size, mIsAutoTimestamp);
addAligned(size, mDataSpace);
+#if COM_ANDROID_GRAPHICS_LIBUI_FLAGS_APPLY_PICTURE_PROFILES
+ addAligned(size, mPictureProfileHandle.has_value());
+ addAligned(size, low32(PictureProfileHandle::NONE.getId()));
+ addAligned(size, high32(PictureProfileHandle::NONE.getId()));
+#endif // COM_ANDROID_GRAPHICS_LIBUI_FLAGS_APPLY_PICTURE_PROFILES
addAligned(size, low32(mFrameNumber));
addAligned(size, high32(mFrameNumber));
addAligned(size, mSlot);
@@ -170,6 +174,16 @@
writeAligned(buffer, size, high32(mTimestamp));
writeAligned(buffer, size, mIsAutoTimestamp);
writeAligned(buffer, size, mDataSpace);
+#if COM_ANDROID_GRAPHICS_LIBUI_FLAGS_APPLY_PICTURE_PROFILES
+ writeAligned(buffer, size, mPictureProfileHandle.has_value());
+ if (mPictureProfileHandle.has_value()) {
+ writeAligned(buffer, size, low32(mPictureProfileHandle->getId()));
+ writeAligned(buffer, size, high32(mPictureProfileHandle->getId()));
+ } else {
+ writeAligned(buffer, size, low32(PictureProfileHandle::NONE.getId()));
+ writeAligned(buffer, size, high32(PictureProfileHandle::NONE.getId()));
+ }
+#endif // COM_ANDROID_GRAPHICS_LIBUI_FLAGS_APPLY_PICTURE_PROFILES
writeAligned(buffer, size, low32(mFrameNumber));
writeAligned(buffer, size, high32(mFrameNumber));
writeAligned(buffer, size, mSlot);
@@ -201,14 +215,14 @@
FlattenableUtils::read(buffer, size, flags);
if (flags & 1) {
- mGraphicBuffer = new GraphicBuffer();
+ mGraphicBuffer = sp<GraphicBuffer>::make();
status_t err = mGraphicBuffer->unflatten(buffer, size, fds, count);
if (err) return err;
size -= FlattenableUtils::align<4>(buffer);
}
if (flags & 2) {
- mFence = new Fence();
+ mFence = sp<Fence>::make();
status_t err = mFence->unflatten(buffer, size, fds, count);
if (err) return err;
size -= FlattenableUtils::align<4>(buffer);
@@ -231,6 +245,7 @@
uint32_t timestampLo = 0, timestampHi = 0;
uint32_t frameNumberLo = 0, frameNumberHi = 0;
+ int32_t pictureProfileIdLo = 0, pictureProfileIdHi = 0;
readAligned(buffer, size, mCrop);
readAligned(buffer, size, mTransform);
@@ -240,6 +255,16 @@
mTimestamp = to64<int64_t>(timestampLo, timestampHi);
readAligned(buffer, size, mIsAutoTimestamp);
readAligned(buffer, size, mDataSpace);
+#if COM_ANDROID_GRAPHICS_LIBUI_FLAGS_APPLY_PICTURE_PROFILES
+ bool hasPictureProfileHandle;
+ readAligned(buffer, size, hasPictureProfileHandle);
+ readAligned(buffer, size, pictureProfileIdLo);
+ readAligned(buffer, size, pictureProfileIdHi);
+ mPictureProfileHandle = hasPictureProfileHandle
+ ? std::optional(PictureProfileHandle(
+ to64<PictureProfileId>(pictureProfileIdLo, pictureProfileIdHi)))
+ : std::nullopt;
+#endif // COM_ANDROID_GRAPHICS_LIBUI_FLAGS_APPLY_PICTURE_PROFILES
readAligned(buffer, size, frameNumberLo);
readAligned(buffer, size, frameNumberHi);
mFrameNumber = to64<uint64_t>(frameNumberLo, frameNumberHi);
diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp
index bfe3d6e..1585aae 100644
--- a/libs/gui/BufferItemConsumer.cpp
+++ b/libs/gui/BufferItemConsumer.cpp
@@ -24,6 +24,7 @@
#include <com_android_graphics_libgui_flags.h>
#include <gui/BufferItem.h>
#include <gui/BufferItemConsumer.h>
+#include <gui/Surface.h>
#include <ui/BufferQueueDefs.h>
#include <ui/GraphicBuffer.h>
@@ -35,6 +36,30 @@
namespace android {
+std::tuple<sp<BufferItemConsumer>, sp<Surface>> BufferItemConsumer::create(
+ uint64_t consumerUsage, int bufferCount, bool controlledByApp,
+ bool isConsumerSurfaceFlinger) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+ sp<BufferItemConsumer> bufferItemConsumer =
+ sp<BufferItemConsumer>::make(consumerUsage, bufferCount, controlledByApp,
+ isConsumerSurfaceFlinger);
+ return {bufferItemConsumer, bufferItemConsumer->getSurface()};
+#else
+ sp<IGraphicBufferProducer> igbp;
+ sp<IGraphicBufferConsumer> igbc;
+ BufferQueue::createBufferQueue(&igbp, &igbc, isConsumerSurfaceFlinger);
+ sp<BufferItemConsumer> bufferItemConsumer =
+ sp<BufferItemConsumer>::make(igbc, consumerUsage, bufferCount, controlledByApp);
+ return {bufferItemConsumer, sp<Surface>::make(igbp, controlledByApp)};
+#endif
+}
+
+sp<BufferItemConsumer> BufferItemConsumer::create(const sp<IGraphicBufferConsumer>& consumer,
+ uint64_t consumerUsage, int bufferCount,
+ bool controlledByApp) {
+ return sp<BufferItemConsumer>::make(consumer, consumerUsage, bufferCount, controlledByApp);
+}
+
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
BufferItemConsumer::BufferItemConsumer(uint64_t consumerUsage, int bufferCount,
bool controlledByApp, bool isConsumerSurfaceFlinger)
@@ -140,7 +165,7 @@
BI_LOGE("Failed to addReleaseFenceLocked");
}
- err = releaseBufferLocked(slotIndex, buffer, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
+ err = releaseBufferLocked(slotIndex, buffer);
if (err != OK && err != IGraphicBufferConsumer::STALE_BUFFER_SLOT) {
BI_LOGE("Failed to release buffer: %s (%d)",
strerror(-err), err);
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index b0f6e69..f21ac18 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -108,6 +108,15 @@
}
#endif
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+void BufferQueue::ProxyConsumerListener::onSlotCountChanged(int slotCount) {
+ sp<ConsumerListener> listener(mConsumerListener.promote());
+ if (listener != nullptr) {
+ listener->onSlotCountChanged(slotCount);
+ }
+}
+#endif
+
void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
bool consumerIsSurfaceFlinger) {
@@ -116,15 +125,16 @@
LOG_ALWAYS_FATAL_IF(outConsumer == nullptr,
"BufferQueue: outConsumer must not be NULL");
- sp<BufferQueueCore> core(new BufferQueueCore());
+ sp<BufferQueueCore> core = sp<BufferQueueCore>::make();
LOG_ALWAYS_FATAL_IF(core == nullptr,
"BufferQueue: failed to create BufferQueueCore");
- sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger));
+ sp<IGraphicBufferProducer> producer =
+ sp<BufferQueueProducer>::make(core, consumerIsSurfaceFlinger);
LOG_ALWAYS_FATAL_IF(producer == nullptr,
"BufferQueue: failed to create BufferQueueProducer");
- sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
+ sp<IGraphicBufferConsumer> consumer = sp<BufferQueueConsumer>::make(core);
LOG_ALWAYS_FATAL_IF(consumer == nullptr,
"BufferQueue: failed to create BufferQueueConsumer");
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 69d25be..270bfbd 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -28,6 +28,10 @@
#define VALIDATE_CONSISTENCY()
#endif
+#define EGL_EGLEXT_PROTOTYPES
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
#include <gui/BufferItem.h>
#include <gui/BufferQueueConsumer.h>
#include <gui/BufferQueueCore.h>
@@ -297,7 +301,11 @@
// We might have freed a slot while dropping old buffers, or the producer
// may be blocked waiting for the number of buffers in the queue to
// decrease.
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ mCore->notifyBufferReleased();
+#else
mCore->mDequeueCondition.notify_all();
+#endif
ATRACE_INT(mCore->mConsumerName.c_str(), static_cast<int32_t>(mCore->mQueue.size()));
#ifndef NO_BINDER
@@ -333,9 +341,9 @@
return BAD_VALUE;
}
- if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
- BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)",
- slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
+ const int totalSlotCount = mCore->getTotalSlotCountLocked();
+ if (slot < 0 || slot >= totalSlotCount) {
+ BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)", slot, totalSlotCount);
return BAD_VALUE;
} else if (!mSlots[slot].mBufferState.isAcquired()) {
BQ_LOGE("detachBuffer: slot %d is not owned by the consumer "
@@ -350,7 +358,12 @@
mCore->mActiveBuffers.erase(slot);
mCore->mFreeSlots.insert(slot);
mCore->clearBufferSlotLocked(slot);
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ mCore->notifyBufferReleased();
+#else
mCore->mDequeueCondition.notify_all();
+#endif
+
VALIDATE_CONSISTENCY();
}
@@ -464,16 +477,24 @@
return NO_ERROR;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
+ const sp<Fence>& releaseFence) {
+#else
status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
const sp<Fence>& releaseFence, EGLDisplay eglDisplay,
EGLSyncKHR eglFence) {
+#endif
ATRACE_CALL();
ATRACE_BUFFER_INDEX(slot);
- if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS ||
- releaseFence == nullptr) {
- BQ_LOGE("releaseBuffer: slot %d out of range or fence %p NULL", slot,
- releaseFence.get());
+ const int totalSlotCount = mCore->getTotalSlotCountLocked();
+ if (slot < 0 || slot >= totalSlotCount) {
+ BQ_LOGE("releaseBuffer: slot index %d out of range [0, %d)", slot, totalSlotCount);
+ return BAD_VALUE;
+ }
+ if (releaseFence == nullptr) {
+ BQ_LOGE("releaseBuffer: slot %d fence %p NULL", slot, releaseFence.get());
return BAD_VALUE;
}
@@ -481,6 +502,13 @@
{ // Autolock scope
std::lock_guard<std::mutex> lock(mCore->mMutex);
+ const int totalSlotCount = mCore->getTotalSlotCountLocked();
+ if (slot < 0 || slot >= totalSlotCount || releaseFence == nullptr) {
+ BQ_LOGE("releaseBuffer: slot %d out of range [0, %d) or fence %p NULL", slot,
+ totalSlotCount, releaseFence.get());
+ return BAD_VALUE;
+ }
+
// If the frame number has changed because the buffer has been reallocated,
// we can ignore this releaseBuffer for the old buffer.
// Ignore this for the shared buffer where the frame number can easily
@@ -498,8 +526,10 @@
return BAD_VALUE;
}
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
mSlots[slot].mEglDisplay = eglDisplay;
mSlots[slot].mEglFence = eglFence;
+#endif
mSlots[slot].mFence = releaseFence;
mSlots[slot].mBufferState.release();
@@ -520,7 +550,12 @@
}
BQ_LOGV("releaseBuffer: releasing slot %d", slot);
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ mCore->notifyBufferReleased();
+#else
mCore->mDequeueCondition.notify_all();
+#endif
+
VALIDATE_CONSISTENCY();
} // Autolock scope
@@ -574,7 +609,11 @@
mCore->mQueue.clear();
mCore->freeAllBuffersLocked();
mCore->mSharedBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ mCore->notifyBufferReleased();
+#else
mCore->mDequeueCondition.notify_all();
+#endif
return NO_ERROR;
}
@@ -616,6 +655,43 @@
return NO_ERROR;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+status_t BufferQueueConsumer::getReleasedBuffersExtended(std::vector<bool>* outSlotMask) {
+ ATRACE_CALL();
+
+ if (outSlotMask == nullptr) {
+ BQ_LOGE("getReleasedBuffersExtended: outSlotMask may not be NULL");
+ return BAD_VALUE;
+ }
+
+ std::lock_guard<std::mutex> lock(mCore->mMutex);
+
+ if (mCore->mIsAbandoned) {
+ BQ_LOGE("getReleasedBuffersExtended: BufferQueue has been abandoned");
+ return NO_INIT;
+ }
+
+ const int totalSlotCount = mCore->getTotalSlotCountLocked();
+ outSlotMask->resize(totalSlotCount);
+ for (int s = 0; s < totalSlotCount; ++s) {
+ (*outSlotMask)[s] = !mSlots[s].mAcquireCalled;
+ }
+
+ // Remove from the mask queued buffers for which acquire has been called,
+ // since the consumer will not receive their buffer addresses and so must
+ // retain their cached information
+ BufferQueueCore::Fifo::iterator current(mCore->mQueue.begin());
+ while (current != mCore->mQueue.end()) {
+ if (current->mAcquireCalled) {
+ (*outSlotMask)[current->mSlot] = false;
+ }
+ ++current;
+ }
+
+ return NO_ERROR;
+}
+#endif
+
status_t BufferQueueConsumer::setDefaultBufferSize(uint32_t width,
uint32_t height) {
ATRACE_CALL();
@@ -634,6 +710,28 @@
return NO_ERROR;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+status_t BufferQueueConsumer::allowUnlimitedSlots(bool allowUnlimitedSlots) {
+ ATRACE_CALL();
+ BQ_LOGV("allowUnlimitedSlots: %d", allowUnlimitedSlots);
+ std::lock_guard<std::mutex> lock(mCore->mMutex);
+
+ if (mCore->mIsAbandoned) {
+ BQ_LOGE("allowUnlimitedSlots: BufferQueue has been abandoned");
+ return NO_INIT;
+ }
+
+ if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
+ BQ_LOGE("allowUnlimitedSlots: BufferQueue already connected");
+ return INVALID_OPERATION;
+ }
+
+ mCore->mAllowExtendedSlotCount = allowUnlimitedSlots;
+
+ return OK;
+}
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+
status_t BufferQueueConsumer::setMaxBufferCount(int bufferCount) {
ATRACE_CALL();
@@ -673,16 +771,23 @@
int maxAcquiredBuffers) {
ATRACE_FORMAT("%s(%d)", __func__, maxAcquiredBuffers);
- if (maxAcquiredBuffers < 1 ||
- maxAcquiredBuffers > BufferQueueCore::MAX_MAX_ACQUIRED_BUFFERS) {
- BQ_LOGE("setMaxAcquiredBufferCount: invalid count %d",
- maxAcquiredBuffers);
- return BAD_VALUE;
- }
-
sp<IConsumerListener> listener;
{ // Autolock scope
std::unique_lock<std::mutex> lock(mCore->mMutex);
+
+ // We reserve two slots in order to guarantee that the producer and
+ // consumer can run asynchronously.
+ int maxMaxAcquiredBuffers =
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ mCore->getTotalSlotCountLocked() - 2;
+#else
+ BufferQueueCore::MAX_MAX_ACQUIRED_BUFFERS;
+#endif
+ if (maxAcquiredBuffers < 1 || maxAcquiredBuffers > maxMaxAcquiredBuffers) {
+ BQ_LOGE("setMaxAcquiredBufferCount: invalid count %d", maxAcquiredBuffers);
+ return BAD_VALUE;
+ }
+
mCore->waitWhileAllocatingLocked(lock);
if (mCore->mIsAbandoned) {
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index e0c5b1f..6c79904 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -38,6 +38,8 @@
#include <system/window.h>
+#include <ui/BufferQueueDefs.h>
+
namespace android {
// Macros for include BufferQueueCore information in log messages
@@ -97,7 +99,11 @@
mConnectedProducerListener(),
mBufferReleasedCbEnabled(false),
mBufferAttachedCbEnabled(false),
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ mSlots(BufferQueueDefs::NUM_BUFFER_SLOTS),
+#else
mSlots(),
+#endif
mQueue(),
mFreeSlots(),
mFreeBuffers(),
@@ -111,6 +117,9 @@
mDefaultWidth(1),
mDefaultHeight(1),
mDefaultBufferDataSpace(HAL_DATASPACE_UNKNOWN),
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ mAllowExtendedSlotCount(false),
+#endif
mMaxBufferCount(BufferQueueDefs::NUM_BUFFER_SLOTS),
mMaxAcquiredBufferCount(1),
mMaxDequeuedBufferCount(1),
@@ -221,6 +230,14 @@
}
}
+int BufferQueueCore::getTotalSlotCountLocked() const {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ return mAllowExtendedSlotCount ? mMaxBufferCount : BufferQueueDefs::NUM_BUFFER_SLOTS;
+#else
+ return BufferQueueDefs::NUM_BUFFER_SLOTS;
+#endif
+}
+
int BufferQueueCore::getMinUndequeuedBufferCountLocked() const {
// If dequeueBuffer is allowed to error out, we don't have to add an
// extra buffer.
@@ -253,6 +270,26 @@
return maxBufferCount;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+status_t BufferQueueCore::extendSlotCountLocked(int size) {
+ int previousSize = (int)mSlots.size();
+ if (previousSize > size) {
+ return BAD_VALUE;
+ }
+ if (previousSize == size) {
+ return NO_ERROR;
+ }
+
+ mSlots.resize(size);
+ for (int i = previousSize; i < size; i++) {
+ mUnusedSlots.push_back(i);
+ }
+
+ mMaxBufferCount = size;
+ return NO_ERROR;
+}
+#endif
+
void BufferQueueCore::clearBufferSlotLocked(int slot) {
BQ_LOGV("clearBufferSlotLocked: slot %d", slot);
@@ -262,14 +299,16 @@
mSlots[slot].mFrameNumber = 0;
mSlots[slot].mAcquireCalled = false;
mSlots[slot].mNeedsReallocation = true;
+ mSlots[slot].mFence = Fence::NO_FENCE;
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
// Destroy fence as BufferQueue now takes ownership
if (mSlots[slot].mEglFence != EGL_NO_SYNC_KHR) {
eglDestroySyncKHR(mSlots[slot].mEglDisplay, mSlots[slot].mEglFence);
mSlots[slot].mEglFence = EGL_NO_SYNC_KHR;
}
- mSlots[slot].mFence = Fence::NO_FENCE;
mSlots[slot].mEglDisplay = EGL_NO_DISPLAY;
+#endif
if (mLastQueuedSlot == slot) {
mLastQueuedSlot = INVALID_BUFFER_SLOT;
@@ -371,11 +410,17 @@
}
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+void BufferQueueCore::notifyBufferReleased() const {
+ mDequeueCondition.notify_all();
+}
+#endif
+
#if DEBUG_ONLY_CODE
void BufferQueueCore::validateConsistencyLocked() const {
static const useconds_t PAUSE_TIME = 0;
int allocatedSlots = 0;
- for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
+ for (int slot = 0; slot < getTotalSlotCountLocked(); ++slot) {
bool isInFreeSlots = mFreeSlots.count(slot) != 0;
bool isInFreeBuffers =
std::find(mFreeBuffers.cbegin(), mFreeBuffers.cend(), slot) !=
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index da74e9c..5961b41 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -40,6 +40,7 @@
#include <gui/TraceUtils.h>
#include <private/gui/BufferQueueThreadState.h>
+#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/Trace.h>
@@ -108,9 +109,9 @@
return NO_INIT;
}
- if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
- BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
- slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
+ int maxSlot = mCore->getTotalSlotCountLocked();
+ if (slot < 0 || slot >= maxSlot) {
+ BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)", slot, maxSlot);
return BAD_VALUE;
} else if (!mSlots[slot].mBufferState.isDequeued()) {
BQ_LOGE("requestBuffer: slot %d is not owned by the producer "
@@ -123,6 +124,49 @@
return NO_ERROR;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+status_t BufferQueueProducer::extendSlotCount(int size) {
+ ATRACE_CALL();
+
+ sp<IConsumerListener> listener;
+ {
+ std::lock_guard<std::mutex> lock(mCore->mMutex);
+ BQ_LOGV("extendSlotCount: size %d", size);
+
+ if (mCore->mIsAbandoned) {
+ BQ_LOGE("extendSlotCount: BufferQueue has been abandoned");
+ return NO_INIT;
+ }
+
+ if (!mCore->mAllowExtendedSlotCount) {
+ BQ_LOGE("extendSlotCount: Consumer did not allow unlimited slots");
+ return INVALID_OPERATION;
+ }
+
+ int maxBeforeExtension = mCore->mMaxBufferCount;
+
+ if (size == maxBeforeExtension) {
+ return NO_ERROR;
+ }
+
+ if (size < maxBeforeExtension) {
+ return BAD_VALUE;
+ }
+
+ if (status_t ret = mCore->extendSlotCountLocked(size); ret != OK) {
+ return ret;
+ }
+ listener = mCore->mConsumerListener;
+ }
+
+ if (listener) {
+ listener->onSlotCountChanged(size);
+ }
+
+ return NO_ERROR;
+}
+#endif
+
status_t BufferQueueProducer::setMaxDequeuedBufferCount(
int maxDequeuedBuffers) {
int maxBufferCount;
@@ -170,9 +214,10 @@
int bufferCount = mCore->getMinUndequeuedBufferCountLocked();
bufferCount += maxDequeuedBuffers;
- if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
+ if (bufferCount > mCore->getTotalSlotCountLocked()) {
BQ_LOGE("setMaxDequeuedBufferCount: bufferCount %d too large "
- "(max %d)", bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
+ "(max %d)",
+ bufferCount, mCore->getTotalSlotCountLocked());
return BAD_VALUE;
}
@@ -202,7 +247,11 @@
if (delta < 0) {
listener = mCore->mConsumerListener;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ mCore->notifyBufferReleased();
+#else
mCore->mDequeueCondition.notify_all();
+#endif
} // Autolock scope
// Call back without lock held
@@ -254,7 +303,12 @@
}
mCore->mAsyncMode = async;
VALIDATE_CONSISTENCY();
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ mCore->notifyBufferReleased();
+#else
mCore->mDequeueCondition.notify_all();
+#endif
+
if (delta < 0) {
listener = mCore->mConsumerListener;
}
@@ -376,6 +430,12 @@
(acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
return WOULD_BLOCK;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ if (status_t status = waitForBufferRelease(lock, mDequeueTimeout);
+ status == TIMED_OUT) {
+ return TIMED_OUT;
+ }
+#else
if (mDequeueTimeout >= 0) {
std::cv_status result = mCore->mDequeueCondition.wait_for(lock,
std::chrono::nanoseconds(mDequeueTimeout));
@@ -385,12 +445,29 @@
} else {
mCore->mDequeueCondition.wait(lock);
}
+#endif
}
} // while (tryAgain)
return NO_ERROR;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+status_t BufferQueueProducer::waitForBufferRelease(std::unique_lock<std::mutex>& lock,
+ nsecs_t timeout) const {
+ if (mDequeueTimeout >= 0) {
+ std::cv_status result =
+ mCore->mDequeueCondition.wait_for(lock, std::chrono::nanoseconds(timeout));
+ if (result == std::cv_status::timeout) {
+ return TIMED_OUT;
+ }
+ } else {
+ mCore->mDequeueCondition.wait(lock);
+ }
+ return OK;
+}
+#endif
+
status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* outFence,
uint32_t width, uint32_t height, PixelFormat format,
uint64_t usage, uint64_t* outBufferAge,
@@ -419,8 +496,10 @@
}
status_t returnFlags = NO_ERROR;
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
EGLDisplay eglDisplay = EGL_NO_DISPLAY;
EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
+#endif
bool attachedByConsumer = false;
sp<IConsumerListener> listener;
@@ -537,8 +616,10 @@
mSlots[found].mAcquireCalled = false;
mSlots[found].mGraphicBuffer = nullptr;
mSlots[found].mRequestBufferCalled = false;
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
+#endif
mSlots[found].mFence = Fence::NO_FENCE;
mCore->mBufferAge = 0;
mCore->mIsAllocating = true;
@@ -563,14 +644,18 @@
found, buffer->width, buffer->height, buffer->format);
}
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
eglDisplay = mSlots[found].mEglDisplay;
eglFence = mSlots[found].mEglFence;
+#endif
// Don't return a fence in shared buffer mode, except for the first
// frame.
*outFence = (mCore->mSharedBufferMode &&
mCore->mSharedBufferSlot == found) ?
Fence::NO_FENCE : mSlots[found].mFence;
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
+#endif
mSlots[found].mFence = Fence::NO_FENCE;
// If shared buffer mode has just been enabled, cache the slot of the
@@ -608,11 +693,11 @@
.requestorName = {mConsumerName.c_str(), mConsumerName.size()},
.extras = std::move(tempOptions),
};
- sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(allocRequest);
+ sp<GraphicBuffer> graphicBuffer = sp<GraphicBuffer>::make(allocRequest);
#else
sp<GraphicBuffer> graphicBuffer =
- new GraphicBuffer(width, height, format, BQ_LAYER_COUNT, usage,
- {mConsumerName.c_str(), mConsumerName.size()});
+ sp<GraphicBuffer>::make(width, height, format, BQ_LAYER_COUNT, usage,
+ std::string{mConsumerName.c_str(), mConsumerName.size()});
#endif
status_t error = graphicBuffer->initCheck();
@@ -659,6 +744,7 @@
returnFlags |= BUFFER_NEEDS_REALLOCATION;
}
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
if (eglFence != EGL_NO_SYNC_KHR) {
EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0,
1000000000);
@@ -673,6 +759,7 @@
}
eglDestroySyncKHR(eglDisplay, eglFence);
}
+#endif
BQ_LOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x",
*outSlot,
@@ -714,9 +801,9 @@
return BAD_VALUE;
}
- if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
- BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)",
- slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
+ const int totalSlotCount = mCore->getTotalSlotCountLocked();
+ if (slot < 0 || slot >= totalSlotCount) {
+ BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)", slot, totalSlotCount);
return BAD_VALUE;
} else if (!mSlots[slot].mBufferState.isDequeued()) {
// TODO(http://b/140581935): This message is BQ_LOGW because it
@@ -741,7 +828,11 @@
mCore->mActiveBuffers.erase(slot);
mCore->mFreeSlots.insert(slot);
mCore->clearBufferSlotLocked(slot);
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ mCore->notifyBufferReleased();
+#else
mCore->mDequeueCondition.notify_all();
+#endif
VALIDATE_CONSISTENCY();
}
@@ -872,7 +963,9 @@
mSlots[*outSlot].mGraphicBuffer = buffer;
mSlots[*outSlot].mBufferState.attachProducer();
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR;
+#endif
mSlots[*outSlot].mFence = Fence::NO_FENCE;
mSlots[*outSlot].mRequestBufferCalled = true;
mSlots[*outSlot].mAcquireCalled = false;
@@ -902,6 +995,8 @@
&getFrameTimestamps);
const Region& surfaceDamage = input.getSurfaceDamage();
const HdrMetadata& hdrMetadata = input.getHdrMetadata();
+ const std::optional<PictureProfileHandle>& pictureProfileHandle =
+ input.getPictureProfileHandle();
if (acquireFence == nullptr) {
BQ_LOGE("queueBuffer: fence is NULL");
@@ -943,9 +1038,9 @@
return NO_INIT;
}
- if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
- BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
- slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
+ const int totalSlotCount = mCore->getTotalSlotCountLocked();
+ if (slot < 0 || slot >= totalSlotCount) {
+ BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)", slot, totalSlotCount);
return BAD_VALUE;
} else if (!mSlots[slot].mBufferState.isDequeued()) {
BQ_LOGE("queueBuffer: slot %d is not owned by the producer "
@@ -1008,6 +1103,7 @@
item.mIsAutoTimestamp = isAutoTimestamp;
item.mDataSpace = dataSpace;
item.mHdrMetadata = hdrMetadata;
+ item.mPictureProfileHandle = pictureProfileHandle;
item.mFrameNumber = currentFrameNumber;
item.mSlot = slot;
item.mFence = acquireFence;
@@ -1082,7 +1178,11 @@
}
mCore->mBufferHasBeenQueued = true;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ mCore->notifyBufferReleased();
+#else
mCore->mDequeueCondition.notify_all();
+#endif
mCore->mLastQueuedSlot = slot;
output->width = mCore->mDefaultWidth;
@@ -1184,9 +1284,9 @@
return BAD_VALUE;
}
- if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
- BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)", slot,
- BufferQueueDefs::NUM_BUFFER_SLOTS);
+ const int totalSlotCount = mCore->getTotalSlotCountLocked();
+ if (slot < 0 || slot >= totalSlotCount) {
+ BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)", slot, totalSlotCount);
return BAD_VALUE;
} else if (!mSlots[slot].mBufferState.isDequeued()) {
BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
@@ -1218,7 +1318,11 @@
bufferId = gb->getId();
}
mSlots[slot].mFence = fence;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ mCore->notifyBufferReleased();
+#else
mCore->mDequeueCondition.notify_all();
+#endif
listener = mCore->mConsumerListener;
VALIDATE_CONSISTENCY();
}
@@ -1350,6 +1454,9 @@
output->nextFrameNumber = mCore->mFrameCounter + 1;
output->bufferReplaced = false;
output->maxBufferCount = mCore->mMaxBufferCount;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ output->isSlotExpansionAllowed = mCore->mAllowExtendedSlotCount;
+#endif
if (listener != nullptr) {
// Set up a death notification so that we can disconnect
@@ -1357,7 +1464,7 @@
#ifndef NO_BINDER
if (IInterface::asBinder(listener)->remoteBinder() != nullptr) {
status = IInterface::asBinder(listener)->linkToDeath(
- static_cast<IBinder::DeathRecipient*>(this));
+ sp<IBinder::DeathRecipient>::fromExisting(this));
if (status != NO_ERROR) {
BQ_LOGE("connect: linkToDeath failed: %s (%d)",
strerror(-status), status);
@@ -1446,8 +1553,7 @@
IInterface::asBinder(mCore->mLinkedToDeath);
// This can fail if we're here because of the death
// notification, but we just ignore it
- token->unlinkToDeath(
- static_cast<IBinder::DeathRecipient*>(this));
+ token->unlinkToDeath(static_cast<IBinder::DeathRecipient*>(this));
}
#endif
mCore->mSharedBufferSlot =
@@ -1457,7 +1563,11 @@
mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
mCore->mConnectedPid = -1;
mCore->mSidebandStream.clear();
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ mCore->notifyBufferReleased();
+#else
mCore->mDequeueCondition.notify_all();
+#endif
mCore->mAutoPrerotation = false;
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
mCore->mAdditionalOptions.clear();
@@ -1508,7 +1618,6 @@
const bool useDefaultSize = !width && !height;
while (true) {
- size_t newBufferCount = 0;
uint32_t allocWidth = 0;
uint32_t allocHeight = 0;
PixelFormat allocFormat = PIXEL_FORMAT_UNKNOWN;
@@ -1530,8 +1639,9 @@
// Only allocate one buffer at a time to reduce risks of overlapping an allocation from
// both allocateBuffers and dequeueBuffer.
- newBufferCount = mCore->mFreeSlots.empty() ? 0 : 1;
- if (newBufferCount == 0) {
+ if (mCore->mFreeSlots.empty()) {
+ BQ_LOGV("allocateBuffers: a slot was occupied while "
+ "allocating. Dropping allocated buffer.");
return;
}
@@ -1573,27 +1683,23 @@
};
#endif
- Vector<sp<GraphicBuffer>> buffers;
- for (size_t i = 0; i < newBufferCount; ++i) {
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
- sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(allocRequest);
+ sp<GraphicBuffer> graphicBuffer = sp<GraphicBuffer>::make(allocRequest);
#else
- sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
- allocWidth, allocHeight, allocFormat, BQ_LAYER_COUNT,
- allocUsage, allocName);
+ sp<GraphicBuffer> graphicBuffer =
+ sp<GraphicBuffer>::make(allocWidth, allocHeight, allocFormat, BQ_LAYER_COUNT,
+ allocUsage, allocName);
#endif
- status_t result = graphicBuffer->initCheck();
+ status_t result = graphicBuffer->initCheck();
- if (result != NO_ERROR) {
- BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
- " %u, usage %#" PRIx64 ")", width, height, format, usage);
- std::lock_guard<std::mutex> lock(mCore->mMutex);
- mCore->mIsAllocating = false;
- mCore->mIsAllocatingCondition.notify_all();
- return;
- }
- buffers.push_back(graphicBuffer);
+ if (result != NO_ERROR) {
+ BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
+ " %u, usage %#" PRIx64 ")", width, height, format, usage);
+ std::lock_guard<std::mutex> lock(mCore->mMutex);
+ mCore->mIsAllocating = false;
+ mCore->mIsAllocatingCondition.notify_all();
+ return;
}
{ // Autolock scope
@@ -1621,15 +1727,13 @@
continue;
}
- for (size_t i = 0; i < newBufferCount; ++i) {
- if (mCore->mFreeSlots.empty()) {
- BQ_LOGV("allocateBuffers: a slot was occupied while "
- "allocating. Dropping allocated buffer.");
- continue;
- }
+ if (mCore->mFreeSlots.empty()) {
+ BQ_LOGV("allocateBuffers: a slot was occupied while "
+ "allocating. Dropping allocated buffer.");
+ } else {
auto slot = mCore->mFreeSlots.begin();
mCore->clearBufferSlotLocked(*slot); // Clean up the slot first
- mSlots[*slot].mGraphicBuffer = buffers[i];
+ mSlots[*slot].mGraphicBuffer = graphicBuffer;
mSlots[*slot].mFence = Fence::NO_FENCE;
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_EXTENDEDALLOCATE)
mSlots[*slot].mAdditionalOptionsGenerationId = allocOptionsGenId;
diff --git a/libs/gui/BufferReleaseChannel.cpp b/libs/gui/BufferReleaseChannel.cpp
index 27367aa..4f495d0 100644
--- a/libs/gui/BufferReleaseChannel.cpp
+++ b/libs/gui/BufferReleaseChannel.cpp
@@ -35,35 +35,35 @@
namespace {
template <typename T>
-static void readAligned(const void*& buffer, size_t& size, T& value) {
+void readAligned(const void*& buffer, size_t& size, T& value) {
size -= FlattenableUtils::align<alignof(T)>(buffer);
FlattenableUtils::read(buffer, size, value);
}
template <typename T>
-static void writeAligned(void*& buffer, size_t& size, T value) {
+void writeAligned(void*& buffer, size_t& size, T value) {
size -= FlattenableUtils::align<alignof(T)>(buffer);
FlattenableUtils::write(buffer, size, value);
}
template <typename T>
-static void addAligned(size_t& size, T /* value */) {
+void addAligned(size_t& size, T /* value */) {
size = FlattenableUtils::align<sizeof(T)>(size);
size += sizeof(T);
}
template <typename T>
-static inline constexpr uint32_t low32(const T n) {
+inline constexpr uint32_t low32(const T n) {
return static_cast<uint32_t>(static_cast<uint64_t>(n));
}
template <typename T>
-static inline constexpr uint32_t high32(const T n) {
+inline constexpr uint32_t high32(const T n) {
return static_cast<uint32_t>(static_cast<uint64_t>(n) >> 32);
}
template <typename T>
-static inline constexpr T to64(const uint32_t lo, const uint32_t hi) {
+inline constexpr T to64(const uint32_t lo, const uint32_t hi) {
return static_cast<T>(static_cast<uint64_t>(hi) << 32 | lo);
}
@@ -108,7 +108,7 @@
status_t BufferReleaseChannel::Message::unflatten(void const*& buffer, size_t& size,
int const*& fds, size_t& count) {
- releaseFence = new Fence();
+ releaseFence = sp<Fence>::make();
if (status_t err = releaseFence->unflatten(buffer, size, fds, count); err != OK) {
return err;
}
@@ -136,23 +136,23 @@
status_t BufferReleaseChannel::ConsumerEndpoint::readReleaseFence(
ReleaseCallbackId& outReleaseCallbackId, sp<Fence>& outReleaseFence,
uint32_t& outMaxAcquiredBufferCount) {
+ std::lock_guard lock{mMutex};
Message message;
mFlattenedBuffer.resize(message.getFlattenedSize());
- std::array<uint8_t, CMSG_SPACE(sizeof(int))> controlMessageBuffer;
+ std::array<uint8_t, CMSG_SPACE(sizeof(int))> controlMessageBuffer{};
iovec iov{
.iov_base = mFlattenedBuffer.data(),
.iov_len = mFlattenedBuffer.size(),
};
- msghdr msg{
- .msg_iov = &iov,
- .msg_iovlen = 1,
- .msg_control = controlMessageBuffer.data(),
- .msg_controllen = controlMessageBuffer.size(),
- };
+ msghdr msg{};
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = controlMessageBuffer.data();
+ msg.msg_controllen = controlMessageBuffer.size();
- int result;
+ ssize_t result;
do {
result = recvmsg(mFd, &msg, 0);
} while (result == -1 && errno == EINTR);
@@ -160,7 +160,7 @@
if (errno == EWOULDBLOCK || errno == EAGAIN) {
return WOULD_BLOCK;
}
- ALOGE("Error reading release fence from socket: error %#x (%s)", errno, strerror(errno));
+ ALOGE("Error reading release fence from socket: error %d (%s)", errno, strerror(errno));
return UNKNOWN_ERROR;
}
@@ -199,9 +199,9 @@
return OK;
}
-int BufferReleaseChannel::ProducerEndpoint::writeReleaseFence(const ReleaseCallbackId& callbackId,
- const sp<Fence>& fence,
- uint32_t maxAcquiredBufferCount) {
+status_t BufferReleaseChannel::ProducerEndpoint::writeReleaseFence(
+ const ReleaseCallbackId& callbackId, const sp<Fence>& fence,
+ uint32_t maxAcquiredBufferCount) {
Message message{callbackId, fence ? fence : Fence::NO_FENCE, maxAcquiredBufferCount};
mFlattenedBuffer.resize(message.getFlattenedSize());
int flattenedFd;
@@ -212,25 +212,22 @@
size_t flattenedBufferSize = mFlattenedBuffer.size();
int* flattenedFdPtr = &flattenedFd;
size_t flattenedFdCount = 1;
- if (status_t err = message.flatten(flattenedBufferPtr, flattenedBufferSize, flattenedFdPtr,
- flattenedFdCount);
- err != OK) {
- ALOGE("Failed to flatten BufferReleaseChannel message.");
- return err;
+ if (status_t status = message.flatten(flattenedBufferPtr, flattenedBufferSize,
+ flattenedFdPtr, flattenedFdCount);
+ status != OK) {
+ return status;
}
}
- iovec iov{
- .iov_base = mFlattenedBuffer.data(),
- .iov_len = mFlattenedBuffer.size(),
- };
+ iovec iov{};
+ iov.iov_base = mFlattenedBuffer.data();
+ iov.iov_len = mFlattenedBuffer.size();
- msghdr msg{
- .msg_iov = &iov,
- .msg_iovlen = 1,
- };
+ msghdr msg{};
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
- std::array<uint8_t, CMSG_SPACE(sizeof(int))> controlMessageBuffer;
+ std::array<uint8_t, CMSG_SPACE(sizeof(int))> controlMessageBuffer{};
if (fence && fence->isValid()) {
msg.msg_control = controlMessageBuffer.data();
msg.msg_controllen = controlMessageBuffer.size();
@@ -242,12 +239,11 @@
memcpy(CMSG_DATA(cmsg), &flattenedFd, sizeof(int));
}
- int result;
+ ssize_t result;
do {
result = sendmsg(mFd, &msg, 0);
} while (result == -1 && errno == EINTR);
if (result == -1) {
- ALOGD("Error writing release fence to socket: error %#x (%s)", errno, strerror(errno));
return -errno;
}
@@ -343,16 +339,9 @@
return -errno;
}
- // Make the producer write-only
- if (shutdown(producerFd.get(), SHUT_RD) == -1) {
- ALOGE("[%s] Failed to shutdown reading on producer socket. errno=%d message='%s'",
- name.c_str(), errno, strerror(errno));
- return -errno;
- }
-
outConsumer = std::make_unique<ConsumerEndpoint>(name, std::move(consumerFd));
outProducer = std::make_shared<ProducerEndpoint>(std::move(name), std::move(producerFd));
return STATUS_OK;
}
-} // namespace android::gui
\ No newline at end of file
+} // namespace android::gui
diff --git a/libs/gui/BufferStuffing.md b/libs/gui/BufferStuffing.md
new file mode 100644
index 0000000..6ed8ad9
--- /dev/null
+++ b/libs/gui/BufferStuffing.md
@@ -0,0 +1,7 @@
+### Buffer Stuffing and Recovery ###
+
+Buffer stuffing happens on the client side when SurfaceFlinger misses a frame, but the client continues producing buffers at the same rate. This could occur anytime when SurfaceFlinger does not meet the expected timeline’s deadline to finish composing a frame. As a result, SurfaceFlinger cannot yet release the buffer for the frame that it missed and the client has one less buffer to render into. The client may then run out of buffers or have to wait for buffer release callbacks, increasing the chances of janking when clients render multiple windows.
+
+Recovery is implemented by first detecting when buffer stuffing occurs and ensuring that the elevated buffer counts in the server are from a relevant SurfaceControl (is a ViewRootImpl). Other SurfaceControl buffer producers such as games, media, and camera have other reasons for expectedly increased buffer counts, which do not need buffer stuffing recovery.
+
+The actual recovery adjusts the animation timeline in the Choreographer so that the client deadlines for subsequent frames are moved forward in time by one frame. This approach adjusts the client buffer production timeline such that SurfaceFlinger does not fall behind when it misses a frame because the client will simply match its frame production rate with SurfaceFlinger. Ordinarily, buffer stuffing is problematic because the client continues producing buffers when SurfaceFlinger is behind. However, if the client delays producing its buffers to match SurfaceFlinger’s rate, the animation has new frame deadlines that can be reasonably met. The animation is effectively paused for one frame longer than originally intended, and continues the remainder of the animation normally.
\ No newline at end of file
diff --git a/libs/gui/Choreographer.cpp b/libs/gui/Choreographer.cpp
index 0c8f3fa..80a3543 100644
--- a/libs/gui/Choreographer.cpp
+++ b/libs/gui/Choreographer.cpp
@@ -20,6 +20,7 @@
#include <gui/Choreographer.h>
#include <gui/TraceUtils.h>
#include <jni.h>
+#include <utils/Looper.h>
#undef LOG_TAG
#define LOG_TAG "AChoreographer"
@@ -69,7 +70,7 @@
Choreographer::Context Choreographer::gChoreographers;
-static thread_local Choreographer* gChoreographer;
+static thread_local sp<Choreographer> gChoreographer;
void Choreographer::initJVM(JNIEnv* env) {
env->GetJavaVM(&gJni.jvm);
@@ -86,14 +87,14 @@
"()V");
}
-Choreographer* Choreographer::getForThread() {
+sp<Choreographer> Choreographer::getForThread() {
if (gChoreographer == nullptr) {
sp<Looper> looper = Looper::getForThread();
if (!looper.get()) {
ALOGW("No looper prepared for thread");
return nullptr;
}
- gChoreographer = new Choreographer(looper);
+ gChoreographer = sp<Choreographer>::make(looper);
status_t result = gChoreographer->initialize();
if (result != OK) {
ALOGW("Failed to initialize");
@@ -238,7 +239,7 @@
// socket should be atomic across processes.
DisplayEventReceiver::Event event;
event.header =
- DisplayEventReceiver::Event::Header{DisplayEventReceiver::DISPLAY_EVENT_NULL,
+ DisplayEventReceiver::Event::Header{DisplayEventType::DISPLAY_EVENT_NULL,
PhysicalDisplayId::fromPort(0), systemTime()};
injectEvent(event);
}
@@ -369,6 +370,10 @@
this, to_string(displayId).c_str(), connectedLevel, maxLevel);
}
+void Choreographer::dispatchModeRejected(PhysicalDisplayId, int32_t) {
+ LOG_ALWAYS_FATAL("dispatchModeRejected was called but was never registered");
+}
+
void Choreographer::handleMessage(const Message& message) {
switch (message.what) {
case MSG_SCHEDULE_CALLBACKS:
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 602bba8..117a362 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -31,12 +31,15 @@
#include <gui/BufferItem.h>
#include <gui/BufferQueue.h>
#include <gui/ConsumerBase.h>
+#include <gui/IConsumerListener.h>
#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <private/gui/ComposerService.h>
+#include <ui/BufferQueueDefs.h>
+
#include <log/log.h>
#include <utils/Log.h>
#include <utils/String8.h>
@@ -59,51 +62,74 @@
return android_atomic_inc(&globalCounter);
}
-ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp) :
+ConsumerBase::ConsumerBase(const sp<IGraphicBufferConsumer>& bufferQueue, bool controlledByApp)
+ :
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ mSlots(BufferQueueDefs::NUM_BUFFER_SLOTS),
+#endif
mAbandoned(false),
mConsumer(bufferQueue),
- mPrevFinalReleaseFence(Fence::NO_FENCE) {
- initialize(controlledByApp);
+ mPrevFinalReleaseFence(Fence::NO_FENCE),
+ mIsControlledByApp(controlledByApp) {
}
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
ConsumerBase::ConsumerBase(bool controlledByApp, bool consumerIsSurfaceFlinger)
- : mAbandoned(false), mPrevFinalReleaseFence(Fence::NO_FENCE) {
+ :
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ mSlots(BufferQueueDefs::NUM_BUFFER_SLOTS),
+#endif
+ mAbandoned(false),
+ mPrevFinalReleaseFence(Fence::NO_FENCE),
+ mIsControlledByApp(controlledByApp) {
sp<IGraphicBufferProducer> producer;
BufferQueue::createBufferQueue(&producer, &mConsumer, consumerIsSurfaceFlinger);
mSurface = sp<Surface>::make(producer, controlledByApp);
- initialize(controlledByApp);
}
ConsumerBase::ConsumerBase(const sp<IGraphicBufferProducer>& producer,
const sp<IGraphicBufferConsumer>& consumer, bool controlledByApp)
- : mAbandoned(false),
+ :
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ mSlots(BufferQueueDefs::NUM_BUFFER_SLOTS),
+#endif
+ mAbandoned(false),
mConsumer(consumer),
mSurface(sp<Surface>::make(producer, controlledByApp)),
- mPrevFinalReleaseFence(Fence::NO_FENCE) {
- initialize(controlledByApp);
+ mPrevFinalReleaseFence(Fence::NO_FENCE),
+ mIsControlledByApp(controlledByApp) {
}
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
-void ConsumerBase::initialize(bool controlledByApp) {
+void ConsumerBase::onFirstRef() {
+ ConsumerListener::onFirstRef();
+ initialize();
+}
+
+void ConsumerBase::initialize() {
// Choose a name using the PID and a process-unique ID.
mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
- // Note that we can't create an sp<...>(this) in a ctor that will not keep a
- // reference once the ctor ends, as that would cause the refcount of 'this'
- // dropping to 0 at the end of the ctor. Since all we need is a wp<...>
- // that's what we create.
- wp<ConsumerListener> listener = static_cast<ConsumerListener*>(this);
- sp<IConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener);
+ // Here we depend on an sp/wp having been created for `this`. For this
+ // reason, initialize() cannot be called from a ctor.
+ wp<ConsumerListener> listener = wp<ConsumerListener>::fromExisting(this);
+ sp<IConsumerListener> proxy = sp<BufferQueue::ProxyConsumerListener>::make(listener);
- status_t err = mConsumer->consumerConnect(proxy, controlledByApp);
+ status_t err = mConsumer->consumerConnect(proxy, mIsControlledByApp);
if (err != NO_ERROR) {
CB_LOGE("ConsumerBase: error connecting to BufferQueue: %s (%d)",
strerror(-err), err);
- } else {
- mConsumer->setConsumerName(mName);
+ return;
}
+
+ mConsumer->setConsumerName(mName);
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ if (err = mConsumer->allowUnlimitedSlots(true); err != NO_ERROR) {
+ CB_LOGE("ConsumerBase: error marking as allowed to have unlimited slots: %s (%d)",
+ strerror(-err), err);
+ }
+#endif
}
ConsumerBase::~ConsumerBase() {
@@ -130,7 +156,11 @@
}
uint64_t id = buffer->getId();
- for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; i++) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ for (int i = 0; i < (int)mSlots.size(); ++i) {
+#else
+ for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+#endif
auto& slot = mSlots[i];
if (slot.mGraphicBuffer && slot.mGraphicBuffer->getId() == id) {
return i;
@@ -242,6 +272,15 @@
return;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ std::vector<bool> mask;
+ mConsumer->getReleasedBuffersExtended(&mask);
+ for (size_t i = 0; i < mSlots.size(); i++) {
+ if (mask[i]) {
+ freeBufferLocked(i);
+ }
+ }
+#else
uint64_t mask = 0;
mConsumer->getReleasedBuffers(&mask);
for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
@@ -249,11 +288,23 @@
freeBufferLocked(i);
}
}
+#endif
}
void ConsumerBase::onSidebandStreamChanged() {
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+void ConsumerBase::onSlotCountChanged(int slotCount) {
+ CB_LOGV("onSlotCountChanged: %d", slotCount);
+ Mutex::Autolock lock(mMutex);
+
+ if (slotCount > (int)mSlots.size()) {
+ mSlots.resize(slotCount);
+ }
+}
+#endif
+
void ConsumerBase::abandon() {
CB_LOGV("abandon");
Mutex::Autolock lock(mMutex);
@@ -270,7 +321,11 @@
CB_LOGE("abandonLocked: ConsumerBase is abandoned!");
return;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ for (int i = 0; i < (int)mSlots.size(); ++i) {
+#else
for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+#endif
freeBufferLocked(i);
}
// disconnect from the BufferQueue
@@ -334,6 +389,26 @@
}
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+status_t ConsumerBase::addReleaseFence(const sp<GraphicBuffer> buffer, const sp<Fence>& fence) {
+ CB_LOGV("addReleaseFence");
+ Mutex::Autolock lock(mMutex);
+
+ if (mAbandoned) {
+ CB_LOGE("addReleaseFence: ConsumerBase is abandoned!");
+ return NO_INIT;
+ }
+ if (buffer == nullptr) {
+ return BAD_VALUE;
+ }
+
+ int slotIndex = getSlotForBufferLocked(buffer);
+ if (slotIndex == BufferQueue::INVALID_BUFFER_SLOT) {
+ return BAD_VALUE;
+ }
+
+ return addReleaseFenceLocked(slotIndex, buffer, fence);
+}
+
status_t ConsumerBase::setDefaultBufferSize(uint32_t width, uint32_t height) {
Mutex::Autolock _l(mMutex);
if (mAbandoned) {
@@ -387,6 +462,15 @@
CB_LOGE("setMaxBufferCount: ConsumerBase is abandoned!");
return NO_INIT;
}
+
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ if (status_t err = mConsumer->allowUnlimitedSlots(false); err != NO_ERROR) {
+ CB_LOGE("ConsumerBase: error marking as not allowed to have unlimited slots: %s (%d)",
+ strerror(-err), err);
+ return err;
+ }
+#endif
+
return mConsumer->setMaxBufferCount(bufferCount);
}
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
@@ -400,7 +484,6 @@
return mConsumer->setMaxAcquiredBufferCount(maxAcquiredBuffers);
}
-#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
status_t ConsumerBase::setConsumerIsProtected(bool isProtected) {
Mutex::Autolock lock(mMutex);
if (mAbandoned) {
@@ -409,7 +492,6 @@
}
return mConsumer->setConsumerIsProtected(isProtected);
}
-#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
sp<NativeHandle> ConsumerBase::getSidebandStream() const {
Mutex::Autolock _l(mMutex);
@@ -448,6 +530,15 @@
if (err != OK) {
return err;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ std::vector<bool> mask;
+ mConsumer->getReleasedBuffersExtended(&mask);
+ for (int i = 0; i < (int)mSlots.size(); i++) {
+ if (mask[i]) {
+ freeBufferLocked(i);
+ }
+ }
+#else
uint64_t mask;
mConsumer->getReleasedBuffers(&mask);
for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
@@ -455,6 +546,8 @@
freeBufferLocked(i);
}
}
+#endif
+
return OK;
}
@@ -585,9 +678,13 @@
return OK;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+status_t ConsumerBase::releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer) {
+#else
status_t ConsumerBase::releaseBufferLocked(
int slot, const sp<GraphicBuffer> graphicBuffer,
EGLDisplay display, EGLSyncKHR eglFence) {
+#endif
if (mAbandoned) {
CB_LOGE("releaseBufferLocked: ConsumerBase is abandoned!");
return NO_INIT;
@@ -596,13 +693,20 @@
// buffer on the same slot), the buffer producer is definitely no longer
// tracking it.
if (!stillTracking(slot, graphicBuffer)) {
+ CB_LOGV("releaseBufferLocked: Not tracking, exiting without calling releaseBuffer for "
+ "slot=%d/%" PRIu64,
+ slot, mSlots[slot].mFrameNumber);
return OK;
}
CB_LOGV("releaseBufferLocked: slot=%d/%" PRIu64,
slot, mSlots[slot].mFrameNumber);
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber, mSlots[slot].mFence);
+#else
status_t err = mConsumer->releaseBuffer(slot, mSlots[slot].mFrameNumber,
display, eglFence, mSlots[slot].mFence);
+#endif
if (err == IGraphicBufferConsumer::STALE_BUFFER_SLOT) {
freeBufferLocked(slot);
}
@@ -615,7 +719,11 @@
bool ConsumerBase::stillTracking(int slot,
const sp<GraphicBuffer> graphicBuffer) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ if (slot < 0 || slot >= (int)mSlots.size()) {
+#else
if (slot < 0 || slot >= BufferQueue::NUM_BUFFER_SLOTS) {
+#endif
return false;
}
return (mSlots[slot].mGraphicBuffer != nullptr &&
diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index 23b432e..ecbceb7 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -20,7 +20,11 @@
#include <com_android_graphics_libgui_flags.h>
#include <gui/BufferItem.h>
+#include <gui/BufferQueue.h>
#include <gui/CpuConsumer.h>
+#include <gui/IGraphicBufferConsumer.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/Surface.h>
#include <utils/Log.h>
#define CC_LOGV(x, ...) ALOGV("[%s] " x, mName.c_str(), ##__VA_ARGS__)
@@ -31,6 +35,28 @@
namespace android {
+std::tuple<sp<CpuConsumer>, sp<Surface>> CpuConsumer::create(size_t maxLockedBuffers,
+ bool controlledByApp,
+ bool isConsumerSurfaceFlinger) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+ sp<CpuConsumer> consumer =
+ sp<CpuConsumer>::make(maxLockedBuffers, controlledByApp, isConsumerSurfaceFlinger);
+ return {consumer, consumer->getSurface()};
+#else
+ sp<IGraphicBufferProducer> igbp;
+ sp<IGraphicBufferConsumer> igbc;
+ BufferQueue::createBufferQueue(&igbp, &igbc, isConsumerSurfaceFlinger);
+
+ return {sp<CpuConsumer>::make(igbc, maxLockedBuffers, controlledByApp),
+ sp<Surface>::make(igbp, controlledByApp)};
+#endif
+}
+
+sp<CpuConsumer> CpuConsumer::create(const sp<IGraphicBufferConsumer>& bq, size_t maxLockedBuffers,
+ bool controlledByApp) {
+ return sp<CpuConsumer>::make(bq, maxLockedBuffers, controlledByApp);
+}
+
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
CpuConsumer::CpuConsumer(size_t maxLockedBuffers, bool controlledByApp,
bool isConsumerSurfaceFlinger)
@@ -230,7 +256,7 @@
return err;
}
- sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
+ sp<Fence> fence(fenceFd >= 0 ? sp<Fence>::make(fenceFd) : Fence::NO_FENCE);
addReleaseFenceLocked(ab.mSlot, ab.mGraphicBuffer, fence);
releaseBufferLocked(ab.mSlot, ab.mGraphicBuffer);
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index c46f9c5..6f23885 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -167,7 +167,7 @@
for (ssize_t i = 0; i < n; i++) {
const DisplayEventReceiver::Event& ev = buf[i];
switch (ev.header.type) {
- case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
+ case DisplayEventType::DISPLAY_EVENT_VSYNC:
// Later vsync events will just overwrite the info from earlier
// ones. That's fine, we only care about the most recent.
gotVsync = true;
@@ -183,7 +183,7 @@
ATRACE_INT("RenderRate", fps);
}
break;
- case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
+ case DisplayEventType::DISPLAY_EVENT_HOTPLUG:
if (ev.hotplug.connectionError == 0) {
dispatchHotplug(ev.header.timestamp, ev.header.displayId,
ev.hotplug.connected);
@@ -192,27 +192,27 @@
ev.hotplug.connectionError);
}
break;
- case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE:
+ case DisplayEventType::DISPLAY_EVENT_MODE_CHANGE:
dispatchModeChanged(ev.header.timestamp, ev.header.displayId,
ev.modeChange.modeId, ev.modeChange.vsyncPeriod);
break;
- case DisplayEventReceiver::DISPLAY_EVENT_NULL:
+ case DisplayEventType::DISPLAY_EVENT_NULL:
dispatchNullEvent(ev.header.timestamp, ev.header.displayId);
break;
- case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE:
+ case DisplayEventType::DISPLAY_EVENT_FRAME_RATE_OVERRIDE:
mFrameRateOverrides.emplace_back(ev.frameRateOverride);
break;
- case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH:
+ case DisplayEventType::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH:
dispatchFrameRateOverrides(ev.header.timestamp, ev.header.displayId,
std::move(mFrameRateOverrides));
break;
- case DisplayEventReceiver::DISPLAY_EVENT_HDCP_LEVELS_CHANGE:
+ case DisplayEventType::DISPLAY_EVENT_HDCP_LEVELS_CHANGE:
dispatchHdcpLevelsChanged(ev.header.displayId,
ev.hdcpLevelsChange.connectedLevel,
ev.hdcpLevelsChange.maxLevel);
break;
- default:
- ALOGW("dispatcher %p ~ ignoring unknown event type %#x", this, ev.header.type);
+ case DisplayEventType::DISPLAY_EVENT_MODE_REJECTION:
+ dispatchModeRejected(ev.header.displayId, ev.modeRejection.modeId);
break;
}
}
diff --git a/libs/gui/DisplayLuts.cpp b/libs/gui/DisplayLuts.cpp
new file mode 100644
index 0000000..8042976
--- /dev/null
+++ b/libs/gui/DisplayLuts.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2024 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/gui/DisplayLuts.h"
+#include <gui/DisplayLuts.h>
+#include <private/gui/ParcelUtils.h>
+
+namespace android::gui {
+
+status_t DisplayLuts::Entry::readFromParcel(const android::Parcel* parcel) {
+ if (parcel == nullptr) {
+ ALOGE("%s: Null parcel", __func__);
+ return BAD_VALUE;
+ }
+
+ SAFE_PARCEL(parcel->readInt32, &dimension);
+ SAFE_PARCEL(parcel->readInt32, &size);
+ SAFE_PARCEL(parcel->readInt32, &samplingKey);
+
+ return OK;
+}
+
+status_t DisplayLuts::Entry::writeToParcel(android::Parcel* parcel) const {
+ if (parcel == nullptr) {
+ ALOGE("%s: Null parcel", __func__);
+ return BAD_VALUE;
+ }
+
+ SAFE_PARCEL(parcel->writeInt32, dimension);
+ SAFE_PARCEL(parcel->writeInt32, size);
+ SAFE_PARCEL(parcel->writeInt32, samplingKey);
+
+ return OK;
+}
+
+status_t DisplayLuts::readFromParcel(const android::Parcel* parcel) {
+ if (parcel == nullptr) {
+ ALOGE("%s: Null parcel", __func__);
+ return BAD_VALUE;
+ }
+
+ SAFE_PARCEL(parcel->readUniqueFileDescriptor, &fd);
+ SAFE_PARCEL(parcel->readInt32Vector, &offsets);
+ int32_t numLutProperties;
+ SAFE_PARCEL(parcel->readInt32, &numLutProperties);
+ lutProperties.reserve(numLutProperties);
+ for (int32_t i = 0; i < numLutProperties; i++) {
+ lutProperties.push_back({});
+ SAFE_PARCEL(lutProperties.back().readFromParcel, parcel);
+ }
+ return OK;
+}
+
+status_t DisplayLuts::writeToParcel(android::Parcel* parcel) const {
+ if (parcel == nullptr) {
+ ALOGE("%s: Null parcel", __func__);
+ return BAD_VALUE;
+ }
+
+ SAFE_PARCEL(parcel->writeUniqueFileDescriptor, fd);
+ SAFE_PARCEL(parcel->writeInt32Vector, offsets);
+ SAFE_PARCEL(parcel->writeInt32, static_cast<int32_t>(lutProperties.size()));
+ for (auto& entry : lutProperties) {
+ SAFE_PARCEL(entry.writeToParcel, parcel);
+ }
+ return OK;
+}
+} // namespace android::gui
\ No newline at end of file
diff --git a/libs/gui/Flags.cpp b/libs/gui/Flags.cpp
new file mode 100644
index 0000000..ee2802f
--- /dev/null
+++ b/libs/gui/Flags.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2024 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 <gui/Flags.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/Surface.h>
+#include <gui/view/Surface.h>
+
+namespace android {
+namespace flagtools {
+sp<SurfaceType> surfaceToSurfaceType(const sp<Surface>& surface) {
+#if WB_LIBCAMERASERVICE_WITH_DEPENDENCIES
+ return surface;
+#else
+ return surface->getIGraphicBufferProducer();
+#endif
+}
+
+ParcelableSurfaceType surfaceToParcelableSurfaceType(const sp<Surface>& surface) {
+#if WB_LIBCAMERASERVICE_WITH_DEPENDENCIES
+ return view::Surface::fromSurface(surface);
+#else
+ return surface->getIGraphicBufferProducer();
+#endif
+}
+
+sp<IGraphicBufferProducer> surfaceTypeToIGBP(const sp<SurfaceType>& surface) {
+#if WB_LIBCAMERASERVICE_WITH_DEPENDENCIES
+ return surface->getIGraphicBufferProducer();
+#else
+ return surface;
+#endif
+}
+
+bool isSurfaceTypeValid(const sp<SurfaceType>& surface) {
+#if WB_LIBCAMERASERVICE_WITH_DEPENDENCIES
+ return Surface::isValid(surface);
+#else
+ return surface != nullptr;
+#endif
+}
+
+ParcelableSurfaceType toParcelableSurfaceType(const view::Surface& surface) {
+#if WB_LIBCAMERASERVICE_WITH_DEPENDENCIES
+ return surface;
+#else
+ return surface.graphicBufferProducer;
+#endif
+}
+
+ParcelableSurfaceType convertSurfaceTypeToParcelable(sp<SurfaceType> surface) {
+#if WB_LIBCAMERASERVICE_WITH_DEPENDENCIES
+ return view::Surface::fromSurface(surface);
+#else
+ return surface;
+#endif
+}
+
+sp<SurfaceType> convertParcelableSurfaceTypeToSurface(const ParcelableSurfaceType& surface) {
+#if WB_LIBCAMERASERVICE_WITH_DEPENDENCIES
+ return surface.toSurface();
+#else
+ return surface;
+#endif
+}
+
+} // namespace flagtools
+} // namespace android
\ No newline at end of file
diff --git a/libs/gui/FrameRateUtils.cpp b/libs/gui/FrameRateUtils.cpp
index 01aa7ed..1b2354e 100644
--- a/libs/gui/FrameRateUtils.cpp
+++ b/libs/gui/FrameRateUtils.cpp
@@ -42,7 +42,7 @@
if (compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT &&
compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE &&
- compatibility != ANATIVEWINDOW_FRAME_RATE_GTE &&
+ compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_AT_LEAST &&
(!privileged ||
(compatibility != ANATIVEWINDOW_FRAME_RATE_EXACT &&
compatibility != ANATIVEWINDOW_FRAME_RATE_NO_VOTE))) {
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 95cce5c..2c5770d 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -37,6 +37,7 @@
#include <gui/DebugEGLImageTracker.h>
#include <gui/GLConsumer.h>
#include <gui/ISurfaceComposer.h>
+#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <private/gui/ComposerService.h>
@@ -101,6 +102,50 @@
return hasIt;
}
+std::tuple<sp<GLConsumer>, sp<Surface>> GLConsumer::create(uint32_t tex, uint32_t textureTarget,
+ bool useFenceSync,
+ bool isControlledByApp) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+ sp<GLConsumer> consumer =
+ sp<GLConsumer>::make(tex, textureTarget, useFenceSync, isControlledByApp);
+ return {consumer, consumer->getSurface()};
+#else
+ sp<IGraphicBufferProducer> igbp;
+ sp<IGraphicBufferConsumer> igbc;
+ BufferQueue::createBufferQueue(&igbp, &igbc);
+
+ return {sp<GLConsumer>::make(igbc, tex, textureTarget, useFenceSync, isControlledByApp),
+ sp<Surface>::make(igbp, isControlledByApp)};
+#endif
+}
+
+std::tuple<sp<GLConsumer>, sp<Surface>> GLConsumer::create(uint32_t textureTarget,
+ bool useFenceSync,
+ bool isControlledByApp) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+ sp<GLConsumer> consumer = sp<GLConsumer>::make(textureTarget, useFenceSync, isControlledByApp);
+ return {consumer, consumer->getSurface()};
+#else
+ sp<IGraphicBufferProducer> igbp;
+ sp<IGraphicBufferConsumer> igbc;
+ BufferQueue::createBufferQueue(&igbp, &igbc);
+
+ return {sp<GLConsumer>::make(igbc, textureTarget, useFenceSync, isControlledByApp),
+ sp<Surface>::make(igbp, isControlledByApp)};
+#endif
+}
+
+sp<GLConsumer> GLConsumer::create(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
+ uint32_t textureTarget, bool useFenceSync,
+ bool isControlledByApp) {
+ return sp<GLConsumer>::make(bq, tex, textureTarget, useFenceSync, isControlledByApp);
+}
+
+sp<GLConsumer> GLConsumer::create(const sp<IGraphicBufferConsumer>& bq, uint32_t textureTarget,
+ bool useFenceSync, bool isControlledByApp) {
+ return sp<GLConsumer>::make(bq, textureTarget, useFenceSync, isControlledByApp);
+}
+
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
GLConsumer::GLConsumer(uint32_t tex, uint32_t texTarget, bool useFenceSync, bool isControlledByApp)
: ConsumerBase(isControlledByApp, /* isConsumerSurfaceFlinger */ false),
@@ -119,6 +164,9 @@
mTexTarget(texTarget),
mEglDisplay(EGL_NO_DISPLAY),
mEglContext(EGL_NO_CONTEXT),
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ mEglSlots(BufferQueueDefs::NUM_BUFFER_SLOTS),
+#endif
mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
mAttached(true) {
GLC_LOGV("GLConsumer");
@@ -129,27 +177,29 @@
}
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
-GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
- uint32_t texTarget, bool useFenceSync, bool isControlledByApp) :
- ConsumerBase(bq, isControlledByApp),
- mCurrentCrop(Rect::EMPTY_RECT),
- mCurrentTransform(0),
- mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
- mCurrentFence(Fence::NO_FENCE),
- mCurrentTimestamp(0),
- mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
- mCurrentFrameNumber(0),
- mDefaultWidth(1),
- mDefaultHeight(1),
- mFilteringEnabled(true),
- mTexName(tex),
- mUseFenceSync(useFenceSync),
- mTexTarget(texTarget),
- mEglDisplay(EGL_NO_DISPLAY),
- mEglContext(EGL_NO_CONTEXT),
- mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
- mAttached(true)
-{
+GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex, uint32_t texTarget,
+ bool useFenceSync, bool isControlledByApp)
+ : ConsumerBase(bq, isControlledByApp),
+ mCurrentCrop(Rect::EMPTY_RECT),
+ mCurrentTransform(0),
+ mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
+ mCurrentFence(Fence::NO_FENCE),
+ mCurrentTimestamp(0),
+ mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
+ mCurrentFrameNumber(0),
+ mDefaultWidth(1),
+ mDefaultHeight(1),
+ mFilteringEnabled(true),
+ mTexName(tex),
+ mUseFenceSync(useFenceSync),
+ mTexTarget(texTarget),
+ mEglDisplay(EGL_NO_DISPLAY),
+ mEglContext(EGL_NO_CONTEXT),
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ mEglSlots(BufferQueueDefs::NUM_BUFFER_SLOTS),
+#endif
+ mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
+ mAttached(true) {
GLC_LOGV("GLConsumer");
memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(),
@@ -176,6 +226,9 @@
mTexTarget(texTarget),
mEglDisplay(EGL_NO_DISPLAY),
mEglContext(EGL_NO_CONTEXT),
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ mEglSlots(BufferQueueDefs::NUM_BUFFER_SLOTS),
+#endif
mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
mAttached(false) {
GLC_LOGV("GLConsumer");
@@ -204,6 +257,9 @@
mTexTarget(texTarget),
mEglDisplay(EGL_NO_DISPLAY),
mEglContext(EGL_NO_CONTEXT),
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ mEglSlots(BufferQueueDefs::NUM_BUFFER_SLOTS),
+#endif
mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
mAttached(false) {
GLC_LOGV("GLConsumer");
@@ -314,7 +370,7 @@
// so... basically, nothing more to do here.
}
- err = releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR);
+ err = releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer);
if (err < NO_ERROR) {
GLC_LOGE("releaseTexImage: failed to release buffer: %s (%d)",
strerror(-err), err);
@@ -322,7 +378,7 @@
}
if (mReleasedTexImage == nullptr) {
- mReleasedTexImage = new EglImage(getDebugTexImageBuffer());
+ mReleasedTexImage = sp<EglImage>::make(getDebugTexImageBuffer());
}
mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
@@ -354,10 +410,10 @@
if (CC_UNLIKELY(sReleasedTexImageBuffer == nullptr)) {
// The first time, create the debug texture in case the application
// continues to use it.
- sp<GraphicBuffer> buffer = new GraphicBuffer(
- kDebugData.width, kDebugData.height, PIXEL_FORMAT_RGBA_8888,
- DEFAULT_USAGE_FLAGS | GraphicBuffer::USAGE_SW_WRITE_RARELY,
- "[GLConsumer debug texture]");
+ sp<GraphicBuffer> buffer =
+ sp<GraphicBuffer>::make(kDebugData.width, kDebugData.height, PIXEL_FORMAT_RGBA_8888,
+ DEFAULT_USAGE_FLAGS | GraphicBuffer::USAGE_SW_WRITE_RARELY,
+ "[GLConsumer debug texture]");
uint32_t* bits;
buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits));
uint32_t stride = buffer->getStride();
@@ -389,24 +445,35 @@
// replaces any old EglImage with a new one (using the new buffer).
if (item->mGraphicBuffer != nullptr) {
int slot = item->mSlot;
- mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
+ mEglSlots[slot].mEglImage = sp<EglImage>::make(item->mGraphicBuffer);
}
return NO_ERROR;
}
-status_t GLConsumer::releaseBufferLocked(int buf,
- sp<GraphicBuffer> graphicBuffer,
- EGLDisplay display, EGLSyncKHR eglFence) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+void GLConsumer::onSlotCountChanged(int slotCount) {
+ ConsumerBase::onSlotCountChanged(slotCount);
+
+ Mutex::Autolock lock(mMutex);
+ if (slotCount > (int)mEglSlots.size()) {
+ mEglSlots.resize(slotCount);
+ }
+}
+#endif
+
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+status_t GLConsumer::releaseBufferLocked(int buf, sp<GraphicBuffer> graphicBuffer,
+ EGLDisplay display, EGLSyncKHR eglFence) {
// release the buffer if it hasn't already been discarded by the
// BufferQueue. This can happen, for example, when the producer of this
// buffer has reallocated the original buffer slot after this buffer
// was acquired.
- status_t err = ConsumerBase::releaseBufferLocked(
- buf, graphicBuffer, display, eglFence);
+ status_t err = ConsumerBase::releaseBufferLocked(buf, graphicBuffer, display, eglFence);
mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
return err;
}
+#endif
status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item,
PendingRelease* pendingRelease)
@@ -418,16 +485,14 @@
if (!mAttached) {
GLC_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL "
"ES context");
- releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
- mEglDisplay, EGL_NO_SYNC_KHR);
+ releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
return INVALID_OPERATION;
}
// Confirm state.
err = checkAndUpdateEglStateLocked();
if (err != NO_ERROR) {
- releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
- mEglDisplay, EGL_NO_SYNC_KHR);
+ releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
return err;
}
@@ -440,8 +505,7 @@
if (err != NO_ERROR) {
GLC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d",
mEglDisplay, slot);
- releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
- mEglDisplay, EGL_NO_SYNC_KHR);
+ releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
return UNKNOWN_ERROR;
}
@@ -453,8 +517,7 @@
// release the old buffer, so instead we just drop the new frame.
// As we are still under lock since acquireBuffer, it is safe to
// release by slot.
- releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
- mEglDisplay, EGL_NO_SYNC_KHR);
+ releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
return err;
}
}
@@ -472,9 +535,14 @@
// release old buffer
if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
if (pendingRelease == nullptr) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ status_t status =
+ releaseBufferLocked(mCurrentTexture, mCurrentTextureImage->graphicBuffer());
+#else
status_t status = releaseBufferLocked(
mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
mEglDisplay, mEglSlots[mCurrentTexture].mEglFence);
+#endif
if (status < NO_ERROR) {
GLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
strerror(-status), status);
@@ -483,10 +551,7 @@
}
} else {
pendingRelease->currentTexture = mCurrentTexture;
- pendingRelease->graphicBuffer =
- mCurrentTextureImage->graphicBuffer();
- pendingRelease->display = mEglDisplay;
- pendingRelease->fence = mEglSlots[mCurrentTexture].mEglFence;
+ pendingRelease->graphicBuffer = mCurrentTextureImage->graphicBuffer();
pendingRelease->isPending = true;
}
}
@@ -717,7 +782,7 @@
"fd: %#x", eglGetError());
return UNKNOWN_ERROR;
}
- sp<Fence> fence(new Fence(fenceFd));
+ sp<Fence> fence = sp<Fence>::make(fenceFd);
status_t err = addReleaseFenceLocked(mCurrentTexture,
mCurrentTextureImage->graphicBuffer(), fence);
if (err != OK) {
@@ -726,6 +791,11 @@
return err;
}
} else if (mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ // Basically all clients are using native fence syncs. If they aren't, we lose nothing
+ // by waiting here, because the alternative can cause deadlocks (b/339705065).
+ glFinish();
+#else
EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
if (fence != EGL_NO_SYNC_KHR) {
// There is already a fence for the current slot. We need to
@@ -755,6 +825,7 @@
}
glFlush();
mEglSlots[mCurrentTexture].mEglFence = fence;
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
}
}
diff --git a/libs/gui/IConsumerListener.cpp b/libs/gui/IConsumerListener.cpp
deleted file mode 100644
index f3bd90c..0000000
--- a/libs/gui/IConsumerListener.cpp
+++ /dev/null
@@ -1,122 +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 <gui/IConsumerListener.h>
-
-#include <gui/BufferItem.h>
-
-namespace android {
-
-namespace { // Anonymous
-
-enum class Tag : uint32_t {
- ON_DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
- ON_FRAME_AVAILABLE,
- ON_FRAME_REPLACED,
- ON_BUFFERS_RELEASED,
- ON_SIDEBAND_STREAM_CHANGED,
- ON_FRAME_DEQUEUED,
- ON_FRAME_CANCELLED,
- ON_FRAME_DETACHED,
- LAST = ON_FRAME_DETACHED,
-};
-
-} // Anonymous namespace
-
-class BpConsumerListener : public SafeBpInterface<IConsumerListener> {
-public:
- explicit BpConsumerListener(const sp<IBinder>& impl)
- : SafeBpInterface<IConsumerListener>(impl, "BpConsumerListener") {}
-
- ~BpConsumerListener() override;
-
- void onDisconnect() override {
- callRemoteAsync<decltype(&IConsumerListener::onDisconnect)>(Tag::ON_DISCONNECT);
- }
-
- void onFrameDequeued(const uint64_t bufferId) override {
- callRemoteAsync<decltype(&IConsumerListener::onFrameDequeued)>(Tag::ON_FRAME_DEQUEUED,
- bufferId);
- }
-
- void onFrameDetached(const uint64_t bufferId) override {
- callRemoteAsync<decltype(&IConsumerListener::onFrameDetached)>(Tag::ON_FRAME_DETACHED,
- bufferId);
- }
-
- void onFrameCancelled(const uint64_t bufferId) override {
- callRemoteAsync<decltype(&IConsumerListener::onFrameCancelled)>(Tag::ON_FRAME_CANCELLED,
- bufferId);
- }
-
- void onFrameAvailable(const BufferItem& item) override {
- callRemoteAsync<decltype(&IConsumerListener::onFrameAvailable)>(Tag::ON_FRAME_AVAILABLE,
- item);
- }
-
- void onFrameReplaced(const BufferItem& item) override {
- callRemoteAsync<decltype(&IConsumerListener::onFrameReplaced)>(Tag::ON_FRAME_REPLACED,
- item);
- }
-
- void onBuffersReleased() override {
- callRemoteAsync<decltype(&IConsumerListener::onBuffersReleased)>(Tag::ON_BUFFERS_RELEASED);
- }
-
- void onSidebandStreamChanged() override {
- callRemoteAsync<decltype(&IConsumerListener::onSidebandStreamChanged)>(
- Tag::ON_SIDEBAND_STREAM_CHANGED);
- }
-
- void addAndGetFrameTimestamps(const NewFrameEventsEntry* /*newTimestamps*/,
- FrameEventHistoryDelta* /*outDelta*/) override {
- LOG_ALWAYS_FATAL("IConsumerListener::addAndGetFrameTimestamps cannot be proxied");
- }
-};
-
-// Out-of-line virtual method definitions to trigger vtable emission in this translation unit (see
-// clang warning -Wweak-vtables)
-BpConsumerListener::~BpConsumerListener() = default;
-
-IMPLEMENT_META_INTERFACE(ConsumerListener, "android.gui.IConsumerListener");
-
-status_t BnConsumerListener::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
- uint32_t flags) {
- if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast<uint32_t>(Tag::LAST)) {
- return BBinder::onTransact(code, data, reply, flags);
- }
- auto tag = static_cast<Tag>(code);
- switch (tag) {
- case Tag::ON_DISCONNECT:
- return callLocalAsync(data, reply, &IConsumerListener::onDisconnect);
- case Tag::ON_FRAME_AVAILABLE:
- return callLocalAsync(data, reply, &IConsumerListener::onFrameAvailable);
- case Tag::ON_FRAME_REPLACED:
- return callLocalAsync(data, reply, &IConsumerListener::onFrameReplaced);
- case Tag::ON_BUFFERS_RELEASED:
- return callLocalAsync(data, reply, &IConsumerListener::onBuffersReleased);
- case Tag::ON_SIDEBAND_STREAM_CHANGED:
- return callLocalAsync(data, reply, &IConsumerListener::onSidebandStreamChanged);
- case Tag::ON_FRAME_DEQUEUED:
- return callLocalAsync(data, reply, &IConsumerListener::onFrameDequeued);
- case Tag::ON_FRAME_CANCELLED:
- return callLocalAsync(data, reply, &IConsumerListener::onFrameCancelled);
- case Tag::ON_FRAME_DETACHED:
- return callLocalAsync(data, reply, &IConsumerListener::onFrameDetached);
- }
-}
-
-} // namespace android
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
deleted file mode 100644
index c705d39..0000000
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ /dev/null
@@ -1,230 +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 <gui/IGraphicBufferConsumer.h>
-
-#include <gui/BufferItem.h>
-#include <gui/IConsumerListener.h>
-
-#include <binder/Parcel.h>
-
-#include <ui/Fence.h>
-#include <ui/GraphicBuffer.h>
-
-#include <utils/NativeHandle.h>
-#include <utils/String8.h>
-
-namespace android {
-
-namespace { // Anonymous namespace
-
-enum class Tag : uint32_t {
- ACQUIRE_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
- DETACH_BUFFER,
- ATTACH_BUFFER,
- RELEASE_BUFFER,
- CONSUMER_CONNECT,
- CONSUMER_DISCONNECT,
- GET_RELEASED_BUFFERS,
- SET_DEFAULT_BUFFER_SIZE,
- SET_MAX_BUFFER_COUNT,
- SET_MAX_ACQUIRED_BUFFER_COUNT,
- SET_CONSUMER_NAME,
- SET_DEFAULT_BUFFER_FORMAT,
- SET_DEFAULT_BUFFER_DATA_SPACE,
- SET_CONSUMER_USAGE_BITS,
- SET_CONSUMER_IS_PROTECTED,
- SET_TRANSFORM_HINT,
- GET_SIDEBAND_STREAM,
- GET_OCCUPANCY_HISTORY,
- DISCARD_FREE_BUFFERS,
- DUMP_STATE,
- LAST = DUMP_STATE,
-};
-
-} // Anonymous namespace
-
-class BpGraphicBufferConsumer : public SafeBpInterface<IGraphicBufferConsumer> {
-public:
- explicit BpGraphicBufferConsumer(const sp<IBinder>& impl)
- : SafeBpInterface<IGraphicBufferConsumer>(impl, "BpGraphicBufferConsumer") {}
-
- ~BpGraphicBufferConsumer() override;
-
- status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen,
- uint64_t maxFrameNumber) override {
- using Signature = decltype(&IGraphicBufferConsumer::acquireBuffer);
- return callRemote<Signature>(Tag::ACQUIRE_BUFFER, buffer, presentWhen, maxFrameNumber);
- }
-
- status_t detachBuffer(int slot) override {
- using Signature = decltype(&IGraphicBufferConsumer::detachBuffer);
- return callRemote<Signature>(Tag::DETACH_BUFFER, slot);
- }
-
- status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer) override {
- using Signature = decltype(&IGraphicBufferConsumer::attachBuffer);
- return callRemote<Signature>(Tag::ATTACH_BUFFER, slot, buffer);
- }
-
- status_t releaseBuffer(int buf, uint64_t frameNumber,
- EGLDisplay display __attribute__((unused)),
- EGLSyncKHR fence __attribute__((unused)),
- const sp<Fence>& releaseFence) override {
- return callRemote<ReleaseBuffer>(Tag::RELEASE_BUFFER, buf, frameNumber, releaseFence);
- }
-
- status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) override {
- using Signature = decltype(&IGraphicBufferConsumer::consumerConnect);
- return callRemote<Signature>(Tag::CONSUMER_CONNECT, consumer, controlledByApp);
- }
-
- status_t consumerDisconnect() override {
- return callRemote<decltype(&IGraphicBufferConsumer::consumerDisconnect)>(
- Tag::CONSUMER_DISCONNECT);
- }
-
- status_t getReleasedBuffers(uint64_t* slotMask) override {
- using Signature = decltype(&IGraphicBufferConsumer::getReleasedBuffers);
- return callRemote<Signature>(Tag::GET_RELEASED_BUFFERS, slotMask);
- }
-
- status_t setDefaultBufferSize(uint32_t width, uint32_t height) override {
- using Signature = decltype(&IGraphicBufferConsumer::setDefaultBufferSize);
- return callRemote<Signature>(Tag::SET_DEFAULT_BUFFER_SIZE, width, height);
- }
-
- status_t setMaxBufferCount(int bufferCount) override {
- using Signature = decltype(&IGraphicBufferConsumer::setMaxBufferCount);
- return callRemote<Signature>(Tag::SET_MAX_BUFFER_COUNT, bufferCount);
- }
-
- status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) override {
- using Signature = decltype(&IGraphicBufferConsumer::setMaxAcquiredBufferCount);
- return callRemote<Signature>(Tag::SET_MAX_ACQUIRED_BUFFER_COUNT, maxAcquiredBuffers);
- }
-
- status_t setConsumerName(const String8& name) override {
- using Signature = decltype(&IGraphicBufferConsumer::setConsumerName);
- return callRemote<Signature>(Tag::SET_CONSUMER_NAME, name);
- }
-
- status_t setDefaultBufferFormat(PixelFormat defaultFormat) override {
- using Signature = decltype(&IGraphicBufferConsumer::setDefaultBufferFormat);
- return callRemote<Signature>(Tag::SET_DEFAULT_BUFFER_FORMAT, defaultFormat);
- }
-
- status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace) override {
- using Signature = decltype(&IGraphicBufferConsumer::setDefaultBufferDataSpace);
- return callRemote<Signature>(Tag::SET_DEFAULT_BUFFER_DATA_SPACE, defaultDataSpace);
- }
-
- status_t setConsumerUsageBits(uint64_t usage) override {
- using Signature = decltype(&IGraphicBufferConsumer::setConsumerUsageBits);
- return callRemote<Signature>(Tag::SET_CONSUMER_USAGE_BITS, usage);
- }
-
- status_t setConsumerIsProtected(bool isProtected) override {
- using Signature = decltype(&IGraphicBufferConsumer::setConsumerIsProtected);
- return callRemote<Signature>(Tag::SET_CONSUMER_IS_PROTECTED, isProtected);
- }
-
- status_t setTransformHint(uint32_t hint) override {
- using Signature = decltype(&IGraphicBufferConsumer::setTransformHint);
- return callRemote<Signature>(Tag::SET_TRANSFORM_HINT, hint);
- }
-
- status_t getSidebandStream(sp<NativeHandle>* outStream) const override {
- using Signature = decltype(&IGraphicBufferConsumer::getSidebandStream);
- return callRemote<Signature>(Tag::GET_SIDEBAND_STREAM, outStream);
- }
-
- status_t getOccupancyHistory(bool forceFlush,
- std::vector<OccupancyTracker::Segment>* outHistory) override {
- using Signature = decltype(&IGraphicBufferConsumer::getOccupancyHistory);
- return callRemote<Signature>(Tag::GET_OCCUPANCY_HISTORY, forceFlush, outHistory);
- }
-
- status_t discardFreeBuffers() override {
- return callRemote<decltype(&IGraphicBufferConsumer::discardFreeBuffers)>(
- Tag::DISCARD_FREE_BUFFERS);
- }
-
- status_t dumpState(const String8& prefix, String8* outResult) const override {
- using Signature = status_t (IGraphicBufferConsumer::*)(const String8&, String8*) const;
- return callRemote<Signature>(Tag::DUMP_STATE, prefix, outResult);
- }
-};
-
-// Out-of-line virtual method definition to trigger vtable emission in this translation unit
-// (see clang warning -Wweak-vtables)
-BpGraphicBufferConsumer::~BpGraphicBufferConsumer() = default;
-
-IMPLEMENT_META_INTERFACE(GraphicBufferConsumer, "android.gui.IGraphicBufferConsumer");
-
-status_t BnGraphicBufferConsumer::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
- uint32_t flags) {
- if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast<uint32_t>(Tag::LAST)) {
- return BBinder::onTransact(code, data, reply, flags);
- }
- auto tag = static_cast<Tag>(code);
- switch (tag) {
- case Tag::ACQUIRE_BUFFER:
- return callLocal(data, reply, &IGraphicBufferConsumer::acquireBuffer);
- case Tag::DETACH_BUFFER:
- return callLocal(data, reply, &IGraphicBufferConsumer::detachBuffer);
- case Tag::ATTACH_BUFFER:
- return callLocal(data, reply, &IGraphicBufferConsumer::attachBuffer);
- case Tag::RELEASE_BUFFER:
- return callLocal(data, reply, &IGraphicBufferConsumer::releaseHelper);
- case Tag::CONSUMER_CONNECT:
- return callLocal(data, reply, &IGraphicBufferConsumer::consumerConnect);
- case Tag::CONSUMER_DISCONNECT:
- return callLocal(data, reply, &IGraphicBufferConsumer::consumerDisconnect);
- case Tag::GET_RELEASED_BUFFERS:
- return callLocal(data, reply, &IGraphicBufferConsumer::getReleasedBuffers);
- case Tag::SET_DEFAULT_BUFFER_SIZE:
- return callLocal(data, reply, &IGraphicBufferConsumer::setDefaultBufferSize);
- case Tag::SET_MAX_BUFFER_COUNT:
- return callLocal(data, reply, &IGraphicBufferConsumer::setMaxBufferCount);
- case Tag::SET_MAX_ACQUIRED_BUFFER_COUNT:
- return callLocal(data, reply, &IGraphicBufferConsumer::setMaxAcquiredBufferCount);
- case Tag::SET_CONSUMER_NAME:
- return callLocal(data, reply, &IGraphicBufferConsumer::setConsumerName);
- case Tag::SET_DEFAULT_BUFFER_FORMAT:
- return callLocal(data, reply, &IGraphicBufferConsumer::setDefaultBufferFormat);
- case Tag::SET_DEFAULT_BUFFER_DATA_SPACE:
- return callLocal(data, reply, &IGraphicBufferConsumer::setDefaultBufferDataSpace);
- case Tag::SET_CONSUMER_USAGE_BITS:
- return callLocal(data, reply, &IGraphicBufferConsumer::setConsumerUsageBits);
- case Tag::SET_CONSUMER_IS_PROTECTED:
- return callLocal(data, reply, &IGraphicBufferConsumer::setConsumerIsProtected);
- case Tag::SET_TRANSFORM_HINT:
- return callLocal(data, reply, &IGraphicBufferConsumer::setTransformHint);
- case Tag::GET_SIDEBAND_STREAM:
- return callLocal(data, reply, &IGraphicBufferConsumer::getSidebandStream);
- case Tag::GET_OCCUPANCY_HISTORY:
- return callLocal(data, reply, &IGraphicBufferConsumer::getOccupancyHistory);
- case Tag::DISCARD_FREE_BUFFERS:
- return callLocal(data, reply, &IGraphicBufferConsumer::discardFreeBuffers);
- case Tag::DUMP_STATE: {
- using Signature = status_t (IGraphicBufferConsumer::*)(const String8&, String8*) const;
- return callLocal<Signature>(data, reply, &IGraphicBufferConsumer::dumpState);
- }
- }
-}
-
-} // namespace android
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 0914480..1d1910e 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -81,6 +81,7 @@
GET_LAST_QUEUED_BUFFER2,
SET_FRAME_RATE,
SET_ADDITIONAL_OPTIONS,
+ SET_MAX_BUFER_COUNT_EXTENDED,
};
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
@@ -103,7 +104,7 @@
}
bool nonNull = reply.readInt32();
if (nonNull) {
- *buf = new GraphicBuffer();
+ *buf = sp<GraphicBuffer>::make();
result = reply.read(**buf);
if(result != NO_ERROR) {
(*buf).clear();
@@ -149,6 +150,20 @@
return result;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ status_t extendSlotCount(int size) override {
+ Parcel data, reply;
+ data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+ data.writeInt32(size);
+ status_t result = remote()->transact(SET_MAX_BUFER_COUNT_EXTENDED, data, &reply);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ result = reply.readInt32();
+ return result;
+ }
+#endif
+
virtual status_t setAsyncMode(bool async) {
Parcel data, reply;
data.writeInterfaceToken(
@@ -182,7 +197,7 @@
}
*buf = reply.readInt32();
- *fence = new Fence();
+ *fence = sp<Fence>::make();
result = reply.read(**fence);
if (result != NO_ERROR) {
fence->clear();
@@ -278,7 +293,7 @@
if (result == NO_ERROR) {
bool nonNull = reply.readInt32();
if (nonNull) {
- *outBuffer = new GraphicBuffer;
+ *outBuffer = sp<GraphicBuffer>::make();
result = reply.read(**outBuffer);
if (result != NO_ERROR) {
outBuffer->clear();
@@ -287,7 +302,7 @@
}
nonNull = reply.readInt32();
if (nonNull) {
- *outFence = new Fence;
+ *outFence = sp<Fence>::make();
result = reply.read(**outFence);
if (result != NO_ERROR) {
outBuffer->clear();
@@ -625,7 +640,7 @@
bool hasBuffer = reply.readBool();
sp<GraphicBuffer> buffer;
if (hasBuffer) {
- buffer = new GraphicBuffer();
+ buffer = sp<GraphicBuffer>::make();
result = reply.read(*buffer);
if (result == NO_ERROR) {
result = reply.read(outTransformMatrix, sizeof(float) * 16);
@@ -635,7 +650,7 @@
ALOGE("getLastQueuedBuffer failed to read buffer: %d", result);
return result;
}
- sp<Fence> fence(new Fence);
+ sp<Fence> fence = sp<Fence>::make();
result = reply.read(*fence);
if (result != NO_ERROR) {
ALOGE("getLastQueuedBuffer failed to read fence: %d", result);
@@ -672,7 +687,7 @@
}
sp<GraphicBuffer> buffer;
if (hasBuffer) {
- buffer = new GraphicBuffer();
+ buffer = sp<GraphicBuffer>::make();
result = reply.read(*buffer);
if (result == NO_ERROR) {
result = reply.read(*outRect);
@@ -685,7 +700,7 @@
ALOGE("getLastQueuedBuffer failed to read buffer: %d", result);
return result;
}
- sp<Fence> fence(new Fence);
+ sp<Fence> fence = sp<Fence>::make();
result = reply.read(*fence);
if (result != NO_ERROR) {
ALOGE("getLastQueuedBuffer failed to read fence: %d", result);
@@ -981,6 +996,14 @@
// ----------------------------------------------------------------------
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+status_t IGraphicBufferProducer::extendSlotCount(int size) {
+ // No-op for IGBP other than BufferQueue.
+ (void)size;
+ return INVALID_OPERATION;
+}
+#endif
+
status_t IGraphicBufferProducer::setLegacyBufferDrop(bool drop) {
// No-op for IGBP other than BufferQueue.
(void) drop;
@@ -1209,7 +1232,7 @@
}
case ATTACH_BUFFER: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- sp<GraphicBuffer> buffer = new GraphicBuffer();
+ sp<GraphicBuffer> buffer = sp<GraphicBuffer>::make();
status_t result = data.read(*buffer.get());
int slot = 0;
if (result == NO_ERROR) {
@@ -1227,7 +1250,7 @@
return result;
}
for (sp<GraphicBuffer>& buffer : buffers) {
- buffer = new GraphicBuffer();
+ buffer = sp<GraphicBuffer>::make();
result = data.read(*buffer.get());
if (result != NO_ERROR) {
return result;
@@ -1283,7 +1306,7 @@
case CANCEL_BUFFER: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
int buf = data.readInt32();
- sp<Fence> fence = new Fence();
+ sp<Fence> fence = sp<Fence>::make();
status_t result = data.read(*fence.get());
if (result == NO_ERROR) {
result = cancelBuffer(buf, fence);
@@ -1582,6 +1605,15 @@
return NO_ERROR;
}
#endif
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ case SET_MAX_BUFER_COUNT_EXTENDED: {
+ CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+ int size = data.readInt32();
+ status_t result = extendSlotCount(size);
+ reply->writeInt32(result);
+ return NO_ERROR;
+ }
+#endif
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/IGraphicBufferProducerFlattenables.cpp b/libs/gui/IGraphicBufferProducerFlattenables.cpp
index c8b9b67..393e1c3 100644
--- a/libs/gui/IGraphicBufferProducerFlattenables.cpp
+++ b/libs/gui/IGraphicBufferProducerFlattenables.cpp
@@ -20,21 +20,19 @@
namespace android {
constexpr size_t IGraphicBufferProducer::QueueBufferInput::minFlattenedSize() {
- return sizeof(timestamp) +
- sizeof(isAutoTimestamp) +
- sizeof(dataSpace) +
- sizeof(crop) +
- sizeof(scalingMode) +
- sizeof(transform) +
- sizeof(stickyTransform) +
- sizeof(getFrameTimestamps) +
- sizeof(slot);
+ return sizeof(timestamp) + sizeof(isAutoTimestamp) + sizeof(dataSpace) + sizeof(crop) +
+ sizeof(scalingMode) + sizeof(transform) + sizeof(stickyTransform) +
+ sizeof(getFrameTimestamps) + sizeof(slot) +
+#if COM_ANDROID_GRAPHICS_LIBUI_FLAGS_APPLY_PICTURE_PROFILES
+ sizeof(decltype(pictureProfileHandle.has_value())) +
+ sizeof(decltype(pictureProfileHandle.getId()));
+#else
+ 0;
+#endif // COM_ANDROID_GRAPHICS_LIBUI_FLAGS_APPLY_PICTURE_PROFILES
}
size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const {
- return minFlattenedSize() +
- fence->getFlattenedSize() +
- surfaceDamage.getFlattenedSize() +
+ return minFlattenedSize() + fence->getFlattenedSize() + surfaceDamage.getFlattenedSize() +
hdrMetadata.getFlattenedSize();
}
@@ -57,6 +55,12 @@
FlattenableUtils::write(buffer, size, transform);
FlattenableUtils::write(buffer, size, stickyTransform);
FlattenableUtils::write(buffer, size, getFrameTimestamps);
+#if COM_ANDROID_GRAPHICS_LIBUI_FLAGS_APPLY_PICTURE_PROFILES
+ FlattenableUtils::write(buffer, size, pictureProfileHandle.has_value());
+ FlattenableUtils::write(buffer, size,
+ pictureProfileHandle.has_value() ? pictureProfileHandle->getId()
+ : PictureProfileHandle::NONE.getId());
+#endif // COM_ANDROID_GRAPHICS_LIBUI_FLAGS_APPLY_PICTURE_PROFILES
status_t result = fence->flatten(buffer, size, fds, count);
if (result != NO_ERROR) {
@@ -91,8 +95,17 @@
FlattenableUtils::read(buffer, size, transform);
FlattenableUtils::read(buffer, size, stickyTransform);
FlattenableUtils::read(buffer, size, getFrameTimestamps);
+#if COM_ANDROID_GRAPHICS_LIBUI_FLAGS_APPLY_PICTURE_PROFILES
+ bool hasPictureProfileHandle;
+ FlattenableUtils::read(buffer, size, hasPictureProfileHandle);
+ PictureProfileId pictureProfileId;
+ FlattenableUtils::read(buffer, size, pictureProfileId);
+ pictureProfileHandle = hasPictureProfileHandle
+ ? std::optional(PictureProfileHandle(pictureProfileId))
+ : std::nullopt;
+#endif // COM_ANDROID_GRAPHICS_LIBUI_FLAGS_APPLY_PICTURE_PROFILES
- fence = new Fence();
+ fence = sp<Fence>::make();
status_t result = fence->unflatten(buffer, size, fds, count);
if (result != NO_ERROR) {
return result;
@@ -115,7 +128,7 @@
constexpr size_t IGraphicBufferProducer::QueueBufferOutput::minFlattenedSize() {
return sizeof(width) + sizeof(height) + sizeof(transformHint) + sizeof(numPendingBuffers) +
sizeof(nextFrameNumber) + sizeof(bufferReplaced) + sizeof(maxBufferCount) +
- sizeof(result);
+ sizeof(result) + sizeof(isSlotExpansionAllowed);
}
size_t IGraphicBufferProducer::QueueBufferOutput::getFlattenedSize() const {
return minFlattenedSize() + frameTimestamps.getFlattenedSize();
@@ -139,6 +152,7 @@
FlattenableUtils::write(buffer, size, nextFrameNumber);
FlattenableUtils::write(buffer, size, bufferReplaced);
FlattenableUtils::write(buffer, size, maxBufferCount);
+ FlattenableUtils::write(buffer, size, isSlotExpansionAllowed);
status_t result = frameTimestamps.flatten(buffer, size, fds, count);
if (result != NO_ERROR) {
@@ -162,6 +176,7 @@
FlattenableUtils::read(buffer, size, nextFrameNumber);
FlattenableUtils::read(buffer, size, bufferReplaced);
FlattenableUtils::read(buffer, size, maxBufferCount);
+ FlattenableUtils::read(buffer, size, isSlotExpansionAllowed);
status_t result = frameTimestamps.unflatten(buffer, size, fds, count);
if (result != NO_ERROR) {
@@ -213,7 +228,7 @@
FlattenableUtils::read(fBuffer, size, result);
int32_t isBufferNull = 0;
FlattenableUtils::read(fBuffer, size, isBufferNull);
- buffer = new GraphicBuffer();
+ buffer = sp<GraphicBuffer>::make();
if (!isBufferNull) {
status_t status = buffer->unflatten(fBuffer, size, fds, count);
if (status != NO_ERROR) {
@@ -308,7 +323,7 @@
FlattenableUtils::read(buffer, size, slot);
FlattenableUtils::read(buffer, size, bufferAge);
- fence = new Fence();
+ fence = sp<Fence>::make();
status_t status = fence->unflatten(buffer, size, fds, count);
if (status != NO_ERROR) {
return status;
@@ -380,7 +395,7 @@
FlattenableUtils::read(buffer, size, slot);
- fence = new Fence();
+ fence = sp<Fence>::make();
return fence->unflatten(buffer, size, fds, count);
}
diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp
index 83fc827..ed28e79 100644
--- a/libs/gui/ITransactionCompletedListener.cpp
+++ b/libs/gui/ITransactionCompletedListener.cpp
@@ -92,7 +92,7 @@
if (err != NO_ERROR) return err;
if (hasFence) {
- gpuCompositionDoneFence = new Fence();
+ gpuCompositionDoneFence = sp<Fence>::make();
err = input->read(*gpuCompositionDoneFence);
if (err != NO_ERROR) return err;
}
@@ -157,7 +157,7 @@
SAFE_PARCEL(input->readBool, &hasFence);
if (hasFence) {
- previousReleaseFence = new Fence();
+ previousReleaseFence = sp<Fence>::make();
SAFE_PARCEL(input->read, *previousReleaseFence);
}
bool hasTransformHint = false;
@@ -216,7 +216,7 @@
return err;
}
if (hasFence) {
- presentFence = new Fence();
+ presentFence = sp<Fence>::make();
err = input->read(*presentFence);
if (err != NO_ERROR) {
return err;
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 422c57b..43855da 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -21,6 +21,7 @@
#include <android/gui/ISurfaceComposerClient.h>
#include <android/native_window.h>
#include <binder/Parcel.h>
+#include <com_android_graphics_libgui_flags.h>
#include <gui/FrameRateUtils.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/LayerState.h>
@@ -65,6 +66,7 @@
mask(0),
reserved(0),
cornerRadius(0.0f),
+ clientDrawnCornerRadius(0.0f),
backgroundBlurRadius(0),
color(0),
bufferTransform(0),
@@ -91,7 +93,9 @@
trustedOverlay(gui::TrustedOverlay::UNSET),
bufferCrop(Rect::INVALID_RECT),
destinationFrame(Rect::INVALID_RECT),
- dropInputMode(gui::DropInputMode::NONE) {
+ dropInputMode(gui::DropInputMode::NONE),
+ pictureProfileHandle(PictureProfileHandle::NONE),
+ appContentPriority(0) {
matrix.dsdx = matrix.dtdy = 1.0f;
matrix.dsdy = matrix.dtdx = 0.0f;
hdrMetadata.validTypes = 0;
@@ -137,6 +141,7 @@
SAFE_PARCEL(output.write, colorTransform.asArray(), 16 * sizeof(float));
SAFE_PARCEL(output.writeFloat, cornerRadius);
+ SAFE_PARCEL(output.writeFloat, clientDrawnCornerRadius);
SAFE_PARCEL(output.writeUint32, backgroundBlurRadius);
SAFE_PARCEL(output.writeParcelable, metadata);
SAFE_PARCEL(output.writeFloat, bgColor.r);
@@ -202,6 +207,16 @@
if (hasBufferReleaseChannel) {
SAFE_PARCEL(output.writeParcelable, *bufferReleaseChannel);
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS_APPLY_PICTURE_PROFILES
+ SAFE_PARCEL(output.writeInt64, pictureProfileHandle.getId());
+ SAFE_PARCEL(output.writeInt32, appContentPriority);
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS_APPLY_PICTURE_PROFILES
+
+ const bool hasLuts = (luts != nullptr);
+ SAFE_PARCEL(output.writeBool, hasLuts);
+ if (hasLuts) {
+ SAFE_PARCEL(output.writeParcelable, *luts);
+ }
return NO_ERROR;
}
@@ -261,6 +276,7 @@
SAFE_PARCEL(input.read, &colorTransform, 16 * sizeof(float));
SAFE_PARCEL(input.readFloat, &cornerRadius);
+ SAFE_PARCEL(input.readFloat, &clientDrawnCornerRadius);
SAFE_PARCEL(input.readUint32, &backgroundBlurRadius);
SAFE_PARCEL(input.readParcelable, &metadata);
@@ -357,6 +373,21 @@
bufferReleaseChannel = std::make_shared<gui::BufferReleaseChannel::ProducerEndpoint>();
SAFE_PARCEL(input.readParcelable, bufferReleaseChannel.get());
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS_APPLY_PICTURE_PROFILES
+ int64_t pictureProfileId;
+ SAFE_PARCEL(input.readInt64, &pictureProfileId);
+ pictureProfileHandle = PictureProfileHandle(pictureProfileId);
+ SAFE_PARCEL(input.readInt32, &appContentPriority);
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS_APPLY_PICTURE_PROFILES
+
+ bool hasLuts;
+ SAFE_PARCEL(input.readBool, &hasLuts);
+ if (hasLuts) {
+ luts = std::make_shared<gui::DisplayLuts>();
+ SAFE_PARCEL(input.readParcelable, luts.get());
+ } else {
+ luts = nullptr;
+ }
return NO_ERROR;
}
@@ -568,6 +599,10 @@
what |= eCornerRadiusChanged;
cornerRadius = other.cornerRadius;
}
+ if (other.what & eClientDrawnCornerRadiusChanged) {
+ what |= eClientDrawnCornerRadiusChanged;
+ clientDrawnCornerRadius = other.clientDrawnCornerRadius;
+ }
if (other.what & eBackgroundBlurRadiusChanged) {
what |= eBackgroundBlurRadiusChanged;
backgroundBlurRadius = other.backgroundBlurRadius;
@@ -649,7 +684,7 @@
}
if (other.what & eInputInfoChanged) {
what |= eInputInfoChanged;
- windowInfoHandle = new WindowInfoHandle(*other.windowInfoHandle);
+ windowInfoHandle = sp<WindowInfoHandle>::make(*other.windowInfoHandle);
}
if (other.what & eBackgroundColorChanged) {
what |= eBackgroundColorChanged;
@@ -664,6 +699,10 @@
what |= eShadowRadiusChanged;
shadowRadius = other.shadowRadius;
}
+ if (other.what & eLutsChanged) {
+ what |= eLutsChanged;
+ luts = other.luts;
+ }
if (other.what & eDefaultFrameRateCompatibilityChanged) {
what |= eDefaultFrameRateCompatibilityChanged;
defaultFrameRateCompatibility = other.defaultFrameRateCompatibility;
@@ -741,6 +780,16 @@
what |= eBufferReleaseChannelChanged;
bufferReleaseChannel = other.bufferReleaseChannel;
}
+ if (com_android_graphics_libgui_flags_apply_picture_profiles()) {
+ if (other.what & ePictureProfileHandleChanged) {
+ what |= ePictureProfileHandleChanged;
+ pictureProfileHandle = other.pictureProfileHandle;
+ }
+ if (other.what & eAppContentPriorityChanged) {
+ what |= eAppContentPriorityChanged;
+ appContentPriority = other.appContentPriority;
+ }
+ }
if ((other.what & what) != other.what) {
ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
"other.what=0x%" PRIX64 " what=0x%" PRIX64 " unmerged flags=0x%" PRIX64,
@@ -767,6 +816,7 @@
}
CHECK_DIFF(diff, eLayerStackChanged, other, layerStack);
CHECK_DIFF(diff, eCornerRadiusChanged, other, cornerRadius);
+ CHECK_DIFF(diff, eClientDrawnCornerRadiusChanged, other, clientDrawnCornerRadius);
CHECK_DIFF(diff, eBackgroundBlurRadiusChanged, other, backgroundBlurRadius);
if (other.what & eBlurRegionsChanged) diff |= eBlurRegionsChanged;
if (other.what & eRelativeLayerChanged) {
@@ -821,6 +871,10 @@
CHECK_DIFF(diff, eColorSpaceAgnosticChanged, other, colorSpaceAgnostic);
CHECK_DIFF(diff, eDimmingEnabledChanged, other, dimmingEnabled);
if (other.what & eBufferReleaseChannelChanged) diff |= eBufferReleaseChannelChanged;
+ if (other.what & eLutsChanged) diff |= eLutsChanged;
+ CHECK_DIFF(diff, ePictureProfileHandleChanged, other, pictureProfileHandle);
+ CHECK_DIFF(diff, eAppContentPriorityChanged, other, appContentPriority);
+
return diff;
}
@@ -947,13 +1001,13 @@
bool tmpBool = false;
SAFE_PARCEL(input->readBool, &tmpBool);
if (tmpBool) {
- buffer = new GraphicBuffer();
+ buffer = sp<GraphicBuffer>::make();
SAFE_PARCEL(input->read, *buffer);
}
SAFE_PARCEL(input->readBool, &tmpBool);
if (tmpBool) {
- acquireFence = new Fence();
+ acquireFence = sp<Fence>::make();
SAFE_PARCEL(input->read, *acquireFence);
}
diff --git a/libs/gui/ScreenCaptureResults.cpp b/libs/gui/ScreenCaptureResults.cpp
index 2de023e..30b5785 100644
--- a/libs/gui/ScreenCaptureResults.cpp
+++ b/libs/gui/ScreenCaptureResults.cpp
@@ -18,6 +18,7 @@
#include <private/gui/ParcelUtils.h>
#include <ui/FenceResult.h>
+#include <ui/GraphicBuffer.h>
namespace android::gui {
@@ -54,7 +55,7 @@
bool hasGraphicBuffer;
SAFE_PARCEL(parcel->readBool, &hasGraphicBuffer);
if (hasGraphicBuffer) {
- buffer = new GraphicBuffer();
+ buffer = sp<GraphicBuffer>::make();
SAFE_PARCEL(parcel->read, *buffer);
}
@@ -79,7 +80,7 @@
bool hasGainmap;
SAFE_PARCEL(parcel->readBool, &hasGainmap);
if (hasGainmap) {
- optionalGainMap = new GraphicBuffer();
+ optionalGainMap = sp<GraphicBuffer>::make();
SAFE_PARCEL(parcel->read, *optionalGainMap);
}
SAFE_PARCEL(parcel->readFloat, &hdrSdrRatio);
diff --git a/libs/gui/StreamSplitter.cpp b/libs/gui/StreamSplitter.cpp
index 2f8e104..848ae7a 100644
--- a/libs/gui/StreamSplitter.cpp
+++ b/libs/gui/StreamSplitter.cpp
@@ -47,7 +47,7 @@
return BAD_VALUE;
}
- sp<StreamSplitter> splitter(new StreamSplitter(inputQueue));
+ sp<StreamSplitter> splitter = sp<StreamSplitter>::make(inputQueue);
status_t status = splitter->mInput->consumerConnect(splitter, false);
if (status == NO_ERROR) {
splitter->mInput->setConsumerName(String8("StreamSplitter"));
@@ -82,7 +82,7 @@
Mutex::Autolock lock(mMutex);
IGraphicBufferProducer::QueueBufferOutput queueBufferOutput;
- sp<OutputListener> listener(new OutputListener(this, outputQueue));
+ sp<OutputListener> listener = sp<OutputListener>::make(this, outputQueue);
IInterface::asBinder(outputQueue)->linkToDeath(listener);
status_t status = outputQueue->connect(listener, NATIVE_WINDOW_API_CPU,
/* producerControlledByApp */ false, &queueBufferOutput);
@@ -140,7 +140,7 @@
// Initialize our reference count for this buffer
mBuffers.add(bufferItem.mGraphicBuffer->getId(),
- new BufferTracker(bufferItem.mGraphicBuffer));
+ sp<BufferTracker>::make(bufferItem.mGraphicBuffer));
IGraphicBufferProducer::QueueBufferInput queueInput(
bufferItem.mTimestamp, bufferItem.mIsAutoTimestamp,
@@ -234,8 +234,7 @@
LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
"attaching buffer to input failed (%d)", status);
- status = mInput->releaseBuffer(consumerSlot, /* frameNumber */ 0,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, tracker->getMergedFence());
+ status = mInput->releaseBuffer(consumerSlot, /* frameNumber */ 0, tracker->getMergedFence());
LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
"releasing buffer to input failed (%d)", status);
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 66e7ddd..63dcfbc 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -38,6 +38,7 @@
#include <utils/NativeHandle.h>
#include <utils/Trace.h>
+#include <ui/BufferQueueDefs.h>
#include <ui/DynamicDisplayInfo.h>
#include <ui/Fence.h>
#include <ui/GraphicBuffer.h>
@@ -98,7 +99,10 @@
: mGraphicBufferProducer(bufferProducer),
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
mSurfaceDeathListener(nullptr),
-#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+#endif
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ mSlots(NUM_BUFFER_SLOTS),
+#endif
mCrop(Rect::EMPTY_RECT),
mBufferAge(0),
mGenerationNumber(0),
@@ -192,7 +196,7 @@
status_t Surface::allowAllocation(bool allowAllocation) {
return mGraphicBufferProducer->allowAllocation(allowAllocation);
}
-#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+#endif
status_t Surface::setGenerationNumber(uint32_t generation) {
status_t result = mGraphicBufferProducer->setGenerationNumber(generation);
@@ -505,7 +509,7 @@
if (result != OK) {
return result;
}
- sp<Fence> fence(new Fence(fenceFd));
+ sp<Fence> fence = sp<Fence>::make(fenceFd);
int waitResult = fence->waitForever("dequeueBuffer_DEPRECATED");
if (waitResult != OK) {
ALOGE("dequeueBuffer_DEPRECATED: Fence::wait returned an error: %d",
@@ -658,7 +662,11 @@
return result;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ if (buf < 0 || buf >= (int)mSlots.size()) {
+#else
if (buf < 0 || buf >= NUM_BUFFER_SLOTS) {
+#endif
ALOGE("dequeueBuffer: IGraphicBufferProducer returned invalid slot number %d", buf);
android_errorWriteLog(0x534e4554, "36991414"); // SafetyNet logging
return FAILED_TRANSACTION;
@@ -757,7 +765,11 @@
Mutex::Autolock lock(mMutex);
uint64_t bufferId = buffer->getId();
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ for (int slot = 0; slot < (int)mSlots.size(); ++slot) {
+#else
for (int slot = 0; slot < Surface::NUM_BUFFER_SLOTS; ++slot) {
+#endif
auto& bufferSlot = mSlots[slot];
if (bufferSlot.buffer != nullptr && bufferSlot.buffer->getId() == bufferId) {
bufferSlot.buffer = nullptr;
@@ -840,7 +852,11 @@
return output.result;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ if (output.slot < 0 || output.slot >= (int)mSlots.size()) {
+#else
if (output.slot < 0 || output.slot >= NUM_BUFFER_SLOTS) {
+#endif
mGraphicBufferProducer->cancelBuffers(cancelBufferInputs, &cancelBufferOutputs);
ALOGE("%s: IGraphicBufferProducer returned invalid slot number %d",
__FUNCTION__, output.slot);
@@ -963,7 +979,7 @@
}
return OK;
}
- sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
+ sp<Fence> fence(fenceFd >= 0 ? sp<Fence>::make(fenceFd) : Fence::NO_FENCE);
mGraphicBufferProducer->cancelBuffer(i, fence);
if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot == i) {
@@ -1001,7 +1017,7 @@
ALOGE("%s: cannot find slot number for cancelled buffer", __FUNCTION__);
badSlotResult = slot;
} else {
- sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
+ sp<Fence> fence(fenceFd >= 0 ? sp<Fence>::make(fenceFd) : Fence::NO_FENCE);
cancelBufferInputs[numBuffersCancelled].slot = slot;
cancelBufferInputs[numBuffersCancelled++].fence = fence;
}
@@ -1027,7 +1043,11 @@
return BAD_VALUE;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ for (int i = 0; i < (int)mSlots.size(); i++) {
+#else
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+#endif
if (mSlots[i].buffer != nullptr &&
mSlots[i].buffer->handle == buffer->handle) {
return i;
@@ -1058,7 +1078,7 @@
Rect crop(Rect::EMPTY_RECT);
mCrop.intersect(Rect(buffer->width, buffer->height), &crop);
- sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
+ sp<Fence> fence(fenceFd >= 0 ? sp<Fence>::make(fenceFd) : Fence::NO_FENCE);
IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
static_cast<android_dataspace>(mDataSpace), crop, mScalingMode,
mTransform ^ mStickyTransform, fence, mStickyTransform,
@@ -2072,7 +2092,7 @@
}
int Surface::connect(int api) {
- static sp<SurfaceListener> listener = new StubSurfaceListener();
+ static sp<SurfaceListener> listener = sp<StubSurfaceListener>::make();
return connect(api, listener);
}
@@ -2084,7 +2104,7 @@
mReportRemovedBuffers = reportBufferRemoval;
if (listener != nullptr) {
- mListenerProxy = new ProducerListenerProxy(this, listener);
+ mListenerProxy = sp<ProducerListenerProxy>::make(this, listener);
}
int err =
@@ -2094,6 +2114,9 @@
mDefaultHeight = output.height;
mNextFrameNumber = output.nextFrameNumber;
mMaxBufferCount = output.maxBufferCount;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ mIsSlotExpansionAllowed = output.isSlotExpansionAllowed;
+#endif
// Ignore transform hint if sticky transform is set or transform to display inverse flag is
// set. Transform hint should be ignored if the client is expected to always submit buffers
@@ -2190,7 +2213,11 @@
*outFence = Fence::NO_FENCE;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ for (int i = 0; i < (int)mSlots.size(); i++) {
+#else
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+#endif
if (mSlots[i].buffer != nullptr &&
mSlots[i].buffer->getId() == buffer->getId()) {
if (mReportRemovedBuffers) {
@@ -2292,8 +2319,35 @@
ALOGV("Surface::setMaxDequeuedBufferCount");
Mutex::Autolock lock(mMutex);
- status_t err = mGraphicBufferProducer->setMaxDequeuedBufferCount(
- maxDequeuedBuffers);
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ if (maxDequeuedBuffers > BufferQueueDefs::NUM_BUFFER_SLOTS && !mIsSlotExpansionAllowed) {
+ return BAD_VALUE;
+ }
+
+ int minUndequeuedBuffers = 0;
+ status_t err = mGraphicBufferProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+ &minUndequeuedBuffers);
+ if (err != OK) {
+ ALOGE("IGraphicBufferProducer::query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS) returned %s",
+ strerror(-err));
+ return err;
+ }
+
+ if (maxDequeuedBuffers > (int)mSlots.size()) {
+ int newSlotCount = minUndequeuedBuffers + maxDequeuedBuffers;
+ err = mGraphicBufferProducer->extendSlotCount(newSlotCount);
+ if (err != OK) {
+ ALOGE("IGraphicBufferProducer::extendSlotCount(%d) returned %s", newSlotCount,
+ strerror(-err));
+ return err;
+ }
+
+ mSlots.resize(newSlotCount);
+ }
+ err = mGraphicBufferProducer->setMaxDequeuedBufferCount(maxDequeuedBuffers);
+#else
+ status_t err = mGraphicBufferProducer->setMaxDequeuedBufferCount(maxDequeuedBuffers);
+#endif
ALOGE_IF(err, "IGraphicBufferProducer::setMaxDequeuedBufferCount(%d) "
"returned %s", maxDequeuedBuffers, strerror(-err));
@@ -2501,7 +2555,11 @@
ALOGE("%s: %zu buffers were freed while being dequeued!",
__FUNCTION__, mDequeuedSlots.size());
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ for (int i = 0; i < (int)mSlots.size(); i++) {
+#else
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+#endif
mSlots[i].buffer = nullptr;
}
}
@@ -2510,7 +2568,11 @@
std::vector<sp<GraphicBuffer>>* outBuffers) {
ALOGV("Surface::getAndFlushBuffersFromSlots");
for (int32_t i : slots) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ if (i < 0 || i >= (int)mSlots.size()) {
+#else
if (i < 0 || i >= NUM_BUFFER_SLOTS) {
+#endif
ALOGE("%s: Invalid slotIndex: %d", __FUNCTION__, i);
return BAD_VALUE;
}
@@ -2670,7 +2732,11 @@
newDirtyRegion.set(bounds);
mDirtyRegion.clear();
Mutex::Autolock lock(mMutex);
- for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ for (int i = 0; i < (int)mSlots.size(); i++) {
+#else
+ for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+#endif
mSlots[i].dirtyRegion.clear();
}
}
@@ -2735,8 +2801,8 @@
bool Surface::waitForNextFrame(uint64_t lastFrame, nsecs_t timeout) {
Mutex::Autolock lock(mMutex);
- if (mNextFrameNumber > lastFrame) {
- return true;
+ if (mLastFrameNumber > lastFrame) {
+ return true;
}
return mQueueBufferCondition.waitRelative(mMutex, timeout) == OK;
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index eeea80f..bb7184f 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -19,8 +19,7 @@
#include <semaphore.h>
#include <stdint.h>
#include <sys/types.h>
-
-#include <com_android_graphics_libgui_flags.h>
+#include <algorithm>
#include <android/gui/BnWindowInfosReportedListener.h>
#include <android/gui/DisplayState.h>
@@ -29,6 +28,8 @@
#include <android/gui/IWindowInfosListener.h>
#include <android/gui/TrustedPresentationThresholds.h>
#include <android/os/IInputConstants.h>
+#include <com_android_graphics_libgui_flags.h>
+#include <gui/DisplayLuts.h>
#include <gui/FrameRateUtils.h>
#include <gui/TraceUtils.h>
#include <utils/Errors.h>
@@ -56,6 +57,7 @@
#include <ui/DisplayMode.h>
#include <ui/DisplayState.h>
#include <ui/DynamicDisplayInfo.h>
+#include <ui/FrameRateCategoryRate.h>
#include <android-base/thread_annotations.h>
#include <gui/LayerStatePermissions.h>
@@ -90,6 +92,7 @@
}
constexpr int64_t INVALID_VSYNC = -1;
+const constexpr char* LOG_SURFACE_CONTROL_REGISTRY = "SurfaceControlRegistry";
} // namespace
@@ -120,7 +123,7 @@
explicit DeathObserver(ComposerService& mgr) : mComposerService(mgr) { }
};
- mDeathObserver = new DeathObserver(*const_cast<ComposerService*>(this));
+ mDeathObserver = sp<DeathObserver>::make(*const_cast<ComposerService*>(this));
IInterface::asBinder(mComposerService)->linkToDeath(mDeathObserver);
return true;
}
@@ -167,7 +170,7 @@
explicit DeathObserver(ComposerServiceAIDL& mgr) : mComposerService(mgr) {}
};
- mDeathObserver = new DeathObserver(*const_cast<ComposerServiceAIDL*>(this));
+ mDeathObserver = sp<DeathObserver>::make(*const_cast<ComposerServiceAIDL*>(this));
IInterface::asBinder(mComposerService)->linkToDeath(mDeathObserver);
return true;
}
@@ -199,7 +202,7 @@
DefaultComposerClient& dc = DefaultComposerClient::getInstance();
Mutex::Autolock _l(dc.mLock);
if (dc.mClient == nullptr) {
- dc.mClient = new SurfaceComposerClient;
+ dc.mClient = sp<SurfaceComposerClient>::make();
}
return dc.mClient;
}
@@ -396,7 +399,7 @@
sp<TransactionCompletedListener> TransactionCompletedListener::getInstance() {
std::lock_guard<std::mutex> lock(sListenerInstanceMutex);
if (sInstance == nullptr) {
- sInstance = new TransactionCompletedListener;
+ sInstance = sp<TransactionCompletedListener>::make();
}
return sInstance;
}
@@ -688,7 +691,7 @@
std::scoped_lock<std::mutex> lock(mMutex);
mTrustedPresentationCallbacks[id] =
std::tuple<TrustedPresentationCallback, void*>(tpc, context);
- return new SurfaceComposerClient::PresentationCallbackRAII(this, id);
+ return sp<SurfaceComposerClient::PresentationCallbackRAII>::make(this, id);
}
void TransactionCompletedListener::clearTrustedPresentationCallback(int id) {
@@ -740,7 +743,7 @@
*/
class BufferCache : public Singleton<BufferCache> {
public:
- BufferCache() : token(new BBinder()) {}
+ BufferCache() : token(sp<BBinder>::make()) {}
sp<IBinder> getToken() {
return IInterface::asBinder(TransactionCompletedListener::getIInstance());
@@ -827,9 +830,7 @@
SurfaceComposerClient::Transaction::Transaction(const Transaction& other)
: mId(other.mId),
- mAnimation(other.mAnimation),
- mEarlyWakeupStart(other.mEarlyWakeupStart),
- mEarlyWakeupEnd(other.mEarlyWakeupEnd),
+ mFlags(other.mFlags),
mMayContainBuffer(other.mMayContainBuffer),
mDesiredPresentTime(other.mDesiredPresentTime),
mIsAutoTimestamp(other.mIsAutoTimestamp),
@@ -844,7 +845,7 @@
void SurfaceComposerClient::Transaction::sanitize(int pid, int uid) {
uint32_t permissions = LayerStatePermissions::getTransactionPermissions(pid, uid);
- for (auto & [handle, composerState] : mComposerStates) {
+ for (auto& composerState : mComposerStates) {
composerState.state.sanitize(permissions);
}
if (!mInputWindowCommands.empty() &&
@@ -866,11 +867,10 @@
status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel) {
const uint64_t transactionId = parcel->readUint64();
- const bool animation = parcel->readBool();
- const bool earlyWakeupStart = parcel->readBool();
- const bool earlyWakeupEnd = parcel->readBool();
+ const uint32_t flags = parcel->readUint32();
const int64_t desiredPresentTime = parcel->readInt64();
const bool isAutoTimestamp = parcel->readBool();
+ const bool logCallPoints = parcel->readBool();
FrameTimelineInfo frameTimelineInfo;
frameTimelineInfo.readFromParcel(parcel);
@@ -880,7 +880,7 @@
if (count > parcel->dataSize()) {
return BAD_VALUE;
}
- SortedVector<DisplayState> displayStates;
+ Vector<DisplayState> displayStates;
displayStates.setCapacity(count);
for (size_t i = 0; i < count; i++) {
DisplayState displayState;
@@ -923,17 +923,14 @@
if (count > parcel->dataSize()) {
return BAD_VALUE;
}
- std::unordered_map<sp<IBinder>, ComposerState, IBinderHash> composerStates;
- composerStates.reserve(count);
+ Vector<ComposerState> composerStates;
+ composerStates.setCapacity(count);
for (size_t i = 0; i < count; i++) {
- sp<IBinder> surfaceControlHandle;
- SAFE_PARCEL(parcel->readStrongBinder, &surfaceControlHandle);
-
ComposerState composerState;
if (composerState.read(*parcel) == BAD_VALUE) {
return BAD_VALUE;
}
- composerStates[surfaceControlHandle] = composerState;
+ composerStates.add(composerState);
}
InputWindowCommands inputWindowCommands;
@@ -962,15 +959,13 @@
// Parsing was successful. Update the object.
mId = transactionId;
- mAnimation = animation;
- mEarlyWakeupStart = earlyWakeupStart;
- mEarlyWakeupEnd = earlyWakeupEnd;
+ mFlags = flags;
mDesiredPresentTime = desiredPresentTime;
mIsAutoTimestamp = isAutoTimestamp;
mFrameTimelineInfo = frameTimelineInfo;
- mDisplayStates = displayStates;
+ mDisplayStates = std::move(displayStates);
mListenerCallbacks = listenerCallbacks;
- mComposerStates = composerStates;
+ mComposerStates = std::move(composerStates);
mInputWindowCommands = inputWindowCommands;
mApplyToken = applyToken;
mUncacheBuffers = std::move(uncacheBuffers);
@@ -993,11 +988,10 @@
const_cast<SurfaceComposerClient::Transaction*>(this)->cacheBuffers();
parcel->writeUint64(mId);
- parcel->writeBool(mAnimation);
- parcel->writeBool(mEarlyWakeupStart);
- parcel->writeBool(mEarlyWakeupEnd);
+ parcel->writeUint32(mFlags);
parcel->writeInt64(mDesiredPresentTime);
parcel->writeBool(mIsAutoTimestamp);
+ parcel->writeBool(mLogCallPoints);
mFrameTimelineInfo.writeToParcel(parcel);
parcel->writeStrongBinder(mApplyToken);
parcel->writeUint32(static_cast<uint32_t>(mDisplayStates.size()));
@@ -1019,8 +1013,7 @@
}
parcel->writeUint32(static_cast<uint32_t>(mComposerStates.size()));
- for (auto const& [handle, composerState] : mComposerStates) {
- SAFE_PARCEL(parcel->writeStrongBinder, handle);
+ for (auto const& composerState : mComposerStates) {
composerState.write(*parcel);
}
@@ -1077,23 +1070,31 @@
}
mMergedTransactionIds.insert(mMergedTransactionIds.begin(), other.mId);
- for (auto const& [handle, composerState] : other.mComposerStates) {
- if (mComposerStates.count(handle) == 0) {
- mComposerStates[handle] = composerState;
- } else {
- if (composerState.state.what & layer_state_t::eBufferChanged) {
- releaseBufferIfOverwriting(mComposerStates[handle].state);
+ for (auto const& otherState : other.mComposerStates) {
+ if (auto it = std::find_if(mComposerStates.begin(), mComposerStates.end(),
+ [&otherState](const auto& composerState) {
+ return composerState.state.surface ==
+ otherState.state.surface;
+ });
+ it != mComposerStates.end()) {
+ if (otherState.state.what & layer_state_t::eBufferChanged) {
+ releaseBufferIfOverwriting(it->state);
}
- mComposerStates[handle].state.merge(composerState.state);
+ it->state.merge(otherState.state);
+ } else {
+ mComposerStates.add(otherState);
}
}
for (auto const& state : other.mDisplayStates) {
- ssize_t index = mDisplayStates.indexOf(state);
- if (index < 0) {
- mDisplayStates.add(state);
+ if (auto it = std::find_if(mDisplayStates.begin(), mDisplayStates.end(),
+ [&state](const auto& displayState) {
+ return displayState.token == state.token;
+ });
+ it != mDisplayStates.end()) {
+ it->merge(state);
} else {
- mDisplayStates.editItemAt(static_cast<size_t>(index)).merge(state);
+ mDisplayStates.add(state);
}
}
@@ -1127,12 +1128,17 @@
mInputWindowCommands.merge(other.mInputWindowCommands);
mMayContainBuffer |= other.mMayContainBuffer;
- mEarlyWakeupStart = mEarlyWakeupStart || other.mEarlyWakeupStart;
- mEarlyWakeupEnd = mEarlyWakeupEnd || other.mEarlyWakeupEnd;
+ mFlags |= other.mFlags;
mApplyToken = other.mApplyToken;
mergeFrameTimelineInfo(mFrameTimelineInfo, other.mFrameTimelineInfo);
+ mLogCallPoints |= other.mLogCallPoints;
+ if (mLogCallPoints) {
+ ALOG(LOG_DEBUG, LOG_SURFACE_CONTROL_REGISTRY,
+ "Transaction %" PRIu64 " merged with transaction %" PRIu64, other.getId(), mId);
+ }
+
other.clear();
return *this;
}
@@ -1144,14 +1150,13 @@
mInputWindowCommands.clear();
mUncacheBuffers.clear();
mMayContainBuffer = false;
- mAnimation = false;
- mEarlyWakeupStart = false;
- mEarlyWakeupEnd = false;
mDesiredPresentTime = 0;
mIsAutoTimestamp = true;
mFrameTimelineInfo = {};
mApplyToken = nullptr;
mMergedTransactionIds.clear();
+ mLogCallPoints = false;
+ mFlags = 0;
}
uint64_t SurfaceComposerClient::Transaction::getId() {
@@ -1186,8 +1191,8 @@
}
size_t count = 0;
- for (auto& [handle, cs] : mComposerStates) {
- layer_state_t* s = &(mComposerStates[handle].state);
+ for (auto& cs : mComposerStates) {
+ layer_state_t* s = &cs.state;
if (!(s->what & layer_state_t::eBufferChanged)) {
continue;
} else if (s->bufferData &&
@@ -1312,58 +1317,47 @@
cacheBuffers();
- Vector<ComposerState> composerStates;
- Vector<DisplayState> displayStates;
- uint32_t flags = 0;
-
- for (auto const& kv : mComposerStates) {
- composerStates.add(kv.second);
- }
-
- displayStates = std::move(mDisplayStates);
-
- if (mAnimation) {
- flags |= ISurfaceComposer::eAnimation;
- }
if (oneWay) {
if (synchronous) {
ALOGE("Transaction attempted to set synchronous and one way at the same time"
" this is an invalid request. Synchronous will win for safety");
} else {
- flags |= ISurfaceComposer::eOneWay;
+ mFlags |= ISurfaceComposer::eOneWay;
}
}
- // If both mEarlyWakeupStart and mEarlyWakeupEnd are set
+ // If both ISurfaceComposer::eEarlyWakeupStart and ISurfaceComposer::eEarlyWakeupEnd are set
// it is equivalent for none
- if (mEarlyWakeupStart && !mEarlyWakeupEnd) {
- flags |= ISurfaceComposer::eEarlyWakeupStart;
+ uint32_t wakeupFlags = ISurfaceComposer::eEarlyWakeupStart | ISurfaceComposer::eEarlyWakeupEnd;
+ if ((mFlags & wakeupFlags) == wakeupFlags) {
+ mFlags &= ~(wakeupFlags);
}
- if (mEarlyWakeupEnd && !mEarlyWakeupStart) {
- flags |= ISurfaceComposer::eEarlyWakeupEnd;
- }
-
sp<IBinder> applyToken = mApplyToken ? mApplyToken : getDefaultApplyToken();
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- sf->setTransactionState(mFrameTimelineInfo, composerStates, displayStates, flags, applyToken,
- mInputWindowCommands, mDesiredPresentTime, mIsAutoTimestamp,
- mUncacheBuffers, hasListenerCallbacks, listenerCallbacks, mId,
- mMergedTransactionIds);
+ status_t binderStatus =
+ sf->setTransactionState(mFrameTimelineInfo, mComposerStates, mDisplayStates, mFlags,
+ applyToken, mInputWindowCommands, mDesiredPresentTime,
+ mIsAutoTimestamp, mUncacheBuffers, hasListenerCallbacks,
+ listenerCallbacks, mId, mMergedTransactionIds);
mId = generateId();
// Clear the current states and flags
clear();
- if (synchronous) {
+ if (synchronous && binderStatus == OK) {
syncCallback->wait();
}
+ if (mLogCallPoints) {
+ ALOG(LOG_DEBUG, LOG_SURFACE_CONTROL_REGISTRY, "Transaction %" PRIu64 " applied", mId);
+ }
+
mStatus = NO_ERROR;
- return NO_ERROR;
+ return binderStatus;
}
-sp<IBinder> SurfaceComposerClient::Transaction::sApplyToken = new BBinder();
+sp<IBinder> SurfaceComposerClient::Transaction::sApplyToken = sp<BBinder>::make();
std::mutex SurfaceComposerClient::Transaction::sApplyTokenMutex;
@@ -1374,7 +1368,7 @@
void SurfaceComposerClient::Transaction::setDefaultApplyToken(sp<IBinder> applyToken) {
std::scoped_lock lock{sApplyTokenMutex};
- sApplyToken = applyToken;
+ sApplyToken = std::move(applyToken);
}
status_t SurfaceComposerClient::Transaction::sendSurfaceFlushJankDataTransaction(
@@ -1389,6 +1383,11 @@
t.registerSurfaceControlForCallback(sc);
return t.apply(/*sync=*/false, /* oneWay=*/true);
}
+
+void SurfaceComposerClient::Transaction::enableDebugLogCallPoints() {
+ mLogCallPoints = true;
+}
+
// ---------------------------------------------------------------------------
sp<IBinder> SurfaceComposerClient::createVirtualDisplay(const std::string& displayName,
@@ -1416,9 +1415,8 @@
ComposerServiceAIDL::getComposerService()->getPhysicalDisplayIds(&displayIds);
if (status.isOk()) {
physicalDisplayIds.reserve(displayIds.size());
- for (auto item : displayIds) {
- auto id = DisplayId::fromValue<PhysicalDisplayId>(static_cast<uint64_t>(item));
- physicalDisplayIds.push_back(*id);
+ for (auto id : displayIds) {
+ physicalDisplayIds.push_back(PhysicalDisplayId::fromValue(static_cast<uint64_t>(id)));
}
}
return physicalDisplayIds;
@@ -1440,31 +1438,34 @@
}
void SurfaceComposerClient::Transaction::setAnimationTransaction() {
- mAnimation = true;
+ mFlags |= ISurfaceComposer::eAnimation;
}
void SurfaceComposerClient::Transaction::setEarlyWakeupStart() {
- mEarlyWakeupStart = true;
+ mFlags |= ISurfaceComposer::eEarlyWakeupStart;
}
void SurfaceComposerClient::Transaction::setEarlyWakeupEnd() {
- mEarlyWakeupEnd = true;
+ mFlags |= ISurfaceComposer::eEarlyWakeupEnd;
}
layer_state_t* SurfaceComposerClient::Transaction::getLayerState(const sp<SurfaceControl>& sc) {
auto handle = sc->getLayerStateHandle();
-
- if (mComposerStates.count(handle) == 0) {
- // we don't have it, add an initialized layer_state to our list
- ComposerState s;
-
- s.state.surface = handle;
- s.state.layerId = sc->getLayerId();
-
- mComposerStates[handle] = s;
+ if (auto it = std::find_if(mComposerStates.begin(), mComposerStates.end(),
+ [&handle](const auto& composerState) {
+ return composerState.state.surface == handle;
+ });
+ it != mComposerStates.end()) {
+ return &it->state;
}
- return &(mComposerStates[handle].state);
+ // we don't have it, add an initialized layer_state to our list
+ ComposerState s;
+ s.state.surface = handle;
+ s.state.layerId = sc->getLayerId();
+ mComposerStates.add(s);
+
+ return &mComposerStates.editItemAt(mComposerStates.size() - 1).state;
}
void SurfaceComposerClient::Transaction::registerSurfaceControlForCallback(
@@ -1674,6 +1675,18 @@
return *this;
}
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setClientDrawnCornerRadius(
+ const sp<SurfaceControl>& sc, float clientDrawnCornerRadius) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+ s->what |= layer_state_t::eClientDrawnCornerRadiusChanged;
+ s->clientDrawnCornerRadius = clientDrawnCornerRadius;
+ return *this;
+}
+
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBackgroundBlurRadius(
const sp<SurfaceControl>& sc, int backgroundBlurRadius) {
layer_state_t* s = getLayerState(sc);
@@ -1940,15 +1953,23 @@
}
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLuts(
- const sp<SurfaceControl>& sc, const base::unique_fd& /*lutFd*/,
- const std::vector<int32_t>& /*offsets*/, const std::vector<int32_t>& /*dimensions*/,
- const std::vector<int32_t>& /*sizes*/, const std::vector<int32_t>& /*samplingKeys*/) {
+ const sp<SurfaceControl>& sc, base::unique_fd&& lutFd, const std::vector<int32_t>& offsets,
+ const std::vector<int32_t>& dimensions, const std::vector<int32_t>& sizes,
+ const std::vector<int32_t>& samplingKeys) {
layer_state_t* s = getLayerState(sc);
if (!s) {
mStatus = BAD_INDEX;
return *this;
}
- // TODO (b/329472856): update layer_state_t for lut(s)
+
+ s->what |= layer_state_t::eLutsChanged;
+ if (lutFd.ok()) {
+ s->luts = std::make_shared<gui::DisplayLuts>(std::move(lutFd), offsets, dimensions, sizes,
+ samplingKeys);
+ } else {
+ s->luts = nullptr;
+ }
+
registerSurfaceControlForCallback(sc);
return *this;
}
@@ -2103,13 +2124,13 @@
}
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInputWindowInfo(
- const sp<SurfaceControl>& sc, const WindowInfo& info) {
+ const sp<SurfaceControl>& sc, sp<WindowInfoHandle> info) {
layer_state_t* s = getLayerState(sc);
if (!s) {
mStatus = BAD_INDEX;
return *this;
}
- s->windowInfoHandle = new WindowInfoHandle(info);
+ s->windowInfoHandle = std::move(info);
s->what |= layer_state_t::eInputInfoChanged;
return *this;
}
@@ -2421,18 +2442,54 @@
return *this;
}
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setPictureProfileHandle(
+ const sp<SurfaceControl>& sc, const PictureProfileHandle& pictureProfileHandle) {
+ if (com_android_graphics_libgui_flags_apply_picture_profiles()) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+
+ s->what |= layer_state_t::ePictureProfileHandleChanged;
+ s->pictureProfileHandle = pictureProfileHandle;
+
+ registerSurfaceControlForCallback(sc);
+ }
+ return *this;
+}
+
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setContentPriority(
+ const sp<SurfaceControl>& sc, int32_t priority) {
+ if (com_android_graphics_libgui_flags_apply_picture_profiles()) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+
+ s->what |= layer_state_t::eAppContentPriorityChanged;
+ s->appContentPriority = priority;
+
+ registerSurfaceControlForCallback(sc);
+ }
+ return *this;
+}
+
// ---------------------------------------------------------------------------
DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp<IBinder>& token) {
+ if (auto it = std::find_if(mDisplayStates.begin(), mDisplayStates.end(),
+ [token](const auto& display) { return display.token == token; });
+ it != mDisplayStates.end()) {
+ return *it;
+ }
+
+ // If display state doesn't exist, add a new one.
DisplayState s;
s.token = token;
- ssize_t index = mDisplayStates.indexOf(s);
- if (index < 0) {
- // we don't have it, add an initialized layer_state to our list
- s.what = 0;
- index = mDisplayStates.add(s);
- }
- return mDisplayStates.editItemAt(static_cast<size_t>(index));
+ mDisplayStates.add(s);
+ return mDisplayStates.editItemAt(mDisplayStates.size() - 1);
}
status_t SurfaceComposerClient::Transaction::setDisplaySurface(const sp<IBinder>& token,
@@ -2626,9 +2683,9 @@
}
ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
if (err == NO_ERROR) {
- *outSurface = new SurfaceControl(this, result.handle, result.layerId,
- toString(result.layerName), w, h, format,
- result.transformHint, flags);
+ *outSurface = sp<SurfaceControl>::make(this, result.handle, result.layerId,
+ toString(result.layerName), w, h, format,
+ result.transformHint, flags);
}
}
return err;
@@ -2644,7 +2701,8 @@
const binder::Status status = mClient->mirrorSurface(mirrorFromHandle, &result);
const status_t err = statusTFromBinderStatus(status);
if (err == NO_ERROR) {
- return new SurfaceControl(this, result.handle, result.layerId, toString(result.layerName));
+ return sp<SurfaceControl>::make(this, result.handle, result.layerId,
+ toString(result.layerName));
}
return nullptr;
}
@@ -2654,7 +2712,8 @@
const binder::Status status = mClient->mirrorDisplay(displayId.value, &result);
const status_t err = statusTFromBinderStatus(status);
if (err == NO_ERROR) {
- return new SurfaceControl(this, result.handle, result.layerId, toString(result.layerName));
+ return sp<SurfaceControl>::make(this, result.handle, result.layerId,
+ toString(result.layerName));
}
return nullptr;
}
@@ -2808,6 +2867,13 @@
outInfo->gameContentTypeSupported = ginfo.gameContentTypeSupported;
outInfo->preferredBootDisplayMode = ginfo.preferredBootDisplayMode;
outInfo->hasArrSupport = ginfo.hasArrSupport;
+ outInfo->frameRateCategoryRate = ui::FrameRateCategoryRate(ginfo.frameRateCategoryRate.normal,
+ ginfo.frameRateCategoryRate.high);
+ outInfo->supportedRefreshRates.clear();
+ outInfo->supportedRefreshRates.reserve(ginfo.supportedRefreshRates.size());
+ for (const auto rate : ginfo.supportedRefreshRates) {
+ outInfo->supportedRefreshRates.push_back(static_cast<float>(rate));
+ }
}
status_t SurfaceComposerClient::getDynamicDisplayInfoFromId(int64_t displayId,
@@ -2991,6 +3057,14 @@
ComposerServiceAIDL::getComposerService()->setPowerMode(token, mode);
}
+status_t SurfaceComposerClient::getMaxLayerPictureProfiles(const sp<IBinder>& token,
+ int32_t* outMaxProfiles) {
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->getMaxLayerPictureProfiles(token,
+ outMaxProfiles);
+ return statusTFromBinderStatus(status);
+}
+
status_t SurfaceComposerClient::getCompositionPreference(
ui::Dataspace* defaultDataspace, ui::PixelFormat* defaultPixelFormat,
ui::Dataspace* wideColorGamutDataspace, ui::PixelFormat* wideColorGamutPixelFormat) {
@@ -3215,6 +3289,20 @@
return statusTFromBinderStatus(status);
}
+status_t SurfaceComposerClient::addActivePictureListener(
+ const sp<gui::IActivePictureListener>& listener) {
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->addActivePictureListener(listener);
+ return statusTFromBinderStatus(status);
+}
+
+status_t SurfaceComposerClient::removeActivePictureListener(
+ const sp<gui::IActivePictureListener>& listener) {
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->removeActivePictureListener(listener);
+ return statusTFromBinderStatus(status);
+}
+
status_t SurfaceComposerClient::notifyPowerBoost(int32_t boostId) {
binder::Status status = ComposerServiceAIDL::getComposerService()->notifyPowerBoost(boostId);
return statusTFromBinderStatus(status);
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index f126c0b..1eb9b87 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -141,7 +141,8 @@
ISurfaceComposerClient::eOpaque);
mBbqChild = mClient->createSurface(String8::format("[BBQ] %s", mName.c_str()), 0, 0, mFormat,
flags, mHandle, {}, &ignore);
- mBbq = sp<BLASTBufferQueue>::make("[BBQ]" + mName, mBbqChild, mWidth, mHeight, mFormat);
+ mBbq = sp<BLASTBufferQueue>::make("[BBQ] " + mName, /* updateDestinationFrame */ true);
+ mBbq->update(mBbqChild, mWidth, mHeight, mFormat);
// This surface is always consumed by SurfaceFlinger, so the
// producerControlledByApp value doesn't matter; using false.
@@ -268,10 +269,11 @@
SAFE_PARCEL(parcel.readUint32, &format);
// We aren't the original owner of the surface.
- *outSurfaceControl = new SurfaceControl(new SurfaceComposerClient(
- interface_cast<ISurfaceComposerClient>(client)),
- handle.get(), layerId, layerName, width, height, format,
- transformHint);
+ *outSurfaceControl =
+ sp<SurfaceControl>::make(sp<SurfaceComposerClient>::make(
+ interface_cast<ISurfaceComposerClient>(client)),
+ handle, layerId, layerName, width, height, format,
+ transformHint);
return NO_ERROR;
}
diff --git a/libs/gui/TEST_MAPPING b/libs/gui/TEST_MAPPING
index a590c86..14d6df6 100644
--- a/libs/gui/TEST_MAPPING
+++ b/libs/gui/TEST_MAPPING
@@ -60,5 +60,34 @@
}
]
}
+ ],
+ "postsubmit": [
+ {
+ "name": "libgui_test",
+ "keywords": [ "primary-device" ],
+ "options": [
+ // TODO(b/397776630): Failing on real devices.
+ {
+ "exclude-filter": "InputSurfacesTest#input_respects_scaled_touchable_region_overflow"
+ },
+ // TODO(b/233363648): Failing on real devices.
+ {
+ "exclude-filter": "SurfaceTextureGLTest#TexturingFromCpuFilledYV12BufferNpot"
+ },
+ {
+ "exclude-filter": "SurfaceTextureGLTest#TexturingFromCpuFilledYV12BufferPow2"
+ },
+ {
+ "exclude-filter": "SurfaceTextureGLTest#TexturingFromCpuFilledYV12BufferWithCrop"
+ },
+ // TODO(b/233363648): Flaky on real devices.
+ {
+ "exclude-filter": "SurfaceTextureGLToGLTest#EglMakeCurrentBeforeConsumerDeathUnrefsBuffers"
+ },
+ {
+ "exclude-filter": "SurfaceTextureGLToGLTest#EglMakeCurrentAfterConsumerDeathUnrefsBuffers"
+ }
+ ]
+ }
]
}
diff --git a/libs/gui/WindowInfo.cpp b/libs/gui/WindowInfo.cpp
index 82d2554..3fb66d1 100644
--- a/libs/gui/WindowInfo.cpp
+++ b/libs/gui/WindowInfo.cpp
@@ -59,6 +59,32 @@
return out;
}
+status_t writeTransform(android::Parcel* parcel, const ui::Transform& transform) {
+ return parcel->writeFloat(transform.dsdx()) ?:
+ parcel->writeFloat(transform.dtdx()) ?:
+ parcel->writeFloat(transform.tx()) ?:
+ parcel->writeFloat(transform.dtdy()) ?:
+ parcel->writeFloat(transform.dsdy()) ?:
+ parcel->writeFloat(transform.ty());
+}
+
+status_t readTransform(const android::Parcel* parcel, ui::Transform& transform) {
+ float dsdx, dtdx, tx, dtdy, dsdy, ty;
+
+ const status_t status = parcel->readFloat(&dsdx) ?:
+ parcel->readFloat(&dtdx) ?:
+ parcel->readFloat(&tx) ?:
+ parcel->readFloat(&dtdy) ?:
+ parcel->readFloat(&dsdy) ?:
+ parcel->readFloat(&ty);
+ if (status != OK) {
+ return status;
+ }
+
+ transform.set({dsdx, dtdx, tx, dtdy, dsdy, ty, 0, 0, 1});
+ return OK;
+}
+
} // namespace
void WindowInfo::setInputConfig(ftl::Flags<InputConfig> config, bool value) {
@@ -73,10 +99,6 @@
touchableRegion.orSelf(region);
}
-bool WindowInfo::supportsSplitTouch() const {
- return !inputConfig.test(InputConfig::PREVENT_SPLITTING);
-}
-
bool WindowInfo::isSpy() const {
return inputConfig.test(InputConfig::SPY);
}
@@ -135,12 +157,7 @@
parcel->writeInt32(surfaceInset) ?:
parcel->writeFloat(globalScaleFactor) ?:
parcel->writeFloat(alpha) ?:
- parcel->writeFloat(transform.dsdx()) ?:
- parcel->writeFloat(transform.dtdx()) ?:
- parcel->writeFloat(transform.tx()) ?:
- parcel->writeFloat(transform.dtdy()) ?:
- parcel->writeFloat(transform.dsdy()) ?:
- parcel->writeFloat(transform.ty()) ?:
+ writeTransform(parcel, transform) ?:
parcel->writeInt32(static_cast<int32_t>(touchOcclusionMode)) ?:
parcel->writeInt32(ownerPid.val()) ?:
parcel->writeInt32(ownerUid.val()) ?:
@@ -153,8 +170,12 @@
parcel->writeStrongBinder(touchableRegionCropHandle.promote()) ?:
parcel->writeStrongBinder(windowToken) ?:
parcel->writeStrongBinder(focusTransferTarget) ?:
- parcel->writeBool(canOccludePresentation);
+ parcel->writeBool(canOccludePresentation) ?:
+ parcel->writeBool(cloneLayerStackTransform.has_value());
// clang-format on
+ if (cloneLayerStackTransform) {
+ status = status ?: writeTransform(parcel, *cloneLayerStackTransform);
+ }
return status;
}
@@ -174,10 +195,10 @@
return status;
}
- float dsdx, dtdx, tx, dtdy, dsdy, ty;
int32_t lpFlags, lpType, touchOcclusionModeInt, inputConfigInt, ownerPidInt, ownerUidInt,
displayIdInt;
sp<IBinder> touchableRegionCropHandleSp;
+ bool hasCloneLayerStackTransform = false;
// clang-format off
status = parcel->readInt32(&lpFlags) ?:
@@ -188,12 +209,7 @@
parcel->readInt32(&surfaceInset) ?:
parcel->readFloat(&globalScaleFactor) ?:
parcel->readFloat(&alpha) ?:
- parcel->readFloat(&dsdx) ?:
- parcel->readFloat(&dtdx) ?:
- parcel->readFloat(&tx) ?:
- parcel->readFloat(&dtdy) ?:
- parcel->readFloat(&dsdy) ?:
- parcel->readFloat(&ty) ?:
+ readTransform(parcel, /*byRef*/ transform) ?:
parcel->readInt32(&touchOcclusionModeInt) ?:
parcel->readInt32(&ownerPidInt) ?:
parcel->readInt32(&ownerUidInt) ?:
@@ -206,8 +222,8 @@
parcel->readNullableStrongBinder(&touchableRegionCropHandleSp) ?:
parcel->readNullableStrongBinder(&windowToken) ?:
parcel->readNullableStrongBinder(&focusTransferTarget) ?:
- parcel->readBool(&canOccludePresentation);
-
+ parcel->readBool(&canOccludePresentation)?:
+ parcel->readBool(&hasCloneLayerStackTransform);
// clang-format on
if (status != OK) {
@@ -216,7 +232,6 @@
layoutParamsFlags = ftl::Flags<Flag>(lpFlags);
layoutParamsType = static_cast<Type>(lpType);
- transform.set({dsdx, dtdx, tx, dtdy, dsdy, ty, 0, 0, 1});
touchOcclusionMode = static_cast<TouchOcclusionMode>(touchOcclusionModeInt);
inputConfig = ftl::Flags<InputConfig>(inputConfigInt);
ownerPid = Pid{ownerPidInt};
@@ -224,6 +239,15 @@
touchableRegionCropHandle = touchableRegionCropHandleSp;
displayId = ui::LogicalDisplayId{displayIdInt};
+ cloneLayerStackTransform =
+ hasCloneLayerStackTransform ? std::make_optional<ui::Transform>() : std::nullopt;
+ if (cloneLayerStackTransform) {
+ status = readTransform(parcel, /*byRef*/ *cloneLayerStackTransform);
+ if (status != OK) {
+ return status;
+ }
+ }
+
return OK;
}
diff --git a/libs/gui/WindowInfosListenerReporter.cpp b/libs/gui/WindowInfosListenerReporter.cpp
index 91c9a85..d633f9f 100644
--- a/libs/gui/WindowInfosListenerReporter.cpp
+++ b/libs/gui/WindowInfosListenerReporter.cpp
@@ -15,6 +15,7 @@
*/
#include <android/gui/ISurfaceComposer.h>
+#include <android/gui/IWindowInfosListener.h>
#include <gui/AidlUtil.h>
#include <gui/WindowInfosListenerReporter.h>
#include "gui/WindowInfosUpdate.h"
@@ -27,7 +28,7 @@
using gui::aidl_utils::statusTFromBinderStatus;
sp<WindowInfosListenerReporter> WindowInfosListenerReporter::getInstance() {
- static sp<WindowInfosListenerReporter> sInstance = new WindowInfosListenerReporter;
+ static sp<WindowInfosListenerReporter> sInstance = sp<WindowInfosListenerReporter>::make();
return sInstance;
}
@@ -116,7 +117,8 @@
std::scoped_lock lock(mListenersMutex);
if (!mWindowInfosListeners.empty()) {
gui::WindowInfosListenerInfo listenerInfo;
- composerService->addWindowInfosListener(this, &listenerInfo);
+ composerService->addWindowInfosListener(sp<gui::IWindowInfosListener>::fromExisting(this),
+ &listenerInfo);
mWindowInfosPublisher = std::move(listenerInfo.windowInfosPublisher);
mListenerId = listenerInfo.listenerId;
}
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp b/libs/gui/aidl/android/gui/ActivePicture.aidl
similarity index 61%
copy from services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp
copy to libs/gui/aidl/android/gui/ActivePicture.aidl
index d383283..9b83be1 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp
+++ b/libs/gui/aidl/android/gui/ActivePicture.aidl
@@ -14,12 +14,19 @@
* limitations under the License.
*/
-#include "mock/DisplayHardware/MockPowerHintSessionWrapper.h"
+package android.gui;
-namespace android::Hwc2::mock {
+/**
+ * Visible content that is using picture processing.
+ * @hide
+ */
+parcelable ActivePicture {
+ /** The layer ID that is using picture processing. */
+ int layerId;
-// Explicit default instantiation is recommended.
-MockPowerHintSessionWrapper::MockPowerHintSessionWrapper()
- : power::PowerHintSessionWrapper(nullptr) {}
+ /** UID that owns layer using picture processing. */
+ int ownerUid;
-} // namespace android::Hwc2::mock
+ /** ID of the picture profile that was used to configure the picture processing. */
+ long pictureProfileId;
+}
diff --git a/libs/gui/aidl/android/gui/CaptureArgs.aidl b/libs/gui/aidl/android/gui/CaptureArgs.aidl
index 4920344..2bbed2b 100644
--- a/libs/gui/aidl/android/gui/CaptureArgs.aidl
+++ b/libs/gui/aidl/android/gui/CaptureArgs.aidl
@@ -69,10 +69,5 @@
// exact colorspace is not an appropriate intermediate result.
// Note that if the caller is requesting a specific dataspace, this hint does nothing.
boolean hintForSeamlessTransition = false;
-
- // Allows the screenshot to attach a gainmap, which allows for a per-pixel
- // transformation of the screenshot to another luminance range, typically
- // mapping an SDR base image into HDR.
- boolean attachGainmap = false;
}
diff --git a/libs/gui/aidl/android/gui/DynamicDisplayInfo.aidl b/libs/gui/aidl/android/gui/DynamicDisplayInfo.aidl
index 70873b0..26c12c5 100644
--- a/libs/gui/aidl/android/gui/DynamicDisplayInfo.aidl
+++ b/libs/gui/aidl/android/gui/DynamicDisplayInfo.aidl
@@ -17,6 +17,7 @@
package android.gui;
import android.gui.DisplayMode;
+import android.gui.FrameRateCategoryRate;
import android.gui.HdrCapabilities;
// Information about a physical display which may change on hotplug reconnect.
@@ -46,4 +47,10 @@
// Represents whether display supports ARR.
boolean hasArrSupport;
+
+ // Represents frame rate for FrameRateCategory Normal and High.
+ FrameRateCategoryRate frameRateCategoryRate;
+
+ // All the refresh rates supported for the default display mode.
+ float[] supportedRefreshRates;
}
diff --git a/libs/binder/trusty/ndk/include/android/llndk-versioning.h b/libs/gui/aidl/android/gui/FrameRateCategoryRate.aidl
similarity index 71%
copy from libs/binder/trusty/ndk/include/android/llndk-versioning.h
copy to libs/gui/aidl/android/gui/FrameRateCategoryRate.aidl
index e955a34..f302801 100644
--- a/libs/binder/trusty/ndk/include/android/llndk-versioning.h
+++ b/libs/gui/aidl/android/gui/FrameRateCategoryRate.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2024 The Android Open Source Project
+ * Copyright 2024 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.
@@ -13,7 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#pragma once
-// TODO(b/349936395): set to true for Trusty
-#define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) (false)
+package android.gui;
+
+/** @hide */
+// Represents frame rate for FrameRateCategory Normal and High.
+parcelable FrameRateCategoryRate {
+ float normal;
+ float high;
+}
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp b/libs/gui/aidl/android/gui/IActivePictureListener.aidl
similarity index 62%
copy from services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp
copy to libs/gui/aidl/android/gui/IActivePictureListener.aidl
index d383283..ad310bb 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp
+++ b/libs/gui/aidl/android/gui/IActivePictureListener.aidl
@@ -14,12 +14,17 @@
* limitations under the License.
*/
-#include "mock/DisplayHardware/MockPowerHintSessionWrapper.h"
+package android.gui;
-namespace android::Hwc2::mock {
+import android.gui.ActivePicture;
-// Explicit default instantiation is recommended.
-MockPowerHintSessionWrapper::MockPowerHintSessionWrapper()
- : power::PowerHintSessionWrapper(nullptr) {}
-
-} // namespace android::Hwc2::mock
+/**
+ * Receive callbacks whenever the visible content using picture profiles changes.
+ * @hide
+ */
+interface IActivePictureListener {
+ /**
+ * Callback reporting the visible content on the screen using picture profiles.
+ */
+ oneway void onActivePicturesChanged(in ActivePicture[] activePictures);
+}
diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
index ac14138..da47ee2 100644
--- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
+++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
@@ -33,6 +33,7 @@
import android.gui.FrameStats;
import android.gui.HdrConversionCapability;
import android.gui.HdrConversionStrategy;
+import android.gui.IActivePictureListener;
import android.gui.IDisplayEventConnection;
import android.gui.IFpsListener;
import android.gui.IHdrLayerInfoListener;
@@ -228,6 +229,11 @@
void setGameContentType(IBinder display, boolean on);
/**
+ * Gets the maximum number of picture profiles supported by the display.
+ */
+ int getMaxLayerPictureProfiles(IBinder display);
+
+ /**
* Capture the specified screen. This requires READ_FRAME_BUFFER
* permission. This function will fail if there is a secure window on
* screen and DisplayCaptureArgs.captureSecureLayers is false.
@@ -599,4 +605,16 @@
* past the provided VSync.
*/
oneway void removeJankListener(int layerId, IJankListener listener, long afterVsync);
+
+ /**
+ * Adds a listener used to monitor visible content that is being processed with picture
+ * profiles.
+ */
+ oneway void addActivePictureListener(IActivePictureListener listener);
+
+ /**
+ * Removes a listener used to monitor visible content that is being processed with picture
+ * profiles.
+ */
+ oneway void removeActivePictureListener(IActivePictureListener listener);
}
diff --git a/libs/gui/aidl/android/gui/Lut.aidl b/libs/gui/aidl/android/gui/Lut.aidl
deleted file mode 100644
index a06e521..0000000
--- a/libs/gui/aidl/android/gui/Lut.aidl
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2024 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.
- */
-
-package android.gui;
-
-import android.gui.LutProperties;
-import android.os.ParcelFileDescriptor;
-
-/**
- * This mirrors aidl::android::hardware::graphics::composer3::Lut definition
- * @hide
- */
-parcelable Lut {
- @nullable ParcelFileDescriptor pfd;
-
- LutProperties lutProperties;
-}
\ No newline at end of file
diff --git a/libs/gui/aidl/android/gui/LutProperties.aidl b/libs/gui/aidl/android/gui/LutProperties.aidl
index 561e0c0..84c7013 100644
--- a/libs/gui/aidl/android/gui/LutProperties.aidl
+++ b/libs/gui/aidl/android/gui/LutProperties.aidl
@@ -25,8 +25,8 @@
enum Dimension { ONE_D = 1, THREE_D = 3 }
Dimension dimension;
- long size;
+ int size;
@Backing(type="int")
- enum SamplingKey { RGB, MAX_RGB }
+ enum SamplingKey { RGB, MAX_RGB, CIE_Y }
SamplingKey[] samplingKeys;
}
\ No newline at end of file
diff --git a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
index fd8ffe1..b1a23b3 100644
--- a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
+++ b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
@@ -971,7 +971,7 @@
// H2BGraphicBufferProducer
status_t H2BGraphicBufferProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
- *buf = new GraphicBuffer();
+ *buf = sp<GraphicBuffer>::make();
status_t fnStatus;
status_t transStatus = toStatusT(mBase->requestBuffer(
static_cast<int32_t>(slot),
@@ -999,7 +999,7 @@
uint32_t h, ::android::PixelFormat format,
uint64_t usage, uint64_t* outBufferAge,
FrameEventHistoryDelta* outTimestamps) {
- *fence = new Fence();
+ *fence = sp<Fence>::make();
status_t fnStatus;
status_t transStatus = toStatusT(mBase->dequeueBuffer(
w, h, static_cast<PixelFormat>(format), uint32_t(usage),
@@ -1035,8 +1035,8 @@
status_t H2BGraphicBufferProducer::detachNextBuffer(
sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) {
- *outBuffer = new GraphicBuffer();
- *outFence = new Fence();
+ *outBuffer = sp<GraphicBuffer>::make();
+ *outFence = sp<Fence>::make();
status_t fnStatus;
status_t transStatus = toStatusT(mBase->detachNextBuffer(
[&fnStatus, outBuffer, outFence] (
@@ -1127,8 +1127,8 @@
status_t H2BGraphicBufferProducer::connect(
const sp<IProducerListener>& listener, int api,
bool producerControlledByApp, QueueBufferOutput* output) {
- sp<HProducerListener> tListener = listener == nullptr ?
- nullptr : new B2HProducerListener(listener);
+ sp<HProducerListener> tListener =
+ listener == nullptr ? nullptr : sp<B2HProducerListener>::make(listener);
status_t fnStatus;
status_t transStatus = toStatusT(mBase->connect(
tListener, static_cast<int32_t>(api), producerControlledByApp,
@@ -1205,13 +1205,13 @@
hidl_handle const& fence,
hidl_array<float, 16> const& transformMatrix) {
fnStatus = toStatusT(status);
- *outBuffer = new GraphicBuffer();
+ *outBuffer = sp<GraphicBuffer>::make();
if (!convertTo(outBuffer->get(), buffer)) {
ALOGE("H2BGraphicBufferProducer::getLastQueuedBuffer - "
"Invalid output buffer");
fnStatus = fnStatus == NO_ERROR ? BAD_VALUE : fnStatus;
}
- *outFence = new Fence();
+ *outFence = sp<Fence>::make();
if (!convertTo(outFence->get(), fence)) {
ALOGE("H2BGraphicBufferProducer::getLastQueuedBuffer - "
"Invalid output fence");
diff --git a/libs/gui/bufferqueue/2.0/B2HGraphicBufferProducer.cpp b/libs/gui/bufferqueue/2.0/B2HGraphicBufferProducer.cpp
index c76d771..4384bd5 100644
--- a/libs/gui/bufferqueue/2.0/B2HGraphicBufferProducer.cpp
+++ b/libs/gui/bufferqueue/2.0/B2HGraphicBufferProducer.cpp
@@ -272,7 +272,7 @@
HConnectionType hConnectionType,
bool producerControlledByApp,
connect_cb _hidl_cb) {
- sp<BProducerListener> bListener = new H2BProducerListener(hListener);
+ sp<BProducerListener> bListener = sp<H2BProducerListener>::make(hListener);
int bConnectionType{};
if (!bListener || !h2b(hConnectionType, &bConnectionType)) {
_hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{});
diff --git a/libs/gui/bufferqueue/2.0/H2BGraphicBufferProducer.cpp b/libs/gui/bufferqueue/2.0/H2BGraphicBufferProducer.cpp
index ae00a26..7121bb7 100644
--- a/libs/gui/bufferqueue/2.0/H2BGraphicBufferProducer.cpp
+++ b/libs/gui/bufferqueue/2.0/H2BGraphicBufferProducer.cpp
@@ -325,7 +325,7 @@
}
sp<HProducerListener> hListener = nullptr;
if (listener && listener->needsReleaseNotify()) {
- hListener = new B2HProducerListener(listener);
+ hListener = sp<B2HProducerListener>::make(listener);
if (!hListener) {
LOG(ERROR) << "connect: failed to wrap listener.";
return UNKNOWN_ERROR;
diff --git a/libs/gui/bufferqueue/2.0/types.cpp b/libs/gui/bufferqueue/2.0/types.cpp
index cbd6cad..c245766 100644
--- a/libs/gui/bufferqueue/2.0/types.cpp
+++ b/libs/gui/bufferqueue/2.0/types.cpp
@@ -147,13 +147,13 @@
bool h2b(native_handle_t const* from, sp<BFence>* to) {
if (!from || from->numFds == 0) {
- *to = new ::android::Fence();
+ *to = sp<::android::Fence>::make();
return true;
}
if (from->numFds != 1 || from->numInts != 0) {
return false;
}
- *to = new BFence(dup(from->data[0]));
+ *to = sp<BFence>::make(dup(from->data[0]));
return true;
}
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 8592cff..db1b9fb 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -17,7 +17,10 @@
#ifndef ANDROID_GUI_BLAST_BUFFER_QUEUE_H
#define ANDROID_GUI_BLAST_BUFFER_QUEUE_H
-#include <com_android_graphics_libgui_flags.h>
+#include <optional>
+#include <queue>
+
+#include <ftl/small_map.h>
#include <gui/BufferItem.h>
#include <gui/BufferItemConsumer.h>
#include <gui/IGraphicBufferConsumer.h>
@@ -29,32 +32,20 @@
#include <utils/RefBase.h>
#include <system/window.h>
-#include <queue>
#include <com_android_graphics_libgui_flags.h>
namespace android {
+// Sizes determined empirically to avoid allocations during common activity.
+constexpr size_t kSubmittedBuffersMapSizeHint = 8;
+constexpr size_t kDequeueTimestampsMapSizeHint = 32;
+
class BLASTBufferQueue;
class BufferItemConsumer;
class BLASTBufferItemConsumer : public BufferItemConsumer {
public:
-#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
- BLASTBufferItemConsumer(const sp<IGraphicBufferProducer>& producer,
- const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
- int bufferCount, bool controlledByApp, wp<BLASTBufferQueue> bbq)
- : BufferItemConsumer(producer, consumer, consumerUsage, bufferCount, controlledByApp),
-#else
- BLASTBufferItemConsumer(const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
- int bufferCount, bool controlledByApp, wp<BLASTBufferQueue> bbq)
- : BufferItemConsumer(consumer, consumerUsage, bufferCount, controlledByApp),
-#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
- mBLASTBufferQueue(std::move(bbq)),
- mCurrentlyConnected(false),
- mPreviouslyConnected(false) {
- }
-
void onDisconnect() override EXCLUDES(mMutex);
void addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
FrameEventHistoryDelta* outDelta) override EXCLUDES(mMutex);
@@ -75,6 +66,23 @@
#endif
private:
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+ BLASTBufferItemConsumer(const sp<IGraphicBufferProducer>& producer,
+ const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
+ int bufferCount, bool controlledByApp, wp<BLASTBufferQueue> bbq)
+ : BufferItemConsumer(producer, consumer, consumerUsage, bufferCount, controlledByApp),
+#else
+ BLASTBufferItemConsumer(const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
+ int bufferCount, bool controlledByApp, wp<BLASTBufferQueue> bbq)
+ : BufferItemConsumer(consumer, consumerUsage, bufferCount, controlledByApp),
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+ mBLASTBufferQueue(std::move(bbq)),
+ mCurrentlyConnected(false),
+ mPreviouslyConnected(false) {
+ }
+
+ friend class sp<BLASTBufferItemConsumer>;
+
const wp<BLASTBufferQueue> mBLASTBufferQueue;
uint64_t mCurrentFrameNumber GUARDED_BY(mMutex) = 0;
@@ -88,10 +96,6 @@
class BLASTBufferQueue : public ConsumerBase::FrameAvailableListener {
public:
- BLASTBufferQueue(const std::string& name, bool updateDestinationFrame = true);
- BLASTBufferQueue(const std::string& name, const sp<SurfaceControl>& surface, int width,
- int height, int32_t format);
-
sp<IGraphicBufferProducer> getIGraphicBufferProducer() const {
return mProducer;
}
@@ -143,13 +147,27 @@
*/
void setTransactionHangCallback(std::function<void(const std::string&)> callback);
void setApplyToken(sp<IBinder>);
+
+ void setWaitForBufferReleaseCallback(std::function<void(const nsecs_t)> callback)
+ EXCLUDES(mWaitForBufferReleaseMutex);
+ std::function<void(const nsecs_t)> getWaitForBufferReleaseCallback() const
+ EXCLUDES(mWaitForBufferReleaseMutex);
+
virtual ~BLASTBufferQueue();
void onFirstRef() override;
private:
+ // Not public to ensure construction via sp<>::make().
+ BLASTBufferQueue(const std::string& name, bool updateDestinationFrame = true);
+
+ friend class sp<BLASTBufferQueue>;
friend class BLASTBufferQueueHelper;
friend class BBQBufferQueueProducer;
+ friend class TestBLASTBufferQueue;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ friend class BBQBufferQueueCore;
+#endif
// can't be copied
BLASTBufferQueue& operator = (const BLASTBufferQueue& rhs);
@@ -182,6 +200,7 @@
sp<SurfaceControl> mSurfaceControl GUARDED_BY(mMutex);
mutable std::mutex mMutex;
+ mutable std::mutex mWaitForBufferReleaseMutex;
std::condition_variable mCallbackCV;
// BufferQueue internally allows 1 more than
@@ -197,7 +216,7 @@
// Keep a reference to the submitted buffers so we can release when surfaceflinger drops the
// buffer or the buffer has been presented and a new buffer is ready to be presented.
- std::unordered_map<ReleaseCallbackId, BufferItem, ReleaseBufferCallbackIdHash> mSubmitted
+ ftl::SmallMap<ReleaseCallbackId, BufferItem, kSubmittedBuffersMapSizeHint> mSubmitted
GUARDED_BY(mMutex);
// Keep a queue of the released buffers instead of immediately releasing
@@ -219,6 +238,10 @@
ui::Size mRequestedSize GUARDED_BY(mMutex);
int32_t mFormat GUARDED_BY(mMutex);
+ // Keep a copy of the current picture profile handle, so it can be moved to a new
+ // SurfaceControl when BBQ migrates via ::update.
+ std::optional<PictureProfileHandle> mPictureProfileHandle;
+
struct BufferInfo {
bool hasBuffer = false;
uint32_t width;
@@ -278,8 +301,8 @@
std::mutex mTimestampMutex;
// Tracks buffer dequeue times by the client. This info is sent to SurfaceFlinger which uses
// it for debugging purposes.
- std::unordered_map<uint64_t /* bufferId */, nsecs_t> mDequeueTimestamps
- GUARDED_BY(mTimestampMutex);
+ ftl::SmallMap<uint64_t /* bufferId */, nsecs_t, kDequeueTimestampsMapSizeHint>
+ mDequeueTimestamps GUARDED_BY(mTimestampMutex);
// Keep track of SurfaceControls that have submitted a transaction and BBQ is waiting on a
// callback for them.
@@ -316,49 +339,50 @@
std::unordered_set<uint64_t> mSyncedFrameNumbers GUARDED_BY(mMutex);
+ std::function<void(const nsecs_t)> mWaitForBufferReleaseCallback
+ GUARDED_BY(mWaitForBufferReleaseMutex);
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ // BufferReleaseChannel is used to communicate buffer releases from SurfaceFlinger to the
+ // client.
+ std::unique_ptr<gui::BufferReleaseChannel::ConsumerEndpoint> mBufferReleaseConsumer;
+ std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint> mBufferReleaseProducer;
+
+ void updateBufferReleaseProducer() REQUIRES(mMutex);
+ void drainBufferReleaseConsumer();
+
+ // BufferReleaseReader is used to do blocking but interruptible reads from the buffer
+ // release channel. To implement this, BufferReleaseReader owns an epoll file descriptor that
+ // is configured to wake up when either the BufferReleaseReader::ConsumerEndpoint or an eventfd
+ // becomes readable. Interrupts are necessary because a free buffer may become available for
+ // reasons other than a buffer release from the producer.
class BufferReleaseReader {
public:
- BufferReleaseReader() = default;
- BufferReleaseReader(std::unique_ptr<gui::BufferReleaseChannel::ConsumerEndpoint>);
- BufferReleaseReader& operator=(BufferReleaseReader&&);
+ explicit BufferReleaseReader(BLASTBufferQueue&);
+
+ BufferReleaseReader(const BufferReleaseReader&) = delete;
+ BufferReleaseReader& operator=(const BufferReleaseReader&) = delete;
// Block until we can read a buffer release message.
//
// Returns:
// * OK if a ReleaseCallbackId and Fence were successfully read.
// * WOULD_BLOCK if the blocking read was interrupted by interruptBlockingRead.
+ // * TIMED_OUT if the blocking read timed out.
// * UNKNOWN_ERROR if something went wrong.
status_t readBlocking(ReleaseCallbackId& outId, sp<Fence>& outReleaseFence,
- uint32_t& outMaxAcquiredBufferCount);
+ uint32_t& outMaxAcquiredBufferCount, nsecs_t timeout);
- // Signals the reader's eventfd to wake up any threads waiting on readBlocking.
void interruptBlockingRead();
+ void clearInterrupts();
private:
- std::mutex mMutex;
- std::unique_ptr<gui::BufferReleaseChannel::ConsumerEndpoint> mEndpoint GUARDED_BY(mMutex);
+ BLASTBufferQueue& mBbq;
+
android::base::unique_fd mEpollFd;
android::base::unique_fd mEventFd;
};
- // BufferReleaseChannel is used to communicate buffer releases from SurfaceFlinger to
- // the client. See BBQBufferQueueProducer::dequeueBuffer for details.
- std::shared_ptr<BufferReleaseReader> mBufferReleaseReader;
- std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint> mBufferReleaseProducer;
-
- class BufferReleaseThread {
- public:
- BufferReleaseThread() = default;
- ~BufferReleaseThread();
- void start(const sp<BLASTBufferQueue>&);
-
- private:
- std::shared_ptr<std::atomic_bool> mRunning;
- std::shared_ptr<BufferReleaseReader> mReader;
- };
-
- BufferReleaseThread mBufferReleaseThread;
+ std::optional<BufferReleaseReader> mBufferReleaseReader;
#endif
};
diff --git a/libs/gui/include/gui/BufferItem.h b/libs/gui/include/gui/BufferItem.h
index 218bb42..2f85c62 100644
--- a/libs/gui/include/gui/BufferItem.h
+++ b/libs/gui/include/gui/BufferItem.h
@@ -17,9 +17,12 @@
#ifndef ANDROID_GUI_BUFFERITEM_H
#define ANDROID_GUI_BUFFERITEM_H
+#include <optional>
+
#include <gui/HdrMetadata.h>
#include <ui/FenceTime.h>
+#include <ui/PictureProfileHandle.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -91,6 +94,10 @@
// mHdrMetadata is the HDR metadata associated with this buffer slot.
HdrMetadata mHdrMetadata;
+ // mPictureProfileHandle is a handle that points to a set of parameters that configure picture
+ // processing hardware to enhance the quality of buffer contents.
+ std::optional<PictureProfileHandle> mPictureProfileHandle;
+
// mFrameNumber is the number of the queued frame for this slot.
uint64_t mFrameNumber;
diff --git a/libs/gui/include/gui/BufferItemConsumer.h b/libs/gui/include/gui/BufferItemConsumer.h
index 6810eda..0bfa7b2 100644
--- a/libs/gui/include/gui/BufferItemConsumer.h
+++ b/libs/gui/include/gui/BufferItemConsumer.h
@@ -47,6 +47,16 @@
enum { INVALID_BUFFER_SLOT = BufferQueue::INVALID_BUFFER_SLOT };
enum { NO_BUFFER_AVAILABLE = BufferQueue::NO_BUFFER_AVAILABLE };
+ static std::tuple<sp<BufferItemConsumer>, sp<Surface>> create(
+ uint64_t consumerUsage, int bufferCount = DEFAULT_MAX_BUFFERS,
+ bool controlledByApp = false, bool isConsumerSurfaceFlinger = false);
+
+ static sp<BufferItemConsumer> create(const sp<IGraphicBufferConsumer>& consumer,
+ uint64_t consumerUsage,
+ int bufferCount = DEFAULT_MAX_BUFFERS,
+ bool controlledByApp = false)
+ __attribute((deprecated("Prefer ctors that create their own surface and consumer.")));
+
// Create a new buffer item consumer. The consumerUsage parameter determines
// the consumer usage flags passed to the graphics allocator. The
// bufferCount parameter specifies how many buffers can be locked for user
diff --git a/libs/gui/include/gui/BufferQueue.h b/libs/gui/include/gui/BufferQueue.h
index 0948c4d0..7b97e13 100644
--- a/libs/gui/include/gui/BufferQueue.h
+++ b/libs/gui/include/gui/BufferQueue.h
@@ -57,7 +57,7 @@
// reference in the BufferQueue class is because we're planning to expose the
// consumer side of a BufferQueue as a binder interface, which doesn't support
// weak references.
- class ProxyConsumerListener : public BnConsumerListener {
+ class ProxyConsumerListener : public IConsumerListener {
public:
explicit ProxyConsumerListener(const wp<ConsumerListener>& consumerListener);
~ProxyConsumerListener() override;
@@ -76,6 +76,9 @@
void onSetFrameRate(float frameRate, int8_t compatibility,
int8_t changeFrameRateStrategy) override;
#endif
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ void onSlotCountChanged(int slotCount) override;
+#endif
private:
// mConsumerListener is a weak reference to the IConsumerListener. This is
// the raison d'etre of ProxyConsumerListener.
diff --git a/libs/gui/include/gui/BufferQueueConsumer.h b/libs/gui/include/gui/BufferQueueConsumer.h
index 6aa801a..ab1231a 100644
--- a/libs/gui/include/gui/BufferQueueConsumer.h
+++ b/libs/gui/include/gui/BufferQueueConsumer.h
@@ -28,8 +28,7 @@
class BufferQueueCore;
-class BufferQueueConsumer : public BnGraphicBufferConsumer {
-
+class BufferQueueConsumer : public IGraphicBufferConsumer {
public:
explicit BufferQueueConsumer(const sp<BufferQueueCore>& core);
~BufferQueueConsumer() override;
@@ -65,13 +64,14 @@
// any references to the just-released buffer that it might have, as if it
// had received a onBuffersReleased() call with a mask set for the released
// buffer.
- //
- // Note that the dependencies on EGL will be removed once we switch to using
- // the Android HW Sync HAL.
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ virtual status_t releaseBuffer(int slot, uint64_t frameNumber,
+ const sp<Fence>& releaseFence) override;
+#else
virtual status_t releaseBuffer(int slot, uint64_t frameNumber,
const sp<Fence>& releaseFence, EGLDisplay display,
EGLSyncKHR fence);
-
+#endif
// connect connects a consumer to the BufferQueue. Only one
// consumer may be connected, and when that consumer disconnects the
// BufferQueue is placed into the "abandoned" state, causing most
@@ -96,11 +96,26 @@
// This should be called from the onBuffersReleased() callback.
virtual status_t getReleasedBuffers(uint64_t* outSlotMask);
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ // getReleasedBuffers sets the values pointed to by outSlotMask to the bits
+ // indicating which buffer slots have been released by the BufferQueue
+ // but have not yet been released by the consumer.
+ //
+ // This should be called from the onBuffersReleased() callback when
+ // allowUnlimitedSlots has been called.
+ virtual status_t getReleasedBuffersExtended(std::vector<bool>* outSlotMask) override;
+#endif
+
// setDefaultBufferSize is used to set the size of buffers returned by
// dequeueBuffer when a width and height of zero is requested. Default
// is 1x1.
virtual status_t setDefaultBufferSize(uint32_t width, uint32_t height);
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ // see IGraphicBufferConsumer::allowUnlimitedSlots
+ virtual status_t allowUnlimitedSlots(bool allowUnlimitedSlots) override;
+#endif
+
// see IGraphicBufferConsumer::setMaxBufferCount
virtual status_t setMaxBufferCount(int bufferCount);
@@ -152,6 +167,7 @@
// dump our state in a String
status_t dumpState(const String8& prefix, String8* outResult) const override;
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
// Functions required for backwards compatibility.
// These will be modified/renamed in IGraphicBufferConsumer and will be
// removed from this class at that time. See b/13306289.
@@ -161,6 +177,7 @@
const sp<Fence>& releaseFence) {
return releaseBuffer(buf, frameNumber, releaseFence, display, fence);
}
+#endif
virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,
bool controlledByApp) {
diff --git a/libs/gui/include/gui/BufferQueueCore.h b/libs/gui/include/gui/BufferQueueCore.h
index d5dd7c8..7f92a46 100644
--- a/libs/gui/include/gui/BufferQueueCore.h
+++ b/libs/gui/include/gui/BufferQueueCore.h
@@ -32,10 +32,11 @@
#include <utils/Trace.h>
#include <utils/Vector.h>
-#include <list>
-#include <set>
-#include <mutex>
#include <condition_variable>
+#include <list>
+#include <mutex>
+#include <set>
+#include <vector>
#define ATRACE_BUFFER_INDEX(index) \
do { \
@@ -80,10 +81,21 @@
BufferQueueCore();
virtual ~BufferQueueCore();
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+protected:
+ // Wake up any threads waiting for a buffer release. The BufferQueue mutex should always held
+ // when this method is called.
+ virtual void notifyBufferReleased() const;
+#endif
+
private:
// Dump our state in a string
void dumpState(const String8& prefix, String8* outResult) const;
+ // getTotalSlotCountLocked returns the total number of slots in use by the
+ // buffer queue at this time.
+ int getTotalSlotCountLocked() const;
+
// getMinUndequeuedBufferCountLocked returns the minimum number of buffers
// that must remain in a state other than DEQUEUED. The async parameter
// tells whether we're in asynchronous mode.
@@ -113,6 +125,10 @@
int getMaxBufferCountLocked(bool asyncMode,
bool dequeueBufferCannotBlock, int maxBufferCount) const;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ // This resizes mSlots to the given size, but only if it's increasing.
+ status_t extendSlotCountLocked(int size);
+#endif
// clearBufferSlotLocked frees the GraphicBuffer and sync resources for the
// given slot.
void clearBufferSlotLocked(int slot);
@@ -197,7 +213,7 @@
// mConnectedProducerListener will not trigger onBufferAttached() callback.
bool mBufferAttachedCbEnabled;
- // mSlots is an array of buffer slots that must be mirrored on the producer
+ // mSlots is a collection of buffer slots that must be mirrored on the producer
// side. This allows buffer ownership to be transferred between the producer
// and consumer without sending a GraphicBuffer over Binder. The entire
// array is initialized to NULL at construction time, and buffers are
@@ -259,8 +275,14 @@
// is specified.
android_dataspace mDefaultBufferDataSpace;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ // mAllowExtendedSlotCount is set by the consumer to permit the producer to
+ // request an unlimited number of slots.
+ bool mAllowExtendedSlotCount;
+#endif
+
// mMaxBufferCount is the limit on the number of buffers that will be
- // allocated at one time. This limit can be set by the consumer.
+ // allocated at one time.
int mMaxBufferCount;
// mMaxAcquiredBufferCount is the number of buffers that the consumer may
diff --git a/libs/gui/include/gui/BufferQueueDefs.h b/libs/gui/include/gui/BufferQueueDefs.h
index ffafb49..42cf439 100644
--- a/libs/gui/include/gui/BufferQueueDefs.h
+++ b/libs/gui/include/gui/BufferQueueDefs.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_GUI_BUFFERQUEUECOREDEFS_H
#define ANDROID_GUI_BUFFERQUEUECOREDEFS_H
+#include <com_android_graphics_libgui_flags.h>
#include <gui/BufferSlot.h>
#include <ui/BufferQueueDefs.h>
@@ -24,7 +25,11 @@
class BufferQueueCore;
namespace BufferQueueDefs {
- typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS];
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ typedef std::vector<BufferSlot> SlotsType;
+#else
+ typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS];
+#endif
} // namespace BufferQueueDefs
} // namespace android
diff --git a/libs/gui/include/gui/BufferQueueProducer.h b/libs/gui/include/gui/BufferQueueProducer.h
index 37a9607..50abadb 100644
--- a/libs/gui/include/gui/BufferQueueProducer.h
+++ b/libs/gui/include/gui/BufferQueueProducer.h
@@ -47,6 +47,11 @@
// flags indicating that previously-returned buffers are no longer valid.
virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ // see IGraphicsBufferProducer::extendSlotCount
+ virtual status_t extendSlotCount(int size) override;
+#endif
+
// see IGraphicsBufferProducer::setMaxDequeuedBufferCount
virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
@@ -218,6 +223,14 @@
// total maximum buffer count for the buffer queue (dequeued AND acquired)
status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers, int* maxBufferCount);
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
+ // Wait until a buffer has been released. The method may spuriously return OK when no buffer has
+ // been released. The BufferQueue mutex is passed in the locked state. It must be unlocked
+ // before waiting for a release and locked before returning.
+ virtual status_t waitForBufferRelease(std::unique_lock<std::mutex>& lock,
+ nsecs_t timeout) const;
+#endif
+
private:
// This is required by the IBinder::DeathRecipient interface
virtual void binderDied(const wp<IBinder>& who);
diff --git a/libs/gui/include/gui/BufferReleaseChannel.h b/libs/gui/include/gui/BufferReleaseChannel.h
index 51fe0b6..0edadec 100644
--- a/libs/gui/include/gui/BufferReleaseChannel.h
+++ b/libs/gui/include/gui/BufferReleaseChannel.h
@@ -69,7 +69,8 @@
sp<Fence>& outReleaseFence, uint32_t& maxAcquiredBufferCount);
private:
- std::vector<uint8_t> mFlattenedBuffer;
+ std::mutex mMutex;
+ std::vector<uint8_t> mFlattenedBuffer GUARDED_BY(mMutex);
};
class ProducerEndpoint : public Endpoint, public Parcelable {
diff --git a/libs/gui/include/gui/BufferSlot.h b/libs/gui/include/gui/BufferSlot.h
index 5b32710..e83d2e3 100644
--- a/libs/gui/include/gui/BufferSlot.h
+++ b/libs/gui/include/gui/BufferSlot.h
@@ -174,26 +174,30 @@
};
struct BufferSlot {
-
BufferSlot()
- : mGraphicBuffer(nullptr),
- mEglDisplay(EGL_NO_DISPLAY),
- mBufferState(),
- mRequestBufferCalled(false),
- mFrameNumber(0),
- mEglFence(EGL_NO_SYNC_KHR),
- mFence(Fence::NO_FENCE),
- mAcquireCalled(false),
- mNeedsReallocation(false) {
+ : mGraphicBuffer(nullptr),
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ mEglDisplay(EGL_NO_DISPLAY),
+#endif
+ mBufferState(),
+ mRequestBufferCalled(false),
+ mFrameNumber(0),
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ mEglFence(EGL_NO_SYNC_KHR),
+#endif
+ mFence(Fence::NO_FENCE),
+ mAcquireCalled(false),
+ mNeedsReallocation(false) {
}
// mGraphicBuffer points to the buffer allocated for this slot or is NULL
// if no buffer has been allocated.
sp<GraphicBuffer> mGraphicBuffer;
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
// mEglDisplay is the EGLDisplay used to create EGLSyncKHR objects.
EGLDisplay mEglDisplay;
-
+#endif
// mBufferState is the current state of this buffer slot.
BufferState mBufferState;
@@ -207,12 +211,14 @@
// may be released before their release fence is signaled).
uint64_t mFrameNumber;
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
// mEglFence is the EGL sync object that must signal before the buffer
// associated with this buffer slot may be dequeued. It is initialized
// to EGL_NO_SYNC_KHR when the buffer is created and may be set to a
// new sync object in releaseBuffer. (This is deprecated in favor of
// mFence, below.)
EGLSyncKHR mEglFence;
+#endif
// mFence is a fence which will signal when work initiated by the
// previous owner of the buffer is finished. When the buffer is FREE,
diff --git a/libs/gui/include/gui/Choreographer.h b/libs/gui/include/gui/Choreographer.h
index 2e5aa4a..5862967 100644
--- a/libs/gui/include/gui/Choreographer.h
+++ b/libs/gui/include/gui/Choreographer.h
@@ -103,7 +103,7 @@
virtual void handleMessage(const Message& message) override;
static void initJVM(JNIEnv* env);
- static Choreographer* getForThread();
+ static sp<Choreographer> getForThread();
static void signalRefreshRateCallbacks(nsecs_t vsyncPeriod) EXCLUDES(gChoreographers.lock);
static int64_t getStartTimeNanosForVsyncId(AVsyncId vsyncId) EXCLUDES(gChoreographers.lock);
virtual ~Choreographer() override EXCLUDES(gChoreographers.lock);
@@ -127,6 +127,7 @@
std::vector<FrameRateOverride> overrides) override;
void dispatchHdcpLevelsChanged(PhysicalDisplayId displayId, int32_t connectedLevel,
int32_t maxLevel) override;
+ void dispatchModeRejected(PhysicalDisplayId displayId, int32_t modeId) override;
void scheduleCallbacks();
diff --git a/libs/gui/include/gui/ConsumerBase.h b/libs/gui/include/gui/ConsumerBase.h
index e976aa4..fd67f09 100644
--- a/libs/gui/include/gui/ConsumerBase.h
+++ b/libs/gui/include/gui/ConsumerBase.h
@@ -98,6 +98,8 @@
status_t detachBuffer(const sp<GraphicBuffer>& buffer);
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+ status_t addReleaseFence(const sp<GraphicBuffer> buffer, const sp<Fence>& fence);
+
// See IGraphicBufferConsumer::setDefaultBufferSize
status_t setDefaultBufferSize(uint32_t width, uint32_t height);
@@ -121,9 +123,7 @@
// See IGraphicBufferConsumer::setMaxAcquiredBufferCount
status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);
-#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
status_t setConsumerIsProtected(bool isProtected);
-#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
// See IGraphicBufferConsumer::getSidebandStream
sp<NativeHandle> getSidebandStream() const;
@@ -139,7 +139,8 @@
ConsumerBase(const ConsumerBase&);
void operator=(const ConsumerBase&);
- void initialize(bool controlledByApp);
+ // Requires `this` to be sp/wp so must not be called from ctor.
+ void initialize();
protected:
// ConsumerBase constructs a new ConsumerBase object to consume image
@@ -185,7 +186,9 @@
virtual void onFrameDetached(const uint64_t bufferId) override;
virtual void onBuffersReleased() override;
virtual void onSidebandStreamChanged() override;
-
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ virtual void onSlotCountChanged(int slotCount) override;
+#endif
virtual int getSlotForBufferLocked(const sp<GraphicBuffer>& buffer);
virtual status_t detachBufferLocked(int slotIndex);
@@ -243,9 +246,16 @@
// must take place when a buffer is released back to the BufferQueue. If
// it is overridden the derived class's implementation must call
// ConsumerBase::releaseBufferLocked.
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ virtual status_t releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer);
+#else
virtual status_t releaseBufferLocked(int slot,
const sp<GraphicBuffer> graphicBuffer,
EGLDisplay display = EGL_NO_DISPLAY, EGLSyncKHR eglFence = EGL_NO_SYNC_KHR);
+#endif
+ // Required to complete initialization, so `final` lest overrides forget to
+ // delegate.
+ void onFirstRef() override final;
// returns true iff the slot still has the graphicBuffer in it.
bool stillTracking(int slot, const sp<GraphicBuffer> graphicBuffer);
@@ -284,7 +294,11 @@
// slot that has not yet been used. The buffer allocated to a slot will also
// be replaced if the requested buffer usage or geometry differs from that
// of the buffer allocated to a slot.
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ std::vector<Slot> mSlots;
+#else
Slot mSlots[BufferQueueDefs::NUM_BUFFER_SLOTS];
+#endif
// mAbandoned indicates that the BufferQueue will no longer be used to
// consume images buffers pushed to it using the IGraphicBufferProducer
@@ -318,6 +332,8 @@
// releaseBufferLocked.
sp<Fence> mPrevFinalReleaseFence;
+ const bool mIsControlledByApp;
+
// mMutex is the mutex used to prevent concurrent access to the member
// variables of ConsumerBase objects. It must be locked whenever the
// member variables are accessed or when any of the *Locked methods are
diff --git a/libs/gui/include/gui/CpuConsumer.h b/libs/gui/include/gui/CpuConsumer.h
index 2bba61b..995cdfb 100644
--- a/libs/gui/include/gui/CpuConsumer.h
+++ b/libs/gui/include/gui/CpuConsumer.h
@@ -31,6 +31,7 @@
class BufferQueue;
class GraphicBuffer;
class String8;
+class Surface;
/**
* CpuConsumer is a BufferQueue consumer endpoint that allows direct CPU
@@ -92,6 +93,13 @@
// Create a new CPU consumer. The maxLockedBuffers parameter specifies
// how many buffers can be locked for user access at the same time.
+ static std::tuple<sp<CpuConsumer>, sp<Surface>> create(size_t maxLockedBuffers,
+ bool controlledByApp = false,
+ bool isConsumerSurfaceFlinger = false);
+ static sp<CpuConsumer> create(const sp<IGraphicBufferConsumer>& bq, size_t maxLockedBuffers,
+ bool controlledByApp = false)
+ __attribute((deprecated("Prefer ctors that create their own surface and consumer.")));
+
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
CpuConsumer(size_t maxLockedBuffers, bool controlledByApp = false,
bool isConsumerSurfaceFlinger = false);
@@ -100,8 +108,8 @@
bool controlledByApp = false)
__attribute((deprecated("Prefer ctors that create their own surface and consumer.")));
#else
- CpuConsumer(const sp<IGraphicBufferConsumer>& bq,
- size_t maxLockedBuffers, bool controlledByApp = false);
+ CpuConsumer(const sp<IGraphicBufferConsumer>& bq, size_t maxLockedBuffers,
+ bool controlledByApp = false);
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
// Gets the next graphics buffer from the producer and locks it for CPU use,
diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h
index 82cd50c..b06ad07 100644
--- a/libs/gui/include/gui/DisplayEventDispatcher.h
+++ b/libs/gui/include/gui/DisplayEventDispatcher.h
@@ -68,6 +68,8 @@
virtual void dispatchHdcpLevelsChanged(PhysicalDisplayId displayId, int32_t connectedLevel,
int32_t maxLevel) = 0;
+ virtual void dispatchModeRejected(PhysicalDisplayId displayId, int32_t modeId) = 0;
+
bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId,
uint32_t* outCount, VsyncEventData* outVsyncEventData);
diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
index 4dbf9e1..f51390a 100644
--- a/libs/gui/include/gui/DisplayEventReceiver.h
+++ b/libs/gui/include/gui/DisplayEventReceiver.h
@@ -55,19 +55,20 @@
static_cast<uint32_t>(c4);
}
+enum class DisplayEventType : uint32_t {
+ DISPLAY_EVENT_VSYNC = fourcc('v', 's', 'y', 'n'),
+ DISPLAY_EVENT_HOTPLUG = fourcc('p', 'l', 'u', 'g'),
+ DISPLAY_EVENT_MODE_CHANGE = fourcc('m', 'o', 'd', 'e'),
+ DISPLAY_EVENT_MODE_REJECTION = fourcc('r', 'e', 'j', 'e'),
+ DISPLAY_EVENT_NULL = fourcc('n', 'u', 'l', 'l'),
+ DISPLAY_EVENT_FRAME_RATE_OVERRIDE = fourcc('r', 'a', 't', 'e'),
+ DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH = fourcc('f', 'l', 's', 'h'),
+ DISPLAY_EVENT_HDCP_LEVELS_CHANGE = fourcc('h', 'd', 'c', 'p'),
+};
+
// ----------------------------------------------------------------------------
class DisplayEventReceiver {
public:
- enum {
- DISPLAY_EVENT_VSYNC = fourcc('v', 's', 'y', 'n'),
- DISPLAY_EVENT_HOTPLUG = fourcc('p', 'l', 'u', 'g'),
- DISPLAY_EVENT_MODE_CHANGE = fourcc('m', 'o', 'd', 'e'),
- DISPLAY_EVENT_NULL = fourcc('n', 'u', 'l', 'l'),
- DISPLAY_EVENT_FRAME_RATE_OVERRIDE = fourcc('r', 'a', 't', 'e'),
- DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH = fourcc('f', 'l', 's', 'h'),
- DISPLAY_EVENT_HDCP_LEVELS_CHANGE = fourcc('h', 'd', 'c', 'p'),
- };
-
struct Event {
// We add __attribute__((aligned(8))) for nsecs_t fields because
// we need to make sure all fields are aligned the same with x86
@@ -76,7 +77,7 @@
// https://en.wikipedia.org/wiki/Data_structure_alignment
struct Header {
- uint32_t type;
+ DisplayEventType type;
PhysicalDisplayId displayId __attribute__((aligned(8)));
nsecs_t timestamp __attribute__((aligned(8)));
};
@@ -96,6 +97,10 @@
nsecs_t vsyncPeriod __attribute__((aligned(8)));
};
+ struct ModeRejection {
+ int32_t modeId;
+ };
+
struct FrameRateOverride {
uid_t uid __attribute__((aligned(8)));
float frameRateHz __attribute__((aligned(8)));
@@ -117,9 +122,10 @@
ModeChange modeChange;
FrameRateOverride frameRateOverride;
HdcpLevelsChange hdcpLevelsChange;
+ ModeRejection modeRejection;
};
};
- static_assert(sizeof(Event) == 216);
+ static_assert(sizeof(Event) == 224);
public:
/*
diff --git a/libs/gui/include/gui/DisplayLuts.h b/libs/gui/include/gui/DisplayLuts.h
new file mode 100644
index 0000000..187381c
--- /dev/null
+++ b/libs/gui/include/gui/DisplayLuts.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2024 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 <android-base/unique_fd.h>
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+#include <cutils/ashmem.h>
+#include <sys/mman.h>
+#include <algorithm>
+#include <ostream>
+#include <vector>
+
+namespace android::gui {
+
+struct DisplayLuts : public Parcelable {
+public:
+ struct Entry : public Parcelable {
+ Entry() {};
+ Entry(int32_t lutDimension, int32_t lutSize, int32_t lutSamplingKey)
+ : dimension(lutDimension), size(lutSize), samplingKey(lutSamplingKey) {}
+ int32_t dimension;
+ int32_t size;
+ int32_t samplingKey;
+
+ status_t writeToParcel(android::Parcel* parcel) const override;
+ status_t readFromParcel(const android::Parcel* parcel) override;
+ };
+
+ DisplayLuts() {}
+
+ DisplayLuts(base::unique_fd lutfd, std::vector<int32_t> lutoffsets,
+ std::vector<int32_t> lutdimensions, std::vector<int32_t> lutsizes,
+ std::vector<int32_t> lutsamplingKeys) {
+ fd = std::move(lutfd);
+ offsets = lutoffsets;
+ lutProperties.reserve(offsets.size());
+ for (size_t i = 0; i < lutoffsets.size(); i++) {
+ Entry entry{lutdimensions[i], lutsizes[i], lutsamplingKeys[i]};
+ lutProperties.emplace_back(entry);
+ }
+ }
+
+ status_t writeToParcel(android::Parcel* parcel) const override;
+ status_t readFromParcel(const android::Parcel* parcel) override;
+
+ const base::unique_fd& getLutFileDescriptor() const { return fd; }
+
+ std::vector<Entry> lutProperties;
+ std::vector<int32_t> offsets;
+
+private:
+ base::unique_fd fd;
+}; // struct DisplayLuts
+
+static inline void PrintTo(const std::vector<int32_t>& offsets, ::std::ostream* os) {
+ *os << "\n .offsets = {";
+ for (size_t i = 0; i < offsets.size(); i++) {
+ *os << offsets[i];
+ if (i != offsets.size() - 1) {
+ *os << ", ";
+ }
+ }
+ *os << "}";
+}
+
+static inline void PrintTo(const std::vector<DisplayLuts::Entry>& entries, ::std::ostream* os) {
+ *os << "\n .lutProperties = {\n";
+ for (auto& [dimension, size, samplingKey] : entries) {
+ *os << " Entry{"
+ << "dimension: " << dimension << ", size: " << size << ", samplingKey: " << samplingKey
+ << "}\n";
+ }
+ *os << " }";
+}
+
+static constexpr size_t kMaxPrintCount = 100;
+
+static inline void PrintTo(const std::vector<float>& buffer, size_t offset, int32_t dimension,
+ size_t size, ::std::ostream* os) {
+ size_t range = std::min(size, kMaxPrintCount);
+ *os << "{";
+ if (dimension == 1) {
+ for (size_t i = 0; i < range; i++) {
+ *os << buffer[offset + i];
+ if (i != range - 1) {
+ *os << ", ";
+ }
+ }
+ } else {
+ *os << "\n {R channel:";
+ for (size_t i = 0; i < range; i++) {
+ *os << buffer[offset + i];
+ if (i != range - 1) {
+ *os << ", ";
+ }
+ }
+ *os << "}\n {G channel:";
+ for (size_t i = 0; i < range; i++) {
+ *os << buffer[offset + size + i];
+ if (i != range - 1) {
+ *os << ", ";
+ }
+ }
+ *os << "}\n {B channel:";
+ for (size_t i = 0; i < range; i++) {
+ *os << buffer[offset + 2 * size + i];
+ if (i != range - 1) {
+ *os << ", ";
+ }
+ }
+ }
+ *os << "}";
+}
+
+static inline void PrintTo(const std::shared_ptr<DisplayLuts> luts, ::std::ostream* os) {
+ *os << "gui::DisplayLuts {";
+ auto& fd = luts->getLutFileDescriptor();
+ *os << "\n .pfd = " << fd.get();
+ if (fd.ok()) {
+ PrintTo(luts->offsets, os);
+ PrintTo(luts->lutProperties, os);
+ // decode luts
+ int32_t fullLength = luts->offsets[luts->offsets.size() - 1];
+ if (luts->lutProperties[luts->offsets.size() - 1].dimension == 1) {
+ fullLength += luts->lutProperties[luts->offsets.size() - 1].size;
+ } else {
+ fullLength += (luts->lutProperties[luts->offsets.size() - 1].size *
+ luts->lutProperties[luts->offsets.size() - 1].size *
+ luts->lutProperties[luts->offsets.size() - 1].size * 3);
+ }
+ size_t bufferSize = static_cast<size_t>(fullLength) * sizeof(float);
+ float* ptr = (float*)mmap(NULL, bufferSize, PROT_READ, MAP_SHARED, fd.get(), 0);
+ if (ptr == MAP_FAILED) {
+ *os << "\n .bufferdata cannot mmap!";
+ return;
+ }
+ std::vector<float> buffers(ptr, ptr + fullLength);
+ munmap(ptr, bufferSize);
+
+ *os << "\n .bufferdata = ";
+ for (size_t i = 0; i < luts->offsets.size(); i++) {
+ PrintTo(buffers, static_cast<size_t>(luts->offsets[i]),
+ luts->lutProperties[i].dimension,
+ static_cast<size_t>(luts->lutProperties[i].size), os);
+ }
+ }
+ *os << "\n }";
+}
+
+} // namespace android::gui
\ No newline at end of file
diff --git a/libs/gui/include/gui/Flags.h b/libs/gui/include/gui/Flags.h
index 735375a..446841b 100644
--- a/libs/gui/include/gui/Flags.h
+++ b/libs/gui/include/gui/Flags.h
@@ -17,8 +17,41 @@
#pragma once
#include <com_android_graphics_libgui_flags.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+class IGraphicBufferProducer;
+class Surface;
+namespace view {
+class Surface;
+}
#define WB_CAMERA3_AND_PROCESSORS_WITH_DEPENDENCIES \
(COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CAMERA3_AND_PROCESSORS) && \
COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ) && \
- COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS))
\ No newline at end of file
+ COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS))
+
+#define WB_LIBCAMERASERVICE_WITH_DEPENDENCIES \
+ (WB_CAMERA3_AND_PROCESSORS_WITH_DEPENDENCIES && \
+ COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_LIBCAMERASERVICE))
+
+#if WB_LIBCAMERASERVICE_WITH_DEPENDENCIES
+typedef android::Surface SurfaceType;
+typedef android::view::Surface ParcelableSurfaceType;
+#else
+typedef android::IGraphicBufferProducer SurfaceType;
+typedef android::sp<android::IGraphicBufferProducer> ParcelableSurfaceType;
+#endif
+
+namespace flagtools {
+sp<SurfaceType> surfaceToSurfaceType(const sp<Surface>& surface);
+ParcelableSurfaceType surfaceToParcelableSurfaceType(const sp<Surface>& surface);
+ParcelableSurfaceType toParcelableSurfaceType(const view::Surface& surface);
+sp<IGraphicBufferProducer> surfaceTypeToIGBP(const sp<SurfaceType>& surface);
+bool isSurfaceTypeValid(const sp<SurfaceType>& surface);
+ParcelableSurfaceType convertSurfaceTypeToParcelable(sp<SurfaceType> surface);
+sp<SurfaceType> convertParcelableSurfaceTypeToSurface(const ParcelableSurfaceType& surface);
+} // namespace flagtools
+
+} // namespace android
diff --git a/libs/gui/include/gui/GLConsumer.h b/libs/gui/include/gui/GLConsumer.h
index bfe3eb3..254d8ac 100644
--- a/libs/gui/include/gui/GLConsumer.h
+++ b/libs/gui/include/gui/GLConsumer.h
@@ -83,6 +83,20 @@
// If the constructor without the tex parameter is used, the GLConsumer is
// created in a detached state, and attachToContext must be called before
// calls to updateTexImage.
+ static std::tuple<sp<GLConsumer>, sp<Surface>> create(uint32_t tex, uint32_t textureTarget,
+ bool useFenceSync,
+ bool isControlledByApp);
+ static std::tuple<sp<GLConsumer>, sp<Surface>> create(uint32_t textureTarget, bool useFenceSync,
+ bool isControlledByApp);
+ static sp<GLConsumer> create(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
+ uint32_t textureTarget, bool useFenceSync, bool isControlledByApp)
+ __attribute((deprecated(
+ "Prefer create functions that create their own surface and consumer.")));
+ static sp<GLConsumer> create(const sp<IGraphicBufferConsumer>& bq, uint32_t textureTarget,
+ bool useFenceSync, bool isControlledByApp)
+ __attribute((deprecated(
+ "Prefer create functions that create their own surface and consumer.")));
+
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
GLConsumer(uint32_t tex, uint32_t textureTarget, bool useFenceSync, bool isControlledByApp);
@@ -266,26 +280,28 @@
virtual status_t acquireBufferLocked(BufferItem *item, nsecs_t presentWhen,
uint64_t maxFrameNumber = 0) override;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ virtual void onSlotCountChanged(int slotCount) override;
+#endif
// releaseBufferLocked overrides the ConsumerBase method to update the
// mEglSlots array in addition to the ConsumerBase.
- virtual status_t releaseBufferLocked(int slot,
- const sp<GraphicBuffer> graphicBuffer,
- EGLDisplay display, EGLSyncKHR eglFence) override;
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ virtual status_t releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer,
+ EGLDisplay display = EGL_NO_DISPLAY,
+ EGLSyncKHR eglFence = EGL_NO_SYNC_KHR) override;
status_t releaseBufferLocked(int slot,
const sp<GraphicBuffer> graphicBuffer, EGLSyncKHR eglFence) {
return releaseBufferLocked(slot, graphicBuffer, mEglDisplay, eglFence);
}
+#endif
struct PendingRelease {
- PendingRelease() : isPending(false), currentTexture(-1),
- graphicBuffer(), display(nullptr), fence(nullptr) {}
+ PendingRelease() : isPending(false), currentTexture(-1), graphicBuffer() {}
bool isPending;
int currentTexture;
sp<GraphicBuffer> graphicBuffer;
- EGLDisplay display;
- EGLSyncKHR fence;
};
// This releases the buffer in the slot referenced by mCurrentTexture,
@@ -465,16 +481,18 @@
// EGLSlot contains the information and object references that
// GLConsumer maintains about a BufferQueue buffer slot.
struct EglSlot {
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
EglSlot() : mEglFence(EGL_NO_SYNC_KHR) {}
-
+#endif
// mEglImage is the EGLImage created from mGraphicBuffer.
sp<EglImage> mEglImage;
-
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
// mFence is the EGL sync object that must signal before the buffer
// associated with this buffer slot may be dequeued. It is initialized
// to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
// on a compile-time option) set to a new sync object in updateTexImage.
EGLSyncKHR mEglFence;
+#endif
};
// mEglDisplay is the EGLDisplay with which this GLConsumer is currently
@@ -496,8 +514,11 @@
// slot that has not yet been used. The buffer allocated to a slot will also
// be replaced if the requested buffer usage or geometry differs from that
// of the buffer allocated to a slot.
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ std::vector<EglSlot> mEglSlots;
+#else
EglSlot mEglSlots[BufferQueueDefs::NUM_BUFFER_SLOTS];
-
+#endif
// mCurrentTexture is the buffer slot index of the buffer that is currently
// bound to the OpenGL texture. It is initialized to INVALID_BUFFER_SLOT,
// indicating that no buffer slot is currently bound to the texture. Note,
diff --git a/libs/gui/include/gui/IConsumerListener.h b/libs/gui/include/gui/IConsumerListener.h
index 51d3959..95e66c7 100644
--- a/libs/gui/include/gui/IConsumerListener.h
+++ b/libs/gui/include/gui/IConsumerListener.h
@@ -16,9 +16,6 @@
#pragma once
-#include <binder/IInterface.h>
-#include <binder/SafeInterface.h>
-
#include <utils/Errors.h>
#include <utils/RefBase.h>
@@ -98,27 +95,18 @@
virtual void onSetFrameRate(float /*frameRate*/, int8_t /*compatibility*/,
int8_t /*changeFrameRateStrategy*/) {}
#endif
-};
-#ifndef NO_BINDER
-class IConsumerListener : public ConsumerListener, public IInterface {
-public:
- DECLARE_META_INTERFACE(ConsumerListener)
-};
-
-class BnConsumerListener : public SafeBnInterface<IConsumerListener> {
-public:
- BnConsumerListener() : SafeBnInterface<IConsumerListener>("BnConsumerListener") {}
-
- status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
- uint32_t flags = 0) override;
-};
-
-#else
-class IConsumerListener : public ConsumerListener {
-};
-class BnConsumerListener : public IConsumerListener {
-};
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ // Notifies the consumer that IGraphicBufferProducer::extendSlotCount has
+ // been called and the total slot count has increased.
+ //
+ // This will only ever be called if
+ // IGraphicBufferConsumer::allowUnlimitedSlots has been called on the
+ // consumer.
+ virtual void onSlotCountChanged(int /* slotCount */) {}
#endif
+};
+
+class IConsumerListener : public ConsumerListener {};
} // namespace android
diff --git a/libs/gui/include/gui/IGraphicBufferConsumer.h b/libs/gui/include/gui/IGraphicBufferConsumer.h
index 0b92e7d..8272a59 100644
--- a/libs/gui/include/gui/IGraphicBufferConsumer.h
+++ b/libs/gui/include/gui/IGraphicBufferConsumer.h
@@ -16,6 +16,7 @@
#pragma once
+#include <com_android_graphics_libgui_flags.h>
#include <gui/OccupancyTracker.h>
#include <binder/IInterface.h>
@@ -35,15 +36,12 @@
class GraphicBuffer;
class IConsumerListener;
class NativeHandle;
-#ifndef NO_BINDER
-class IGraphicBufferConsumer : public IInterface {
-public:
- DECLARE_META_INTERFACE(GraphicBufferConsumer)
-#else
+
+/*
+ * See IGraphicBufferProducer for details on SLOT_COUNT.
+ */
class IGraphicBufferConsumer : public RefBase {
public:
-#endif
-
enum {
// Returned by releaseBuffer, after which the consumer must free any references to the
// just-released buffer that it might have.
@@ -92,7 +90,7 @@
//
// Return of a value other than NO_ERROR means an error has occurred:
// * BAD_VALUE - the given slot number is invalid, either because it is out of the range
- // [0, NUM_BUFFER_SLOTS) or because the slot it refers to is not
+ // [0, SLOT_COUNT) or because the slot it refers to is not
// currently acquired.
virtual status_t detachBuffer(int slot) = 0;
@@ -134,19 +132,17 @@
// * the buffer slot was invalid
// * the fence was NULL
// * the buffer slot specified is not in the acquired state
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ virtual status_t releaseBuffer(int buf, uint64_t frameNumber,
+ const sp<Fence>& releaseFence) = 0;
+#else
virtual status_t releaseBuffer(int buf, uint64_t frameNumber, EGLDisplay display,
EGLSyncKHR fence, const sp<Fence>& releaseFence) = 0;
- status_t releaseHelper(int buf, uint64_t frameNumber, const sp<Fence>& releaseFence) {
+ status_t releaseBuffer(int buf, uint64_t frameNumber, const sp<Fence>& releaseFence) {
return releaseBuffer(buf, frameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, releaseFence);
}
- // This is explicitly *not* the actual signature of IGBC::releaseBuffer, but:
- // 1) We have no easy way to send the EGL objects across Binder
- // 2) This has always been broken, probably because
- // 3) IGBC is rarely remoted
- // For now, we will choose to bury our heads in the sand and ignore this problem until such time
- // as we can finally finish converting away from EGL sync to native Android sync
- using ReleaseBuffer = decltype(&IGraphicBufferConsumer::releaseHelper);
+#endif
// consumerConnect connects a consumer to the BufferQueue. Only one consumer may be connected,
// and when that consumer disconnects the BufferQueue is placed into the "abandoned" state,
@@ -180,6 +176,19 @@
// * NO_INIT - the BufferQueue has been abandoned.
virtual status_t getReleasedBuffers(uint64_t* slotMask) = 0;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ // getReleasedBuffersExtended for each slot, sets slotMask[slot] to 1 if it
+ // corresponds to a released buffer slot. In particular, a released buffer
+ // is one that has been released by the BufferQueue but has not yet been
+ // released by the consumer.
+ //
+ // This should be called from the onBuffersReleased() callback.
+ //
+ // Return of a value other than NO_ERROR means an error has occurred:
+ // * NO_INIT - the BufferQueue has been abandoned.
+ virtual status_t getReleasedBuffersExtended(std::vector<bool>* slotMask) = 0;
+#endif
+
// setDefaultBufferSize is used to set the size of buffers returned by dequeueBuffer when a
// width and height of zero is requested. Default is 1x1.
//
@@ -187,6 +196,26 @@
// * BAD_VALUE - either w or h was zero
virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h) = 0;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ // allowUnlimitedSlots allows the producer to set the upper bound on slots.
+ //
+ // Must be called before the producer is connected. If the producer
+ // increases the slot count, an IConsumerListener::onSlotCountChanged
+ // update is sent.
+ //
+ // This can not be used with setMaxBufferCount. Calls after
+ // setMaxBufferCount will fail and calls to setMaxBufferCount after setting
+ // this to true will fail.
+ //
+ // Return of a value other than NO_ERROR means an error has occurred:
+ // * NO_INIT - the BufferQueue has been abandoned
+ // * INVALID_OPERATION - one of the following errors has occurred:
+ // * Producer has been connected
+ // * setMaxBufferCount has been called and shrunk the
+ // BufferQueue.
+ virtual status_t allowUnlimitedSlots(bool allowUnlimitedSlots) = 0;
+#endif
+
// setMaxBufferCount sets the maximum value for the number of buffers used in the BufferQueue
// (the initial default is NUM_BUFFER_SLOTS). If a call to setMaxAcquiredBufferCount (by the
// consumer), or a call to setAsyncMode or setMaxDequeuedBufferCount (by the producer), would
@@ -286,18 +315,4 @@
}
};
-#ifndef NO_BINDER
-class BnGraphicBufferConsumer : public SafeBnInterface<IGraphicBufferConsumer> {
-public:
- BnGraphicBufferConsumer()
- : SafeBnInterface<IGraphicBufferConsumer>("BnGraphicBufferConsumer") {}
-
- status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
- uint32_t flags = 0) override;
-};
-#else
-class BnGraphicBufferConsumer : public IGraphicBufferConsumer {
-};
-#endif
-
} // namespace android
diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h
index 3aac457..7accca6 100644
--- a/libs/gui/include/gui/IGraphicBufferProducer.h
+++ b/libs/gui/include/gui/IGraphicBufferProducer.h
@@ -19,6 +19,7 @@
#include <stdint.h>
#include <sys/types.h>
+#include <optional>
#include <utils/Errors.h>
#include <utils/RefBase.h>
@@ -28,6 +29,7 @@
#include <ui/BufferQueueDefs.h>
#include <ui/Fence.h>
#include <ui/GraphicBuffer.h>
+#include <ui/PictureProfileHandle.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -70,6 +72,14 @@
* dequeueBuffer() to get an empty buffer, fills it with data, then
* calls queueBuffer() to make it available to the consumer.
*
+ * BufferQueues have a size, which we'll refer to in other comments as
+ * SLOT_COUNT. Its default is 64 (NUM_BUFFER_SLOTS). It can be adjusted by
+ * the IGraphicBufferConsumer::setMaxBufferCount, or when
+ * IGraphicBufferConsumer::allowUnlimitedSlots is set to true, by
+ * IGraphicBufferProducer::extendSlotCount. The actual number of buffers in use
+ * is a function of various configurations, including whether we're in single
+ * buffer mode, the maximum dequeuable/aquirable buffers, and SLOT_COUNT.
+ *
* This class was previously called ISurfaceTexture.
*/
#ifndef NO_BINDER
@@ -104,7 +114,7 @@
// slot->buffer mapping so that it's not necessary to transfer a
// GraphicBuffer for every dequeue operation.
//
- // The slot must be in the range of [0, NUM_BUFFER_SLOTS).
+ // The slot must be in the range of [0, SLOT_COUNT).
//
// Return of a value other than NO_ERROR means an error has occurred:
// * NO_INIT - the buffer queue has been abandoned or the producer is not
@@ -114,6 +124,30 @@
// * buffer specified by the slot is not dequeued
virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) = 0;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ // extendSlotCount sets the maximum slot count (SLOT_COUNT) to the given
+ // size. This feature must be enabled by the consumer to function via
+ // IGraphicBufferConsumer::allowUnlimitedSlots. This must be called before
+ // the producer connects.
+ //
+ // After calling this, any slot can be returned in the [0, size) range.
+ // Callers are responsible for the allocation of the appropriate slots
+ // array for their own buffer cache.
+ //
+ // On success, the consumer is notified (so that it can increase its own
+ // slot cache).
+ //
+ // Return of a value other than NO_ERROR means that an error has occurred:
+ // * NO_INIT - the buffer queue has been abandoned
+ // * INVALID_OPERATION - one of the following conditions has occurred:
+ // * The producer is connected already
+ // * The consumer didn't call allowUnlimitedSlots
+ // * BAD_VALUE - The value is smaller than the previous max size
+ // (initialized to 64, then whatever the last call to this
+ // was)
+ virtual status_t extendSlotCount(int size);
+#endif
+
// setMaxDequeuedBufferCount sets the maximum number of buffers that can be
// dequeued by the producer at one time. If this method succeeds, any new
// buffer slots will be both unallocated and owned by the BufferQueue object
@@ -127,7 +161,7 @@
// will result in a BAD_VALUE error.
//
// The buffer count should be at least 1 (inclusive), but at most
- // (NUM_BUFFER_SLOTS - the minimum undequeued buffer count) (exclusive). The
+ // (SLOT_COUNT - the minimum undequeued buffer count) (exclusive). The
// minimum undequeued buffer count can be obtained by calling
// query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS).
//
@@ -237,8 +271,8 @@
// * NO_INIT - the buffer queue has been abandoned or the producer is not
// connected.
// * BAD_VALUE - the given slot number is invalid, either because it is
- // out of the range [0, NUM_BUFFER_SLOTS), or because the slot
- // it refers to is not currently dequeued and requested.
+ // out of the range [0, SLOT_COUNT), or because the slot it
+ // refers to is not currently dequeued and requested.
virtual status_t detachBuffer(int slot) = 0;
// detachNextBuffer is equivalent to calling dequeueBuffer, requestBuffer,
@@ -365,6 +399,14 @@
const HdrMetadata& getHdrMetadata() const { return hdrMetadata; }
void setHdrMetadata(const HdrMetadata& metadata) { hdrMetadata = metadata; }
+ const std::optional<PictureProfileHandle>& getPictureProfileHandle() const {
+ return pictureProfileHandle;
+ }
+ void setPictureProfileHandle(const PictureProfileHandle& profile) {
+ pictureProfileHandle = profile;
+ }
+ void clearPictureProfileHandle() { pictureProfileHandle = std::nullopt; }
+
int64_t timestamp{0};
int isAutoTimestamp{0};
android_dataspace dataSpace{HAL_DATASPACE_UNKNOWN};
@@ -377,6 +419,7 @@
bool getFrameTimestamps{false};
int slot{-1};
HdrMetadata hdrMetadata;
+ std::optional<PictureProfileHandle> pictureProfileHandle;
};
struct QueueBufferOutput : public Flattenable<QueueBufferOutput> {
@@ -403,7 +446,8 @@
uint64_t nextFrameNumber{0};
FrameEventHistoryDelta frameTimestamps;
bool bufferReplaced{false};
- int maxBufferCount{0};
+ int maxBufferCount{BufferQueueDefs::NUM_BUFFER_SLOTS};
+ bool isSlotExpansionAllowed{false};
status_t result{NO_ERROR};
};
@@ -419,7 +463,7 @@
// below). Any other properties (zero point, etc)
// are client-dependent, and should be documented by the client.
//
- // The slot must be in the range of [0, NUM_BUFFER_SLOTS).
+ // The slot must be in the range of [0, SLOT_COUNT).
//
// Upon success, the output will be filled with meaningful values
// (refer to the documentation below).
@@ -449,7 +493,7 @@
//
// The buffer is not queued for use by the consumer.
//
- // The slot must be in the range of [0, NUM_BUFFER_SLOTS).
+ // The slot must be in the range of [0, SLOT_COUNT).
//
// The buffer will not be overwritten until the fence signals. The fence
// will usually be the one obtained from dequeueBuffer.
diff --git a/libs/gui/include/gui/InputTransferToken.h b/libs/gui/include/gui/InputTransferToken.h
index 6530b50..fb4aaa7 100644
--- a/libs/gui/include/gui/InputTransferToken.h
+++ b/libs/gui/include/gui/InputTransferToken.h
@@ -25,7 +25,7 @@
namespace android {
struct InputTransferToken : public RefBase, Parcelable {
public:
- InputTransferToken() { mToken = new BBinder(); }
+ InputTransferToken() { mToken = sp<BBinder>::make(); }
InputTransferToken(const sp<IBinder>& token) { mToken = token; }
@@ -50,4 +50,4 @@
return token1->mToken == token2->mToken;
}
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 00065c8..c2680a4 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -26,6 +26,7 @@
#include <android/gui/LayerCaptureArgs.h>
#include <android/gui/TrustedPresentationThresholds.h>
#include <android/native_window.h>
+#include <gui/DisplayLuts.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/ITransactionCompletedListener.h>
#include <math/mat4.h>
@@ -46,6 +47,7 @@
#include <ui/BlurRegion.h>
#include <ui/GraphicTypes.h>
#include <ui/LayerStack.h>
+#include <ui/PictureProfileHandle.h>
#include <ui/Rect.h>
#include <ui/Region.h>
#include <ui/Rotation.h>
@@ -169,6 +171,10 @@
// Sets a property on this layer indicating that its visible region should be considered
// when computing TrustedPresentation Thresholds.
eCanOccludePresentation = 0x1000,
+ // Indicates that the SurfaceControl should recover from buffer stuffing when
+ // possible. This is the case when the SurfaceControl is the root SurfaceControl
+ // owned by ViewRootImpl.
+ eRecoverableFromBufferStuffing = 0x2000,
};
enum {
@@ -184,6 +190,7 @@
eCachingHintChanged = 0x00000200,
eDimmingEnabledChanged = 0x00000400,
eShadowRadiusChanged = 0x00000800,
+ eLutsChanged = 0x00001000,
eBufferCropChanged = 0x00002000,
eRelativeLayerChanged = 0x00004000,
eReparent = 0x00008000,
@@ -222,6 +229,9 @@
eExtendedRangeBrightnessChanged = 0x10000'00000000,
eEdgeExtensionChanged = 0x20000'00000000,
eBufferReleaseChannelChanged = 0x40000'00000000,
+ ePictureProfileHandleChanged = 0x80000'00000000,
+ eAppContentPriorityChanged = 0x100000'00000000,
+ eClientDrawnCornerRadiusChanged = 0x200000'00000000,
};
layer_state_t();
@@ -242,9 +252,9 @@
// Geometry updates.
static constexpr uint64_t GEOMETRY_CHANGES = layer_state_t::eBufferCropChanged |
layer_state_t::eBufferTransformChanged | layer_state_t::eCornerRadiusChanged |
- layer_state_t::eCropChanged | layer_state_t::eDestinationFrameChanged |
- layer_state_t::eMatrixChanged | layer_state_t::ePositionChanged |
- layer_state_t::eTransformToDisplayInverseChanged |
+ layer_state_t::eClientDrawnCornerRadiusChanged | layer_state_t::eCropChanged |
+ layer_state_t::eDestinationFrameChanged | layer_state_t::eMatrixChanged |
+ layer_state_t::ePositionChanged | layer_state_t::eTransformToDisplayInverseChanged |
layer_state_t::eTransparentRegionChanged | layer_state_t::eEdgeExtensionChanged;
// Buffer and related updates.
@@ -255,7 +265,7 @@
layer_state_t::eTransformToDisplayInverseChanged |
layer_state_t::eTransparentRegionChanged |
layer_state_t::eExtendedRangeBrightnessChanged |
- layer_state_t::eDesiredHdrHeadroomChanged;
+ layer_state_t::eDesiredHdrHeadroomChanged | layer_state_t::eLutsChanged;
// Content updates.
static constexpr uint64_t CONTENT_CHANGES = layer_state_t::BUFFER_CHANGES |
@@ -265,7 +275,8 @@
layer_state_t::eColorSpaceAgnosticChanged | layer_state_t::eColorTransformChanged |
layer_state_t::eCornerRadiusChanged | layer_state_t::eDimmingEnabledChanged |
layer_state_t::eHdrMetadataChanged | layer_state_t::eShadowRadiusChanged |
- layer_state_t::eStretchChanged;
+ layer_state_t::eStretchChanged |
+ layer_state_t::ePictureProfileHandleChanged | layer_state_t::eAppContentPriorityChanged;
// Changes which invalidates the layer's visible region in CE.
static constexpr uint64_t CONTENT_DIRTY = layer_state_t::CONTENT_CHANGES |
@@ -290,6 +301,11 @@
static constexpr uint64_t VISIBLE_REGION_CHANGES = layer_state_t::GEOMETRY_CHANGES |
layer_state_t::HIERARCHY_CHANGES | layer_state_t::eAlphaChanged;
+ // Changes that force GPU composition.
+ static constexpr uint64_t COMPOSITION_EFFECTS = layer_state_t::eBackgroundBlurRadiusChanged |
+ layer_state_t::eBlurRegionsChanged | layer_state_t::eCornerRadiusChanged |
+ layer_state_t::eShadowRadiusChanged | layer_state_t::eStretchChanged;
+
bool hasValidBuffer() const;
void sanitize(int32_t permissions);
@@ -318,6 +334,7 @@
uint8_t reserved;
matrix22_t matrix;
float cornerRadius;
+ float clientDrawnCornerRadius;
uint32_t backgroundBlurRadius;
sp<SurfaceControl> relativeLayerSurfaceControl;
@@ -410,12 +427,23 @@
float currentHdrSdrRatio = 1.f;
float desiredHdrSdrRatio = 1.f;
+ // Enhance the quality of the buffer contents by configurating a picture processing pipeline
+ // with values as specified by this picture profile.
+ PictureProfileHandle pictureProfileHandle{PictureProfileHandle::NONE};
+
+ // A value indicating the significance of the layer's content to the app's desired user
+ // experience. A higher value will result in more likelihood of getting access to limited
+ // resources, such as picture processing hardware.
+ int32_t appContentPriority = 0;
+
gui::CachingHint cachingHint = gui::CachingHint::Enabled;
TrustedPresentationThresholds trustedPresentationThresholds;
TrustedPresentationListener trustedPresentationListener;
std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint> bufferReleaseChannel;
+
+ std::shared_ptr<gui::DisplayLuts> luts;
};
class ComposerState {
@@ -474,12 +502,18 @@
Rect layerStackSpaceRect = Rect::EMPTY_RECT;
Rect orientedDisplaySpaceRect = Rect::EMPTY_RECT;
- // Exclusive to virtual displays: The sink surface into which the virtual display is rendered,
- // and an optional resolution that overrides its default dimensions.
- sp<IGraphicBufferProducer> surface;
+ // For physical displays, this is the resolution, which must match the active display mode. To
+ // change the resolution, the client must first call SurfaceControl.setDesiredDisplayModeSpecs
+ // with the new DesiredDisplayModeSpecs#defaultMode, then commit the matching width and height.
+ //
+ // For virtual displays, this is an optional resolution that overrides its default dimensions.
+ //
uint32_t width = 0;
uint32_t height = 0;
+ // For virtual displays, this is the sink surface into which the virtual display is rendered.
+ sp<IGraphicBufferProducer> surface;
+
status_t write(Parcel& output) const;
status_t read(const Parcel& input);
};
diff --git a/libs/gui/include/gui/StreamSplitter.h b/libs/gui/include/gui/StreamSplitter.h
index b4eef29..8176f75 100644
--- a/libs/gui/include/gui/StreamSplitter.h
+++ b/libs/gui/include/gui/StreamSplitter.h
@@ -37,7 +37,7 @@
// BufferQueue, where each buffer queued to the input is available to be
// acquired by each of the outputs, and is able to be dequeued by the input
// again only once all of the outputs have released it.
-class StreamSplitter : public BnConsumerListener {
+class StreamSplitter : public IConsumerListener {
public:
// createSplitter creates a new splitter, outSplitter, using inputQueue as
// the input BufferQueue. Output BufferQueues must be added using addOutput
@@ -153,6 +153,8 @@
size_t mReleaseCount;
};
+ friend class sp<StreamSplitter>;
+
// Only called from createSplitter
explicit StreamSplitter(const sp<IGraphicBufferConsumer>& inputQueue);
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 14a3513..755674d 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -558,7 +558,11 @@
// slot that has not yet been used. The buffer allocated to a slot will also
// be replaced if the requested buffer usage or geometry differs from that
// of the buffer allocated to a slot.
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ std::vector<BufferSlot> mSlots;
+#else
BufferSlot mSlots[NUM_BUFFER_SLOTS];
+#endif
// mReqWidth is the buffer width that will be requested at the next dequeue
// operation. It is initialized to 1.
@@ -732,6 +736,10 @@
std::vector<sp<GraphicBuffer>> mRemovedBuffers;
int mMaxBufferCount;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ bool mIsSlotExpansionAllowed;
+#endif
+
sp<IProducerListener> mListenerProxy;
// Get and flush the buffers of given slots, if the buffer in the slot
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 5ea0c16..60f16ae 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -38,6 +38,7 @@
#include <ui/EdgeExtensionEffect.h>
#include <ui/FrameStats.h>
#include <ui/GraphicTypes.h>
+#include <ui/PictureProfileHandle.h>
#include <ui/PixelFormat.h>
#include <ui/Rotation.h>
#include <ui/StaticDisplayInfo.h>
@@ -297,6 +298,10 @@
static status_t removeHdrLayerInfoListener(const sp<IBinder>& displayToken,
const sp<gui::IHdrLayerInfoListener>& listener);
+ static status_t addActivePictureListener(const sp<gui::IActivePictureListener>& listener);
+
+ static status_t removeActivePictureListener(const sp<gui::IActivePictureListener>& listener);
+
/*
* Sends a power boost to the composer. This function is asynchronous.
*
@@ -342,6 +347,15 @@
static bool flagEdgeExtensionEffectUseShader();
+ /**
+ * Returns how many picture profiles are supported by the display.
+ *
+ * displayToken
+ * The token of the display.
+ */
+ static status_t getMaxLayerPictureProfiles(const sp<IBinder>& displayToken,
+ int32_t* outMaxProfiles);
+
// ------------------------------------------------------------------------
// surface creation / destruction
@@ -437,10 +451,12 @@
static void mergeFrameTimelineInfo(FrameTimelineInfo& t, const FrameTimelineInfo& other);
// Tracks registered callbacks
sp<TransactionCompletedListener> mTransactionCompletedListener = nullptr;
+ // Prints debug logs when enabled.
+ bool mLogCallPoints = false;
protected:
- std::unordered_map<sp<IBinder>, ComposerState, IBinderHash> mComposerStates;
- SortedVector<DisplayState> mDisplayStates;
+ Vector<ComposerState> mComposerStates;
+ Vector<DisplayState> mDisplayStates;
std::unordered_map<sp<ITransactionCompletedListener>, CallbackInfo, TCLHash>
mListenerCallbacks;
std::vector<client_cache_t> mUncacheBuffers;
@@ -451,10 +467,7 @@
std::vector<uint64_t> mMergedTransactionIds;
uint64_t mId;
-
- bool mAnimation = false;
- bool mEarlyWakeupStart = false;
- bool mEarlyWakeupEnd = false;
+ uint32_t mFlags = 0;
// Indicates that the Transaction may contain buffers that should be cached. The reason this
// is only a guess is that buffers can be removed before cache is called. This is only a
@@ -551,6 +564,11 @@
Transaction& setCrop(const sp<SurfaceControl>& sc, const Rect& crop);
Transaction& setCrop(const sp<SurfaceControl>& sc, const FloatRect& crop);
Transaction& setCornerRadius(const sp<SurfaceControl>& sc, float cornerRadius);
+ // Sets the client drawn corner radius for the layer. If both a corner radius and a client
+ // radius are sent to SF, the client radius will be used. This indicates that the corner
+ // radius is drawn by the client and not SurfaceFlinger.
+ Transaction& setClientDrawnCornerRadius(const sp<SurfaceControl>& sc,
+ float clientDrawnCornerRadius);
Transaction& setBackgroundBlurRadius(const sp<SurfaceControl>& sc,
int backgroundBlurRadius);
Transaction& setBlurRegions(const sp<SurfaceControl>& sc,
@@ -602,7 +620,7 @@
Transaction& setExtendedRangeBrightness(const sp<SurfaceControl>& sc,
float currentBufferRatio, float desiredRatio);
Transaction& setDesiredHdrHeadroom(const sp<SurfaceControl>& sc, float desiredRatio);
- Transaction& setLuts(const sp<SurfaceControl>& sc, const base::unique_fd& lutFd,
+ Transaction& setLuts(const sp<SurfaceControl>& sc, base::unique_fd&& lutFd,
const std::vector<int32_t>& offsets,
const std::vector<int32_t>& dimensions,
const std::vector<int32_t>& sizes,
@@ -685,7 +703,8 @@
// ONLY FOR BLAST ADAPTER
Transaction& notifyProducerDisconnect(const sp<SurfaceControl>& sc);
- Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, const gui::WindowInfo& info);
+ Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc,
+ sp<gui::WindowInfoHandle> info);
Transaction& setFocusedWindow(const gui::FocusRequest& request);
Transaction& addWindowInfosReportedListener(
@@ -773,6 +792,20 @@
const sp<SurfaceControl>& sc,
const std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint>& channel);
+ /**
+ * Configures a surface control to use picture processing hardware, configured as specified
+ * by the picture profile, to enhance the quality of all subsequent buffer contents.
+ */
+ Transaction& setPictureProfileHandle(const sp<SurfaceControl>& sc,
+ const PictureProfileHandle& pictureProfileHandle);
+
+ /**
+ * Configures the relative importance of the contents of the layer with respect to the app's
+ * user experience. A lower priority value will give the layer preferred access to limited
+ * resources, such as picture processing, over a layer with a higher priority value.
+ */
+ Transaction& setContentPriority(const sp<SurfaceControl>& sc, int32_t contentPriority);
+
status_t setDisplaySurface(const sp<IBinder>& token,
const sp<IGraphicBufferProducer>& bufferProducer);
@@ -809,6 +842,7 @@
static void setDefaultApplyToken(sp<IBinder> applyToken);
static status_t sendSurfaceFlushJankDataTransaction(const sp<SurfaceControl>& sc);
+ void enableDebugLogCallPoints();
};
status_t clearLayerFrameStats(const sp<IBinder>& token) const;
diff --git a/libs/gui/include/gui/VsyncEventData.h b/libs/gui/include/gui/VsyncEventData.h
index b40a840..ced5130 100644
--- a/libs/gui/include/gui/VsyncEventData.h
+++ b/libs/gui/include/gui/VsyncEventData.h
@@ -36,6 +36,9 @@
// Size of frame timelines provided by the platform; max is kFrameTimelinesCapacity.
uint32_t frameTimelinesLength;
+ // Number of queued buffers to indicate if buffer stuffing mode is detected.
+ uint32_t numberQueuedBuffers;
+
struct alignas(8) FrameTimeline {
// The Vsync Id corresponsing to this vsync event. This will be used to
// populate ISurfaceComposer::setFrameTimelineVsync and
diff --git a/libs/gui/include/gui/WindowInfo.h b/libs/gui/include/gui/WindowInfo.h
index eb3be55..420dc21 100644
--- a/libs/gui/include/gui/WindowInfo.h
+++ b/libs/gui/include/gui/WindowInfo.h
@@ -150,8 +150,6 @@
static_cast<uint32_t>(os::InputConfig::NOT_FOCUSABLE),
NOT_TOUCHABLE =
static_cast<uint32_t>(os::InputConfig::NOT_TOUCHABLE),
- PREVENT_SPLITTING =
- static_cast<uint32_t>(os::InputConfig::PREVENT_SPLITTING),
DUPLICATE_TOUCH_TO_WALLPAPER =
static_cast<uint32_t>(os::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER),
IS_WALLPAPER =
@@ -220,9 +218,14 @@
// An alpha of 1.0 means fully opaque and 0.0 means fully transparent.
float alpha;
- // Transform applied to individual windows.
+ // Transform applied to individual windows for input.
+ // Maps display coordinates to the window's input coordinate space.
ui::Transform transform;
+ // Transform applied to get to the layer stack space of the cloned window for input.
+ // Maps display coordinates of the clone window to the layer stack space of the cloned window.
+ std::optional<ui::Transform> cloneLayerStackTransform;
+
/*
* This is filled in by the WM relative to the frame and then translated
* to absolute coordinates by SurfaceFlinger once the frame is computed.
diff --git a/libs/gui/include/gui/mock/GraphicBufferConsumer.h b/libs/gui/include/gui/mock/GraphicBufferConsumer.h
index 98f24c2..24d26b1 100644
--- a/libs/gui/include/gui/mock/GraphicBufferConsumer.h
+++ b/libs/gui/include/gui/mock/GraphicBufferConsumer.h
@@ -18,6 +18,7 @@
#include <gmock/gmock.h>
+#include <com_android_graphics_libgui_flags.h>
#include <gui/IGraphicBufferConsumer.h>
#include <utils/RefBase.h>
@@ -25,18 +26,24 @@
namespace android {
namespace mock {
-class GraphicBufferConsumer : public BnGraphicBufferConsumer, public virtual android::RefBase {
+class GraphicBufferConsumer : public IGraphicBufferConsumer {
public:
GraphicBufferConsumer();
- ~GraphicBufferConsumer() override;
+ ~GraphicBufferConsumer();
MOCK_METHOD3(acquireBuffer, status_t(BufferItem*, nsecs_t, uint64_t));
MOCK_METHOD1(detachBuffer, status_t(int));
MOCK_METHOD2(attachBuffer, status_t(int*, const sp<GraphicBuffer>&));
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ MOCK_METHOD3(releaseBuffer, status_t(int, uint64_t, const sp<Fence>&));
+#else
MOCK_METHOD5(releaseBuffer, status_t(int, uint64_t, EGLDisplay, EGLSyncKHR, const sp<Fence>&));
+#endif
MOCK_METHOD2(consumerConnect, status_t(const sp<IConsumerListener>&, bool));
MOCK_METHOD0(consumerDisconnect, status_t());
+ MOCK_METHOD1(allowUnlimitedSlots, status_t(bool));
MOCK_METHOD1(getReleasedBuffers, status_t(uint64_t*));
+ MOCK_METHOD1(getReleasedBuffersExtended, status_t(std::vector<bool>*));
MOCK_METHOD2(setDefaultBufferSize, status_t(uint32_t, uint32_t));
MOCK_METHOD1(setMaxBufferCount, status_t(int));
MOCK_METHOD1(setMaxAcquiredBufferCount, status_t(int));
diff --git a/libs/gui/include/gui/view/Surface.h b/libs/gui/include/gui/view/Surface.h
index 7ddac81..bd8704d 100644
--- a/libs/gui/include/gui/view/Surface.h
+++ b/libs/gui/include/gui/view/Surface.h
@@ -24,7 +24,9 @@
#include <binder/IBinder.h>
#include <binder/Parcelable.h>
+#include <gui/Flags.h>
#include <gui/IGraphicBufferProducer.h>
+#include <gui/Surface.h>
namespace android {
@@ -46,6 +48,30 @@
sp<IGraphicBufferProducer> graphicBufferProducer;
sp<IBinder> surfaceControlHandle;
+#if WB_LIBCAMERASERVICE_WITH_DEPENDENCIES
+ // functions used to convert to a parcelable Surface so it can be passed over binder.
+ static Surface fromSurface(const sp<android::Surface>& surface);
+ sp<android::Surface> toSurface() const;
+
+ status_t getUniqueId(/* out */ uint64_t* id) const;
+
+ bool isEmpty() const;
+
+ bool operator==(const Surface& other) const {
+ return graphicBufferProducer == other.graphicBufferProducer;
+ }
+ bool operator!=(const Surface& other) const { return !(*this == other); }
+ bool operator==(const sp<android::Surface> other) const {
+ if (other == nullptr) return graphicBufferProducer == nullptr;
+ return graphicBufferProducer == other->getIGraphicBufferProducer();
+ }
+ bool operator!=(const sp<android::Surface> other) const { return !(*this == other); }
+ bool operator<(const Surface& other) const {
+ return graphicBufferProducer < other.graphicBufferProducer;
+ }
+ bool operator>(const Surface& other) const { return other < *this; }
+#endif
+
virtual status_t writeToParcel(Parcel* parcel) const override;
virtual status_t readFromParcel(const Parcel* parcel) override;
diff --git a/libs/gui/libgui_flags.aconfig b/libs/gui/libgui_flags.aconfig
index 1c7e0e4..90d91ac 100644
--- a/libs/gui/libgui_flags.aconfig
+++ b/libs/gui/libgui_flags.aconfig
@@ -2,6 +2,14 @@
container: "system"
flag {
+ name: "apply_picture_profiles"
+ namespace: "tv_os_media"
+ description: "This flag controls sending picture profiles from BBQ to Composer HAL"
+ bug: "337330263"
+ is_fixed_read_only: true
+} # apply_picture_profiles
+
+flag {
name: "bq_setframerate"
namespace: "core_graphics"
description: "This flag controls plumbing setFrameRate thru BufferQueue"
@@ -123,3 +131,22 @@
bug: "359252619"
is_fixed_read_only: true
} # bq_producer_throttles_only_async_mode
+
+flag {
+ name: "bq_gl_fence_cleanup"
+ namespace: "core_graphics"
+ description: "Remove BufferQueueProducer::dequeue's wait on this fence (or the fence entirely) to prevent deadlocks"
+ bug: "339705065"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+} # bq_gl_fence_cleanup
+
+flag {
+ name: "wb_media_migration"
+ namespace: "core_graphics"
+ description: "Main flag for the warren buffers media migration."
+ bug: "340934031"
+ is_fixed_read_only: true
+} # wb_media_migration
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index f07747f..87051a7 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -55,6 +55,7 @@
"-DCOM_ANDROID_GRAPHICS_LIBGUI_FLAGS_BQ_EXTENDEDALLOCATE=true",
"-DCOM_ANDROID_GRAPHICS_LIBGUI_FLAGS_WB_CONSUMER_BASE_OWNS_BQ=true",
"-DCOM_ANDROID_GRAPHICS_LIBGUI_FLAGS_WB_PLATFORM_API_IMPROVEMENTS=true",
+ "-DCOM_ANDROID_GRAPHICS_LIBGUI_FLAGS_WB_UNLIMITED_SLOTS=true",
],
srcs: [
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index 53f4a36..b861c6d 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -81,7 +81,9 @@
public:
TestBLASTBufferQueue(const std::string& name, const sp<SurfaceControl>& surface, int width,
int height, int32_t format)
- : BLASTBufferQueue(name, surface, width, height, format) {}
+ : BLASTBufferQueue(name) {
+ update(surface, width, height, format);
+ }
void transactionCallback(nsecs_t latchTime, const sp<Fence>& presentFence,
const std::vector<SurfaceControlStats>& stats) override {
@@ -112,8 +114,8 @@
class BLASTBufferQueueHelper {
public:
BLASTBufferQueueHelper(const sp<SurfaceControl>& sc, int width, int height) {
- mBlastBufferQueueAdapter = new TestBLASTBufferQueue("TestBLASTBufferQueue", sc, width,
- height, PIXEL_FORMAT_RGBA_8888);
+ mBlastBufferQueueAdapter = sp<TestBLASTBufferQueue>::make("TestBLASTBufferQueue", sc, width,
+ height, PIXEL_FORMAT_RGBA_8888);
}
void update(const sp<SurfaceControl>& sc, int width, int height) {
diff --git a/libs/gui/tests/BufferItemConsumer_test.cpp b/libs/gui/tests/BufferItemConsumer_test.cpp
index 845a1ca..b980f88 100644
--- a/libs/gui/tests/BufferItemConsumer_test.cpp
+++ b/libs/gui/tests/BufferItemConsumer_test.cpp
@@ -22,14 +22,18 @@
#include <gui/BufferItemConsumer.h>
#include <gui/IProducerListener.h>
#include <gui/Surface.h>
+#include <ui/BufferQueueDefs.h>
#include <ui/GraphicBuffer.h>
+#include <unordered_set>
+
namespace android {
static constexpr int kWidth = 100;
static constexpr int kHeight = 100;
static constexpr int kMaxLockedBuffers = 3;
static constexpr int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+static constexpr int kUsage = GRALLOC_USAGE_SW_READ_RARELY;
static constexpr int kFrameSleepUs = 30 * 1000;
class BufferItemConsumerTest : public ::testing::Test {
@@ -56,14 +60,17 @@
};
void SetUp() override {
- mBIC = new BufferItemConsumer(kFormat, kMaxLockedBuffers, true);
+ mBuffers.resize(BufferQueueDefs::NUM_BUFFER_SLOTS);
+
+ sp<Surface> surface;
+ std::tie(mBIC, surface) = BufferItemConsumer::create(kUsage, kMaxLockedBuffers, true);
String8 name("BufferItemConsumer_Under_Test");
mBIC->setName(name);
mBFL = new BufferFreedListener(this);
mBIC->setBufferFreedListener(mBFL);
sp<IProducerListener> producerListener = new TrackingProducerListener(this);
- mProducer = mBIC->getSurface()->getIGraphicBufferProducer();
+ mProducer = surface->getIGraphicBufferProducer();
IGraphicBufferProducer::QueueBufferOutput bufferOutput;
ASSERT_EQ(NO_ERROR,
mProducer->connect(producerListener, NATIVE_WINDOW_API_CPU,
@@ -136,6 +143,11 @@
ASSERT_EQ(NO_ERROR, ret);
}
+ void DetachBuffer(int slot) {
+ ALOGD("detachBuffer: slot=%d", slot);
+ status_t ret = mBIC->detachBuffer(mBuffers[slot]);
+ ASSERT_EQ(NO_ERROR, ret);
+ }
std::mutex mMutex;
int mFreedBufferCount{0};
@@ -145,7 +157,7 @@
sp<BufferFreedListener> mBFL;
sp<IGraphicBufferProducer> mProducer;
sp<IGraphicBufferConsumer> mConsumer;
- sp<GraphicBuffer> mBuffers[BufferQueueDefs::NUM_BUFFER_SLOTS];
+ std::vector<sp<GraphicBuffer>> mBuffers;
};
// Test that detaching buffer from consumer side triggers onBufferFreed.
@@ -238,4 +250,52 @@
}
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+TEST_F(BufferItemConsumerTest, UnlimitedSlots_AcquireReleaseAll) {
+ ASSERT_EQ(OK, mProducer->extendSlotCount(256));
+ mBuffers.resize(256);
+
+ ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(100));
+
+ std::unordered_set<int> slots;
+ for (int i = 0; i < 100; i++) {
+ int slot;
+ DequeueBuffer(&slot);
+ slots.insert(slot);
+ }
+ EXPECT_EQ(100u, slots.size());
+
+ for (int dequeuedSlot : slots) {
+ QueueBuffer(dequeuedSlot);
+
+ int slot;
+ AcquireBuffer(&slot);
+ ReleaseBuffer(slot);
+ }
+}
+
+TEST_F(BufferItemConsumerTest, UnlimitedSlots_AcquireDetachAll) {
+ ASSERT_EQ(OK, mProducer->extendSlotCount(256));
+ mBuffers.resize(256);
+
+ ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(100));
+
+ std::unordered_set<int> slots;
+ for (int i = 0; i < 100; i++) {
+ int slot;
+ DequeueBuffer(&slot);
+ slots.insert(slot);
+ }
+ EXPECT_EQ(100u, slots.size());
+
+ for (int dequeuedSlot : slots) {
+ QueueBuffer(dequeuedSlot);
+
+ int slot;
+ AcquireBuffer(&slot);
+ DetachBuffer(slot);
+ }
+}
+#endif
+
} // namespace android
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 2e6ffcb..cfbb2e7 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -20,6 +20,8 @@
#include "Constants.h"
#include "MockConsumer.h"
+#include <EGL/egl.h>
+
#include <gui/BufferItem.h>
#include <gui/BufferItemConsumer.h>
#include <gui/BufferQueue.h>
@@ -27,8 +29,10 @@
#include <gui/Surface.h>
#include <ui/GraphicBuffer.h>
+#include <ui/PictureProfileHandle.h>
#include <android-base/properties.h>
+#include <android-base/unique_fd.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
@@ -42,8 +46,11 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <csignal>
#include <future>
+#include <optional>
#include <thread>
+#include <unordered_map>
#include <com_android_graphics_libgui_flags.h>
@@ -60,6 +67,15 @@
public:
protected:
+ void TearDown() override {
+ std::vector<std::function<void()>> teardownFns;
+ teardownFns.swap(mTeardownFns);
+
+ for (auto& fn : teardownFns) {
+ fn();
+ }
+ }
+
void GetMinUndequeuedBufferCount(int* bufferCount) {
ASSERT_TRUE(bufferCount != nullptr);
ASSERT_EQ(OK, mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
@@ -94,6 +110,7 @@
sp<IGraphicBufferProducer> mProducer;
sp<IGraphicBufferConsumer> mConsumer;
+ std::vector<std::function<void()>> mTeardownFns;
};
static const uint32_t TEST_DATA = 0x12345678u;
@@ -101,12 +118,14 @@
// XXX: Tests that fork a process to hold the BufferQueue must run before tests
// that use a local BufferQueue, or else Binder will get unhappy
//
-// In one instance this was a crash in the createBufferQueue where the
-// binder call to create a buffer allocator apparently got garbage back.
-// See b/36592665.
+// TODO(b/392945118): In one instance this was a crash in the createBufferQueue
+// where the binder call to create a buffer allocator apparently got garbage
+// back. See b/36592665.
TEST_F(BufferQueueTest, DISABLED_BufferQueueInAnotherProcess) {
const String16 PRODUCER_NAME = String16("BQTestProducer");
- const String16 CONSUMER_NAME = String16("BQTestConsumer");
+
+ base::unique_fd readfd, writefd;
+ ASSERT_TRUE(base::Pipe(&readfd, &writefd));
pid_t forkPid = fork();
ASSERT_NE(forkPid, -1);
@@ -118,23 +137,51 @@
BufferQueue::createBufferQueue(&producer, &consumer);
sp<IServiceManager> serviceManager = defaultServiceManager();
serviceManager->addService(PRODUCER_NAME, IInterface::asBinder(producer));
- serviceManager->addService(CONSUMER_NAME, IInterface::asBinder(consumer));
+
+ class ChildConsumerListener : public IConsumerListener {
+ public:
+ ChildConsumerListener(const sp<IGraphicBufferConsumer>& consumer,
+ base::unique_fd&& writeFd)
+ : mConsumer(consumer), mWriteFd(std::move(writeFd)) {}
+
+ virtual void onFrameAvailable(const BufferItem&) override {
+ BufferItem item;
+ ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
+
+ uint32_t* dataOut;
+ ASSERT_EQ(OK,
+ item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
+ reinterpret_cast<void**>(&dataOut)));
+ ASSERT_EQ(*dataOut, TEST_DATA);
+ ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
+
+ bool isOk = true;
+ write(mWriteFd, &isOk, sizeof(bool));
+ }
+ virtual void onBuffersReleased() override {}
+ virtual void onSidebandStreamChanged() override {}
+
+ private:
+ sp<IGraphicBufferConsumer> mConsumer;
+ base::unique_fd mWriteFd;
+ };
+
+ sp<ChildConsumerListener> mc =
+ sp<ChildConsumerListener>::make(consumer, std::move(writefd));
+ ASSERT_EQ(OK, consumer->consumerConnect(mc, false));
+
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
LOG_ALWAYS_FATAL("Shouldn't be here");
+ } else {
+ mTeardownFns.emplace_back([forkPid]() { kill(forkPid, SIGTERM); });
}
sp<IServiceManager> serviceManager = defaultServiceManager();
sp<IBinder> binderProducer = serviceManager->waitForService(PRODUCER_NAME);
mProducer = interface_cast<IGraphicBufferProducer>(binderProducer);
EXPECT_TRUE(mProducer != nullptr);
- sp<IBinder> binderConsumer =
- serviceManager->getService(CONSUMER_NAME);
- mConsumer = interface_cast<IGraphicBufferConsumer>(binderConsumer);
- EXPECT_TRUE(mConsumer != nullptr);
- sp<MockConsumer> mc(new MockConsumer);
- ASSERT_EQ(OK, mConsumer->consumerConnect(mc, false));
IGraphicBufferProducer::QueueBufferOutput output;
ASSERT_EQ(OK,
mProducer->connect(nullptr, NATIVE_WINDOW_API_CPU, false, &output));
@@ -158,14 +205,9 @@
NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
- BufferItem item;
- ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
-
- uint32_t* dataOut;
- ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
- reinterpret_cast<void**>(&dataOut)));
- ASSERT_EQ(*dataOut, TEST_DATA);
- ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
+ bool isOk;
+ read(readfd, &isOk, sizeof(bool));
+ ASSERT_TRUE(isOk);
}
TEST_F(BufferQueueTest, GetMaxBufferCountInQueueBufferOutput_Succeeds) {
@@ -424,8 +466,7 @@
ASSERT_EQ(BAD_VALUE, mConsumer->attachBuffer(&newSlot, nullptr));
ASSERT_EQ(OK, mConsumer->attachBuffer(&newSlot, item.mGraphicBuffer));
- ASSERT_EQ(OK, mConsumer->releaseBuffer(newSlot, 0, EGL_NO_DISPLAY,
- EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+ ASSERT_EQ(OK, mConsumer->releaseBuffer(newSlot, 0, Fence::NO_FENCE));
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
@@ -608,8 +649,7 @@
ASSERT_EQ(true, item.mQueuedBuffer);
ASSERT_EQ(false, item.mAutoRefresh);
- ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+ ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
// attempt to acquire a second time should return no buffer available
ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
@@ -652,8 +692,7 @@
ASSERT_EQ(i == 0, item.mQueuedBuffer);
ASSERT_EQ(true, item.mAutoRefresh);
- ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+ ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
}
// Repeatedly queue and dequeue a buffer from the producer side, it should
@@ -683,8 +722,7 @@
ASSERT_EQ(i == 0, item.mQueuedBuffer);
ASSERT_EQ(true, item.mAutoRefresh);
- ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+ ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
}
}
@@ -734,8 +772,7 @@
ASSERT_EQ(true, item.mQueuedBuffer);
ASSERT_EQ(false, item.mAutoRefresh);
- ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+ ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
// attempt to acquire a second time should return no buffer available
ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
@@ -873,8 +910,7 @@
for (size_t i = 0; i < 2; ++i) {
BufferItem item;
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
- ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+ ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
}
// Make sure we got the second buffer back
@@ -928,8 +964,7 @@
nullptr, nullptr));
ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
- ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+ ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
std::this_thread::sleep_for(16ms);
}
@@ -945,8 +980,7 @@
nullptr, nullptr));
ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
- ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+ ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
std::this_thread::sleep_for(16ms);
}
ASSERT_EQ(OK,
@@ -958,12 +992,10 @@
nullptr));
ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
- ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+ ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
std::this_thread::sleep_for(16ms);
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
- ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+ ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
// Sleep between segments
std::this_thread::sleep_for(500ms);
@@ -980,13 +1012,11 @@
nullptr, nullptr));
ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
- ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+ ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
std::this_thread::sleep_for(16ms);
}
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
- ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+ ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
// Now we read the segments
std::vector<OccupancyTracker::Segment> history;
@@ -1107,8 +1137,7 @@
// Acquire and free 1 buffer
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
- ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+ ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
int releasedSlot = item.mSlot;
// Acquire 1 buffer, leaving 1 filled buffer in queue
@@ -1375,8 +1404,7 @@
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
ASSERT_EQ(slot, item.mSlot);
ASSERT_NE(nullptr, item.mGraphicBuffer.get());
- ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+ ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
// Dequeue and queue the buffer again
ASSERT_EQ(OK,
@@ -1389,8 +1417,7 @@
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
ASSERT_EQ(slot, item.mSlot);
ASSERT_EQ(nullptr, item.mGraphicBuffer.get());
- ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+ ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
// Dequeue and queue the buffer again
ASSERT_EQ(OK,
@@ -1569,4 +1596,278 @@
EXPECT_EQ(ADATASPACE_UNKNOWN, dataSpace);
}
+TEST_F(BufferQueueTest, PassesThroughPictureProfileHandle) {
+ createBufferQueue();
+ sp<MockConsumer> mc(new MockConsumer);
+ mConsumer->consumerConnect(mc, false);
+
+ IGraphicBufferProducer::QueueBufferOutput qbo;
+ mProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false, &qbo);
+ mProducer->setMaxDequeuedBufferCount(2);
+ mConsumer->setMaxAcquiredBufferCount(2);
+
+ // First try to pass a valid picture profile handle
+ {
+ int slot;
+ sp<Fence> fence;
+ sp<GraphicBuffer> buf;
+ IGraphicBufferProducer::QueueBufferInput qbi(0, false, HAL_DATASPACE_UNKNOWN,
+ Rect(0, 0, 1, 1),
+ NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
+ Fence::NO_FENCE);
+ qbi.setPictureProfileHandle(PictureProfileHandle(1));
+
+ EXPECT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+ mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
+ nullptr, nullptr));
+ EXPECT_EQ(OK, mProducer->requestBuffer(slot, &buf));
+ EXPECT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
+
+ BufferItem item;
+ EXPECT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
+
+ ASSERT_TRUE(item.mPictureProfileHandle.has_value());
+ ASSERT_EQ(item.mPictureProfileHandle, PictureProfileHandle(1));
+ }
+
+ // Then validate that the picture profile handle isn't sticky and is reset for the next buffer
+ {
+ int slot;
+ sp<Fence> fence;
+ sp<GraphicBuffer> buf;
+ IGraphicBufferProducer::QueueBufferInput qbi(0, false, HAL_DATASPACE_UNKNOWN,
+ Rect(0, 0, 1, 1),
+ NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
+ Fence::NO_FENCE);
+
+ EXPECT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+ mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0, GRALLOC_USAGE_SW_READ_OFTEN,
+ nullptr, nullptr));
+ EXPECT_EQ(OK, mProducer->requestBuffer(slot, &buf));
+ EXPECT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
+
+ BufferItem item;
+ EXPECT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
+
+ ASSERT_FALSE(item.mPictureProfileHandle.has_value());
+ }
+}
+
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+struct MockUnlimitedSlotConsumer : public MockConsumer {
+ virtual void onSlotCountChanged(int size) override { mSize = size; }
+
+ std::optional<int> mSize;
+};
+
+TEST_F(BufferQueueTest, UnlimitedSlots_FailsWhenNotAllowed) {
+ createBufferQueue();
+
+ sp<MockUnlimitedSlotConsumer> mc = sp<MockUnlimitedSlotConsumer>::make();
+ EXPECT_EQ(OK, mConsumer->consumerConnect(mc, false));
+
+ EXPECT_EQ(INVALID_OPERATION, mProducer->extendSlotCount(64));
+ EXPECT_EQ(INVALID_OPERATION, mProducer->extendSlotCount(32));
+ EXPECT_EQ(INVALID_OPERATION, mProducer->extendSlotCount(128));
+
+ EXPECT_EQ(std::nullopt, mc->mSize);
+}
+
+TEST_F(BufferQueueTest, UnlimitedSlots_OnlyAllowedForExtensions) {
+ createBufferQueue();
+
+ sp<MockUnlimitedSlotConsumer> consumerListener = sp<MockUnlimitedSlotConsumer>::make();
+ EXPECT_EQ(OK, mConsumer->consumerConnect(consumerListener, false));
+ EXPECT_EQ(OK, mConsumer->allowUnlimitedSlots(true));
+
+ EXPECT_EQ(BAD_VALUE, mProducer->extendSlotCount(32));
+ EXPECT_EQ(OK, mProducer->extendSlotCount(64));
+ EXPECT_EQ(OK, mProducer->extendSlotCount(128));
+ EXPECT_EQ(128, *consumerListener->mSize);
+
+ EXPECT_EQ(OK, mProducer->extendSlotCount(128));
+ EXPECT_EQ(BAD_VALUE, mProducer->extendSlotCount(127));
+}
+
+class BufferQueueUnlimitedTest : public BufferQueueTest {
+protected:
+ static constexpr auto kMaxBufferCount = 128;
+ static constexpr auto kAcquirableBufferCount = 2;
+ static constexpr auto kDequeableBufferCount = kMaxBufferCount - kAcquirableBufferCount;
+
+ virtual void SetUp() override {
+ BufferQueueTest::SetUp();
+
+ createBufferQueue();
+ setUpConsumer();
+ setUpProducer();
+ }
+
+ void setUpConsumer() {
+ EXPECT_EQ(OK, mConsumer->consumerConnect(mConsumerListener, false));
+
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ EXPECT_EQ(OK, mConsumer->allowUnlimitedSlots(true));
+#endif
+ EXPECT_EQ(OK, mConsumer->setConsumerUsageBits(GraphicBuffer::USAGE_SW_READ_OFTEN));
+ EXPECT_EQ(OK, mConsumer->setDefaultBufferSize(10, 10));
+ EXPECT_EQ(OK, mConsumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888));
+ EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(kAcquirableBufferCount));
+ }
+
+ void setUpProducer() {
+ EXPECT_EQ(OK, mProducer->extendSlotCount(kMaxBufferCount));
+
+ IGraphicBufferProducer::QueueBufferOutput output;
+ EXPECT_EQ(OK,
+ mProducer->connect(mProducerListener, NATIVE_WINDOW_API_CPU,
+ /*producerControlledByApp*/ true, &output));
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+ ASSERT_TRUE(output.isSlotExpansionAllowed);
+#endif
+ ASSERT_EQ(OK, mProducer->setMaxDequeuedBufferCount(kDequeableBufferCount));
+ ASSERT_EQ(OK, mProducer->allowAllocation(true));
+ }
+
+ std::unordered_map<int, sp<Fence>> dequeueAll() {
+ std::unordered_map<int, sp<Fence>> slotsToFences;
+
+ for (int i = 0; i < kDequeableBufferCount; ++i) {
+ int slot;
+ sp<Fence> fence;
+ sp<GraphicBuffer> buffer;
+
+ status_t ret =
+ mProducer->dequeueBuffer(&slot, &fence, /*w*/ 0, /*h*/ 0, /*format*/ 0,
+ /*uint64_t*/ 0,
+ /*outBufferAge*/ nullptr, /*outTimestamps*/ nullptr);
+ if (ret & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
+ EXPECT_EQ(OK, mProducer->requestBuffer(slot, &buffer))
+ << "Unable to request buffer for slot " << slot;
+ }
+ EXPECT_FALSE(slotsToFences.contains(slot));
+ slotsToFences.emplace(slot, fence);
+ }
+ EXPECT_EQ(kDequeableBufferCount, (int)slotsToFences.size());
+ return slotsToFences;
+ }
+
+ sp<MockUnlimitedSlotConsumer> mConsumerListener = sp<MockUnlimitedSlotConsumer>::make();
+ sp<StubProducerListener> mProducerListener = sp<StubProducerListener>::make();
+};
+
+TEST_F(BufferQueueUnlimitedTest, ExpandOverridesConsumerMaxBuffers) {
+ createBufferQueue();
+ setUpConsumer();
+ EXPECT_EQ(OK, mConsumer->setMaxBufferCount(10));
+
+ setUpProducer();
+
+ EXPECT_EQ(kDequeableBufferCount, (int)dequeueAll().size());
+}
+
+TEST_F(BufferQueueUnlimitedTest, CanDetachAll) {
+ auto slotsToFences = dequeueAll();
+ for (auto& [slot, fence] : slotsToFences) {
+ EXPECT_EQ(OK, mProducer->detachBuffer(slot));
+ }
+}
+
+TEST_F(BufferQueueUnlimitedTest, CanCancelAll) {
+ auto slotsToFences = dequeueAll();
+ for (auto& [slot, fence] : slotsToFences) {
+ EXPECT_EQ(OK, mProducer->cancelBuffer(slot, fence));
+ }
+}
+
+TEST_F(BufferQueueUnlimitedTest, CanAcquireAndReleaseAll) {
+ auto slotsToFences = dequeueAll();
+ for (auto& [slot, fence] : slotsToFences) {
+ IGraphicBufferProducer::QueueBufferInput input;
+ input.fence = fence;
+
+ IGraphicBufferProducer::QueueBufferOutput output;
+ EXPECT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
+
+ BufferItem buffer;
+ EXPECT_EQ(OK, mConsumer->acquireBuffer(&buffer, 0));
+ EXPECT_EQ(OK,
+ mConsumer->releaseBuffer(buffer.mSlot, buffer.mFrameNumber, EGL_NO_DISPLAY,
+ EGL_NO_SYNC, buffer.mFence));
+ }
+}
+
+TEST_F(BufferQueueUnlimitedTest, CanAcquireAndDetachAll) {
+ auto slotsToFences = dequeueAll();
+ for (auto& [slot, fence] : slotsToFences) {
+ IGraphicBufferProducer::QueueBufferInput input;
+ input.fence = fence;
+
+ IGraphicBufferProducer::QueueBufferOutput output;
+ EXPECT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
+
+ BufferItem buffer;
+ EXPECT_EQ(OK, mConsumer->acquireBuffer(&buffer, 0));
+ EXPECT_EQ(OK, mConsumer->detachBuffer(buffer.mSlot));
+ }
+}
+
+TEST_F(BufferQueueUnlimitedTest, GetReleasedBuffersExtended) {
+ // First, acquire and release all the buffers so the consumer "knows" about
+ // them
+ auto slotsToFences = dequeueAll();
+
+ std::vector<bool> releasedSlots;
+ EXPECT_EQ(OK, mConsumer->getReleasedBuffersExtended(&releasedSlots));
+ for (auto& [slot, _] : slotsToFences) {
+ EXPECT_TRUE(releasedSlots[slot])
+ << "Slots that haven't been acquired will show up as released.";
+ }
+ for (auto& [slot, fence] : slotsToFences) {
+ IGraphicBufferProducer::QueueBufferInput input;
+ input.fence = fence;
+
+ IGraphicBufferProducer::QueueBufferOutput output;
+ EXPECT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
+
+ BufferItem buffer;
+ EXPECT_EQ(OK, mConsumer->acquireBuffer(&buffer, 0));
+ EXPECT_EQ(OK,
+ mConsumer->releaseBuffer(buffer.mSlot, buffer.mFrameNumber, EGL_NO_DISPLAY,
+ EGL_NO_SYNC_KHR, buffer.mFence));
+ }
+
+ EXPECT_EQ(OK, mConsumer->getReleasedBuffersExtended(&releasedSlots));
+ for (auto& [slot, _] : slotsToFences) {
+ EXPECT_FALSE(releasedSlots[slot])
+ << "Slots that have been acquired will show up as not released.";
+ }
+
+ // Then, alternatively cancel and detach (release) buffers. Only detached
+ // buffers should be returned by getReleasedBuffersExtended
+ slotsToFences = dequeueAll();
+ std::set<int> cancelledSlots;
+ std::set<int> detachedSlots;
+ bool cancel;
+ for (auto& [slot, fence] : slotsToFences) {
+ if (cancel) {
+ EXPECT_EQ(OK, mProducer->cancelBuffer(slot, fence));
+ cancelledSlots.insert(slot);
+ } else {
+ EXPECT_EQ(OK, mProducer->detachBuffer(slot));
+ detachedSlots.insert(slot);
+ }
+ cancel = !cancel;
+ }
+
+ EXPECT_EQ(OK, mConsumer->getReleasedBuffersExtended(&releasedSlots));
+ for (int slot : detachedSlots) {
+ EXPECT_TRUE(releasedSlots[slot]) << "Slots that are detached are released.";
+ }
+ for (int slot : cancelledSlots) {
+ EXPECT_FALSE(releasedSlots[slot])
+ << "Slots that are still held in the queue are not released.";
+ }
+}
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
} // namespace android
diff --git a/libs/gui/tests/BufferReleaseChannel_test.cpp b/libs/gui/tests/BufferReleaseChannel_test.cpp
index 11d122b..74f69e1 100644
--- a/libs/gui/tests/BufferReleaseChannel_test.cpp
+++ b/libs/gui/tests/BufferReleaseChannel_test.cpp
@@ -29,11 +29,11 @@
// Helper function to check if two file descriptors point to the same file.
bool is_same_file(int fd1, int fd2) {
- struct stat stat1;
+ struct stat stat1 {};
if (fstat(fd1, &stat1) != 0) {
return false;
}
- struct stat stat2;
+ struct stat stat2 {};
if (fstat(fd2, &stat2) != 0) {
return false;
}
@@ -42,7 +42,18 @@
} // namespace
-TEST(BufferReleaseChannelTest, MessageFlattenable) {
+class BufferReleaseChannelTest : public testing::Test {
+protected:
+ std::unique_ptr<BufferReleaseChannel::ConsumerEndpoint> mConsumer;
+ std::shared_ptr<BufferReleaseChannel::ProducerEndpoint> mProducer;
+
+ void SetUp() override {
+ ASSERT_EQ(OK,
+ BufferReleaseChannel::open("BufferReleaseChannelTest"s, mConsumer, mProducer));
+ }
+};
+
+TEST_F(BufferReleaseChannelTest, MessageFlattenable) {
ReleaseCallbackId releaseCallbackId{1, 2};
sp<Fence> releaseFence = sp<Fence>::make(memfd_create("fake-fence-fd", 0));
uint32_t maxAcquiredBufferCount = 5;
@@ -92,31 +103,23 @@
// Verify that the BufferReleaseChannel consume returns WOULD_BLOCK when there's no message
// available.
-TEST(BufferReleaseChannelTest, ConsumerEndpointIsNonBlocking) {
- std::unique_ptr<BufferReleaseChannel::ConsumerEndpoint> consumer;
- std::shared_ptr<BufferReleaseChannel::ProducerEndpoint> producer;
- ASSERT_EQ(OK, BufferReleaseChannel::open("test-channel"s, consumer, producer));
-
+TEST_F(BufferReleaseChannelTest, ConsumerEndpointIsNonBlocking) {
ReleaseCallbackId releaseCallbackId;
sp<Fence> releaseFence;
uint32_t maxAcquiredBufferCount;
ASSERT_EQ(WOULD_BLOCK,
- consumer->readReleaseFence(releaseCallbackId, releaseFence, maxAcquiredBufferCount));
+ mConsumer->readReleaseFence(releaseCallbackId, releaseFence, maxAcquiredBufferCount));
}
// Verify that we can write a message to the BufferReleaseChannel producer and read that message
// using the BufferReleaseChannel consumer.
-TEST(BufferReleaseChannelTest, ProduceAndConsume) {
- std::unique_ptr<BufferReleaseChannel::ConsumerEndpoint> consumer;
- std::shared_ptr<BufferReleaseChannel::ProducerEndpoint> producer;
- ASSERT_EQ(OK, BufferReleaseChannel::open("test-channel"s, consumer, producer));
-
+TEST_F(BufferReleaseChannelTest, ProduceAndConsume) {
sp<Fence> fence = sp<Fence>::make(memfd_create("fake-fence-fd", 0));
for (uint64_t i = 0; i < 64; i++) {
ReleaseCallbackId producerId{i, i + 1};
uint32_t maxAcquiredBufferCount = i + 2;
- ASSERT_EQ(OK, producer->writeReleaseFence(producerId, fence, maxAcquiredBufferCount));
+ ASSERT_EQ(OK, mProducer->writeReleaseFence(producerId, fence, maxAcquiredBufferCount));
}
for (uint64_t i = 0; i < 64; i++) {
@@ -127,7 +130,7 @@
sp<Fence> consumerFence;
uint32_t maxAcquiredBufferCount;
ASSERT_EQ(OK,
- consumer->readReleaseFence(consumerId, consumerFence, maxAcquiredBufferCount));
+ mConsumer->readReleaseFence(consumerId, consumerFence, maxAcquiredBufferCount));
ASSERT_EQ(expectedId, consumerId);
ASSERT_TRUE(is_same_file(fence->get(), consumerFence->get()));
@@ -135,4 +138,16 @@
}
}
+// Verify that BufferReleaseChannel::ConsumerEndpoint's socket can't be written to.
+TEST_F(BufferReleaseChannelTest, ConsumerSocketReadOnly) {
+ uint64_t data = 0;
+ ASSERT_EQ(-1, write(mConsumer->getFd().get(), &data, sizeof(uint64_t)));
+ ASSERT_EQ(errno, EPIPE);
+}
+
+// Verify that BufferReleaseChannel::ProducerEndpoint's socket can't be read from.
+TEST_F(BufferReleaseChannelTest, ProducerSocketWriteOnly) {
+ ASSERT_EQ(0, read(mProducer->getFd().get(), nullptr, sizeof(uint64_t)));
+}
+
} // namespace android
\ No newline at end of file
diff --git a/libs/gui/tests/Choreographer_test.cpp b/libs/gui/tests/Choreographer_test.cpp
index 8db48d2..314dea6 100644
--- a/libs/gui/tests/Choreographer_test.cpp
+++ b/libs/gui/tests/Choreographer_test.cpp
@@ -50,7 +50,7 @@
TEST_F(ChoreographerTest, InputCallbackBeforeAnimation) {
sp<Looper> looper = Looper::prepare(0);
- Choreographer* choreographer = Choreographer::getForThread();
+ sp<Choreographer> choreographer = Choreographer::getForThread();
VsyncCallback animationCb;
choreographer->postFrameCallbackDelayed(nullptr, nullptr, vsyncCallback, &animationCb, 0,
CALLBACK_ANIMATION);
@@ -83,4 +83,4 @@
animationCb.frameTime.count());
}
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/libs/gui/tests/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp
index f4239cb..482cfde 100644
--- a/libs/gui/tests/CpuConsumer_test.cpp
+++ b/libs/gui/tests/CpuConsumer_test.cpp
@@ -66,10 +66,9 @@
test_info->name(),
params.width, params.height,
params.maxLockedBuffers, params.format);
- mCC = new CpuConsumer(params.maxLockedBuffers);
+ std::tie(mCC, mSTC) = CpuConsumer::create(params.maxLockedBuffers);
String8 name("CpuConsumer_Under_Test");
mCC->setName(name);
- mSTC = mCC->getSurface();
mANW = mSTC;
}
@@ -803,6 +802,27 @@
::testing::ValuesIn(rgba8888TestSets));
#endif
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+TEST(CpuConsumerSlotTest, UnlimitedSlots_AcquireReleaseAll) {
+ sp<CpuConsumer> cpuConsumer = sp<CpuConsumer>::make(3);
+ sp<Surface> surface = cpuConsumer->getSurface();
+ sp<SurfaceListener> listener = sp<StubSurfaceListener>::make();
+ ASSERT_EQ(OK, surface->connect(NATIVE_WINDOW_API_CPU, listener));
+ ASSERT_EQ(OK, surface->setMaxDequeuedBufferCount(256));
+ std::vector<Surface::BatchBuffer> buffers(256);
+ EXPECT_EQ(OK, surface->dequeueBuffers(&buffers));
+
+ for (auto& buffer : buffers) {
+ sp<GraphicBuffer> graphicBuffer = GraphicBuffer::from(buffer.buffer);
+ sp<Fence> fence = sp<Fence>::make(buffer.fenceFd);
+ EXPECT_EQ(OK, surface->queueBuffer(graphicBuffer, fence));
+
+ CpuConsumer::LockedBuffer nativeBuffer;
+ EXPECT_EQ(OK, cpuConsumer->lockNextBuffer(&nativeBuffer));
+ EXPECT_EQ(OK, cpuConsumer->unlockBuffer(nativeBuffer));
+ }
+}
+#endif
} // namespace android
diff --git a/libs/gui/tests/DisconnectWaiter.h b/libs/gui/tests/DisconnectWaiter.h
index 6e6915b..3d5f633 100644
--- a/libs/gui/tests/DisconnectWaiter.h
+++ b/libs/gui/tests/DisconnectWaiter.h
@@ -29,7 +29,7 @@
// no way to forward the events. This DisconnectWaiter will not let the
// disconnect finish until finishDisconnect() is called. It will
// also block until a disconnect is called
-class DisconnectWaiter : public BnConsumerListener {
+class DisconnectWaiter : public IConsumerListener {
public:
DisconnectWaiter () :
mWaitForDisconnect(false),
diff --git a/libs/gui/tests/DisplayEventStructLayout_test.cpp b/libs/gui/tests/DisplayEventStructLayout_test.cpp
index 29eeaa8..791f471 100644
--- a/libs/gui/tests/DisplayEventStructLayout_test.cpp
+++ b/libs/gui/tests/DisplayEventStructLayout_test.cpp
@@ -36,15 +36,16 @@
CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncData.frameInterval, 8);
CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncData.preferredFrameTimelineIndex, 16);
CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncData.frameTimelinesLength, 20);
- CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncData.frameTimelines, 24);
- CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncData.frameTimelines[0].vsyncId, 24);
+ CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncData.numberQueuedBuffers, 24);
+ CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncData.frameTimelines, 32);
+ CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncData.frameTimelines[0].vsyncId, 32);
CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncData.frameTimelines[0].deadlineTimestamp,
- 32);
+ 40);
CHECK_OFFSET(DisplayEventReceiver::Event::VSync,
- vsyncData.frameTimelines[0].expectedPresentationTime, 40);
+ vsyncData.frameTimelines[0].expectedPresentationTime, 48);
// Also test the offsets of the last frame timeline. A loop is not used because the non-const
// index cannot be used in static_assert.
- const int lastFrameTimelineOffset = /* Start of array */ 24 +
+ const int lastFrameTimelineOffset = /* Start of array */ 32 +
(VsyncEventData::kFrameTimelinesCapacity - 1) * /* Size of FrameTimeline */ 24;
CHECK_OFFSET(DisplayEventReceiver::Event::VSync,
vsyncData.frameTimelines[VsyncEventData::kFrameTimelinesCapacity - 1].vsyncId,
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 7d0b512..cf05fd4 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -34,6 +34,8 @@
#include <binder/Parcel.h>
#include <binder/ProcessState.h>
+#include <gui/IConsumerListener.h>
+#include <gui/IGraphicBufferConsumer.h>
#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
@@ -75,7 +77,7 @@
if (input == nullptr) {
ALOGE("Failed to link to input service");
} else {
- ALOGE("Linked to input");
+ ALOGI("Linked to input");
}
return interface_cast<IInputFlinger>(input);
}
@@ -83,6 +85,7 @@
// We use the top 10 layers as a way to haphazardly place ourselves above anything else.
static const int LAYER_BASE = INT32_MAX - 10;
static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s;
+static constexpr float EPSILON = MotionEvent::ROUNDING_PRECISION;
class SynchronousWindowInfosReportedListener : public gui::BnWindowInfosReportedListener {
public:
@@ -112,91 +115,81 @@
mInputFlinger = getInputFlinger();
if (noInputChannel) {
- mInputInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, true);
+ mInputInfo->editInfo()->setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, true);
} else {
android::os::InputChannelCore tempChannel;
android::binder::Status result =
- mInputFlinger->createInputChannel("testchannels", &tempChannel);
+ mInputFlinger->createInputChannel(sc->getName() + " channel", &tempChannel);
if (!result.isOk()) {
ADD_FAILURE() << "binder call to createInputChannel failed";
}
mClientChannel = InputChannel::create(std::move(tempChannel));
- mInputInfo.token = mClientChannel->getConnectionToken();
+ mInputInfo->editInfo()->token = mClientChannel->getConnectionToken();
mInputConsumer = new InputConsumer(mClientChannel);
}
- mInputInfo.name = "Test info";
- mInputInfo.dispatchingTimeout = 5s;
- mInputInfo.globalScaleFactor = 1.0;
- mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height));
+ mInputInfo->editInfo()->name = "Test info";
+ mInputInfo->editInfo()->dispatchingTimeout = 5s;
+ mInputInfo->editInfo()->globalScaleFactor = 1.0;
+ mInputInfo->editInfo()->touchableRegion.orSelf(Rect(0, 0, width, height));
InputApplicationInfo aInfo;
aInfo.token = new BBinder();
aInfo.name = "Test app info";
aInfo.dispatchingTimeoutMillis =
std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count();
- mInputInfo.applicationInfo = aInfo;
+ mInputInfo->editInfo()->applicationInfo = aInfo;
}
static std::unique_ptr<InputSurface> makeColorInputSurface(const sp<SurfaceComposerClient>& scc,
- int width, int height) {
+ int width, int height,
+ const std::string& name) {
sp<SurfaceControl> surfaceControl =
- scc->createSurface(String8("Test Surface"), 0 /* bufHeight */, 0 /* bufWidth */,
+ scc->createSurface(String8(name.c_str()), 0 /* bufHeight */, 0 /* bufWidth */,
PIXEL_FORMAT_RGBA_8888,
ISurfaceComposerClient::eFXSurfaceEffect);
return std::make_unique<InputSurface>(surfaceControl, width, height);
}
static std::unique_ptr<InputSurface> makeBufferInputSurface(
- const sp<SurfaceComposerClient>& scc, int width, int height) {
+ const sp<SurfaceComposerClient>& scc, int width, int height,
+ const std::string& name = "Test Buffer Surface") {
sp<SurfaceControl> surfaceControl =
- scc->createSurface(String8("Test Buffer Surface"), width, height,
- PIXEL_FORMAT_RGBA_8888, 0 /* flags */);
+ scc->createSurface(String8(name.c_str()), width, height, PIXEL_FORMAT_RGBA_8888,
+ 0 /* flags */);
return std::make_unique<InputSurface>(surfaceControl, width, height);
}
static std::unique_ptr<InputSurface> makeContainerInputSurface(
- const sp<SurfaceComposerClient>& scc, int width, int height) {
+ const sp<SurfaceComposerClient>& scc, int width, int height,
+ const std::string& name = "Test Container Surface") {
sp<SurfaceControl> surfaceControl =
- scc->createSurface(String8("Test Container Surface"), 0 /* bufHeight */,
- 0 /* bufWidth */, PIXEL_FORMAT_RGBA_8888,
+ scc->createSurface(String8(name.c_str()), 0 /* bufHeight */, 0 /* bufWidth */,
+ PIXEL_FORMAT_RGBA_8888,
ISurfaceComposerClient::eFXSurfaceContainer);
return std::make_unique<InputSurface>(surfaceControl, width, height);
}
static std::unique_ptr<InputSurface> makeContainerInputSurfaceNoInputChannel(
- const sp<SurfaceComposerClient>& scc, int width, int height) {
+ const sp<SurfaceComposerClient>& scc, int width, int height,
+ const std::string& name = "Test Container Surface") {
sp<SurfaceControl> surfaceControl =
- scc->createSurface(String8("Test Container Surface"), 100 /* height */,
- 100 /* width */, PIXEL_FORMAT_RGBA_8888,
+ scc->createSurface(String8(name.c_str()), 100 /* height */, 100 /* width */,
+ PIXEL_FORMAT_RGBA_8888,
ISurfaceComposerClient::eFXSurfaceContainer);
return std::make_unique<InputSurface>(surfaceControl, width, height,
true /* noInputChannel */);
}
static std::unique_ptr<InputSurface> makeCursorInputSurface(
- const sp<SurfaceComposerClient>& scc, int width, int height) {
+ const sp<SurfaceComposerClient>& scc, int width, int height,
+ const std::string& name = "Test Cursor Surface") {
sp<SurfaceControl> surfaceControl =
- scc->createSurface(String8("Test Cursor Surface"), 0 /* bufHeight */,
- 0 /* bufWidth */, PIXEL_FORMAT_RGBA_8888,
- ISurfaceComposerClient::eCursorWindow);
+ scc->createSurface(String8(name.c_str()), 0 /* bufHeight */, 0 /* bufWidth */,
+ PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eCursorWindow);
return std::make_unique<InputSurface>(surfaceControl, width, height);
}
- InputEvent* consumeEvent(std::chrono::milliseconds timeout = 3000ms) {
- mClientChannel->waitForMessage(timeout);
-
- InputEvent* ev;
- uint32_t seqId;
- status_t consumed = mInputConsumer->consume(&mInputEventFactory, true, -1, &seqId, &ev);
- if (consumed != OK) {
- return nullptr;
- }
- status_t status = mInputConsumer->sendFinishedSignal(seqId, true);
- EXPECT_EQ(OK, status) << "Could not send finished signal";
- return ev;
- }
-
void assertFocusChange(bool hasFocus) {
InputEvent* ev = consumeEvent();
ASSERT_NE(ev, nullptr);
@@ -211,8 +204,8 @@
ASSERT_EQ(InputEventType::MOTION, ev->getType());
MotionEvent* mev = static_cast<MotionEvent*>(ev);
EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, mev->getAction());
- EXPECT_EQ(x, mev->getX(0));
- EXPECT_EQ(y, mev->getY(0));
+ EXPECT_NEAR(x, mev->getX(0), EPSILON);
+ EXPECT_NEAR(y, mev->getY(0), EPSILON);
EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS);
ev = consumeEvent();
@@ -294,7 +287,7 @@
transactionBody) {
SurfaceComposerClient::Transaction t;
transactionBody(t, mSurfaceControl);
- t.apply(true);
+ t.apply(/*synchronously=*/true);
}
virtual void showAt(int x, int y, Rect crop = Rect(0, 0, 100, 100)) {
@@ -307,30 +300,46 @@
t.setAlpha(mSurfaceControl, 1);
auto reportedListener = sp<SynchronousWindowInfosReportedListener>::make();
t.addWindowInfosReportedListener(reportedListener);
- t.apply();
+ t.apply(/*synchronously=*/true);
reportedListener->wait();
}
void requestFocus(ui::LogicalDisplayId displayId = ui::LogicalDisplayId::DEFAULT) {
SurfaceComposerClient::Transaction t;
FocusRequest request;
- request.token = mInputInfo.token;
- request.windowName = mInputInfo.name;
+ request.token = mInputInfo->getInfo()->token;
+ request.windowName = mInputInfo->getInfo()->name;
request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
request.displayId = displayId.val();
t.setFocusedWindow(request);
- t.apply(true);
+ t.apply(/*synchronously=*/true);
}
public:
+ // But should be private
+ sp<gui::WindowInfoHandle> mInputInfo = sp<gui::WindowInfoHandle>::make();
sp<SurfaceControl> mSurfaceControl;
+
+private:
std::shared_ptr<InputChannel> mClientChannel;
sp<IInputFlinger> mInputFlinger;
- WindowInfo mInputInfo;
-
PreallocatedInputEventFactory mInputEventFactory;
InputConsumer* mInputConsumer;
+
+ InputEvent* consumeEvent(std::chrono::milliseconds timeout = 3000ms) {
+ mClientChannel->waitForMessage(timeout);
+
+ InputEvent* ev;
+ uint32_t seqId;
+ status_t consumed = mInputConsumer->consume(&mInputEventFactory, true, -1, &seqId, &ev);
+ if (consumed != OK) {
+ return nullptr;
+ }
+ status_t status = mInputConsumer->sendFinishedSignal(seqId, true);
+ EXPECT_EQ(OK, status) << "Could not send finished signal";
+ return ev;
+ }
};
class BlastInputSurface : public InputSurface {
@@ -363,7 +372,7 @@
transactionBody) override {
SurfaceComposerClient::Transaction t;
transactionBody(t, mParentSurfaceControl);
- t.apply(true);
+ t.apply(/*synchronously=*/true);
}
void showAt(int x, int y, Rect crop = Rect(0, 0, 100, 100)) override {
@@ -377,7 +386,7 @@
t.setInputWindowInfo(mSurfaceControl, mInputInfo);
t.setCrop(mSurfaceControl, crop);
t.setAlpha(mSurfaceControl, 1);
- t.apply(true);
+ t.apply(/*synchronously=*/true);
}
private:
@@ -408,8 +417,9 @@
void TearDown() { mComposerClient->dispose(); }
- std::unique_ptr<InputSurface> makeSurface(int width, int height) {
- return InputSurface::makeColorInputSurface(mComposerClient, width, height);
+ std::unique_ptr<InputSurface> makeSurface(int width, int height,
+ const std::string& name = "Test Surface") const {
+ return InputSurface::makeColorInputSurface(mComposerClient, width, height, name);
}
void postBuffer(const sp<SurfaceControl>& layer, int32_t w, int32_t h) {
@@ -417,7 +427,7 @@
BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE;
sp<GraphicBuffer> buffer =
new GraphicBuffer(w, h, PIXEL_FORMAT_RGBA_8888, 1, usageFlags, "test");
- Transaction().setBuffer(layer, buffer).apply(true);
+ Transaction().setBuffer(layer, buffer).apply(/*synchronously=*/true);
usleep(mBufferPostDelay);
}
@@ -458,7 +468,7 @@
injectTap(101, 101);
- EXPECT_NE(surface->consumeEvent(), nullptr);
+ surface->expectTap(1, 1);
}
/**
@@ -468,10 +478,10 @@
* reverse order.
*/
TEST_F(InputSurfacesTest, input_respects_positioning) {
- std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
+ std::unique_ptr<InputSurface> surface = makeSurface(100, 100, "Left Surface");
surface->showAt(100, 100);
- std::unique_ptr<InputSurface> surface2 = makeSurface(100, 100);
+ std::unique_ptr<InputSurface> surface2 = makeSurface(100, 100, "Right Surface");
surface2->showAt(200, 200);
injectTap(201, 201);
@@ -491,8 +501,8 @@
}
TEST_F(InputSurfacesTest, input_respects_layering) {
- std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
- std::unique_ptr<InputSurface> surface2 = makeSurface(100, 100);
+ std::unique_ptr<InputSurface> surface = makeSurface(100, 100, "Test Surface 1");
+ std::unique_ptr<InputSurface> surface2 = makeSurface(100, 100, "Test Surface 2");
surface->showAt(10, 10);
surface2->showAt(10, 10);
@@ -517,11 +527,11 @@
// (such as shadows in dialogs). Inputs sent to the client are offset such that 0,0 is the start
// of the client content.
TEST_F(InputSurfacesTest, input_respects_surface_insets) {
- std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
- std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
+ std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100, "Background Surface");
+ std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100, "Foreground Surface");
bgSurface->showAt(100, 100);
- fgSurface->mInputInfo.surfaceInset = 5;
+ fgSurface->mInputInfo->editInfo()->surfaceInset = 5;
fgSurface->showAt(100, 100);
injectTap(106, 106);
@@ -532,12 +542,12 @@
}
TEST_F(InputSurfacesTest, input_respects_surface_insets_with_replaceTouchableRegionWithCrop) {
- std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
- std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
+ std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100, "Background Surface");
+ std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100, "Foreground Surface");
bgSurface->showAt(100, 100);
- fgSurface->mInputInfo.surfaceInset = 5;
- fgSurface->mInputInfo.replaceTouchableRegionWithCrop = true;
+ fgSurface->mInputInfo->editInfo()->surfaceInset = 5;
+ fgSurface->mInputInfo->editInfo()->replaceTouchableRegionWithCrop = true;
fgSurface->showAt(100, 100);
injectTap(106, 106);
@@ -549,11 +559,11 @@
// Ensure a surface whose insets are cropped, handles the touch offset correctly. ref:b/120413463
TEST_F(InputSurfacesTest, input_respects_cropped_surface_insets) {
- std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100);
- std::unique_ptr<InputSurface> childSurface = makeSurface(100, 100);
+ std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100, "Parent Surface");
+ std::unique_ptr<InputSurface> childSurface = makeSurface(100, 100, "Child Surface");
parentSurface->showAt(100, 100);
- childSurface->mInputInfo.surfaceInset = 10;
+ childSurface->mInputInfo->editInfo()->surfaceInset = 10;
childSurface->showAt(100, 100);
childSurface->doTransaction([&](auto& t, auto& sc) {
@@ -570,11 +580,11 @@
// Ensure a surface whose insets are scaled, handles the touch offset correctly.
TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets) {
- std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
- std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
+ std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100, "Background Surface");
+ std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100, "Foreground Surface");
bgSurface->showAt(100, 100);
- fgSurface->mInputInfo.surfaceInset = 5;
+ fgSurface->mInputInfo->editInfo()->surfaceInset = 5;
fgSurface->showAt(100, 100);
fgSurface->doTransaction([&](auto& t, auto& sc) { t.setMatrix(sc, 2.0, 0, 0, 4.0); });
@@ -588,12 +598,12 @@
}
TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets_overflow) {
- std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
- std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
+ std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100, "Background Surface");
+ std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100, "Foreground Surface");
bgSurface->showAt(100, 100);
// In case we pass the very big inset without any checking.
- fgSurface->mInputInfo.surfaceInset = INT32_MAX;
+ fgSurface->mInputInfo->editInfo()->surfaceInset = INT32_MAX;
fgSurface->showAt(100, 100);
fgSurface->doTransaction([&](auto& t, auto& sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); });
@@ -606,28 +616,29 @@
TEST_F(InputSurfacesTest, touchable_region) {
std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
- surface->mInputInfo.touchableRegion.set(Rect{19, 29, 21, 31});
+ surface->mInputInfo->editInfo()->touchableRegion.set(Rect{19, 29, 21, 31});
surface->showAt(11, 22);
// A tap within the surface but outside the touchable region should not be sent to the surface.
injectTap(20, 30);
- EXPECT_EQ(surface->consumeEvent(/*timeout=*/200ms), nullptr);
+ surface->assertNoEvent();
injectTap(31, 52);
surface->expectTap(20, 30);
}
TEST_F(InputSurfacesTest, input_respects_touchable_region_offset_overflow) {
- std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
- std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
+ std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100, "Background Surface");
+ std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100, "Foreground Surface");
bgSurface->showAt(100, 100);
// Set the touchable region to the values at the limit of its corresponding type.
// Since the surface is offset from the origin, the touchable region will be transformed into
// display space, which would trigger an overflow or an underflow. Ensure that we are protected
// against such a situation.
- fgSurface->mInputInfo.touchableRegion.orSelf(Rect{INT32_MIN, INT32_MIN, INT32_MAX, INT32_MAX});
+ fgSurface->mInputInfo->editInfo()->touchableRegion.orSelf(
+ Rect{INT32_MIN, INT32_MIN, INT32_MAX, INT32_MAX});
fgSurface->showAt(100, 100);
@@ -638,11 +649,12 @@
}
TEST_F(InputSurfacesTest, input_respects_scaled_touchable_region_overflow) {
- std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
- std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
+ std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100, "Background Surface");
+ std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100, "Foreground Surface");
bgSurface->showAt(0, 0);
- fgSurface->mInputInfo.touchableRegion.orSelf(Rect{INT32_MIN, INT32_MIN, INT32_MAX, INT32_MAX});
+ fgSurface->mInputInfo->editInfo()->touchableRegion.orSelf(
+ Rect{INT32_MIN, INT32_MIN, INT32_MAX, INT32_MAX});
fgSurface->showAt(0, 0);
fgSurface->doTransaction([&](auto& t, auto& sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); });
@@ -703,8 +715,8 @@
}
TEST_F(InputSurfacesTest, input_ignores_color_layer_alpha) {
- std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
- std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
+ std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100, "Background Surface");
+ std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100, "Foreground Surface");
bgSurface->showAt(10, 10);
fgSurface->showAt(10, 10);
@@ -812,7 +824,7 @@
TEST_F(InputSurfacesTest, rotate_surface_with_scale_and_insets) {
std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
- surface->mInputInfo.surfaceInset = 5;
+ surface->mInputInfo->editInfo()->surfaceInset = 5;
surface->showAt(100, 100);
surface->doTransaction([](auto& t, auto& sc) {
@@ -835,17 +847,19 @@
}
TEST_F(InputSurfacesTest, touch_flag_obscured) {
- std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
+ std::unique_ptr<InputSurface> surface = makeSurface(100, 100, "Touchable Surface");
surface->showAt(100, 100);
// Add non touchable window to fully cover touchable window. Window behind gets touch, but
// with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED
- std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100);
- nonTouchableSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
- nonTouchableSurface->mInputInfo.ownerUid = gui::Uid{22222};
+ std::unique_ptr<InputSurface> nonTouchableSurface =
+ makeSurface(100, 100, "Non-Touchable Surface");
+ nonTouchableSurface->mInputInfo->editInfo()
+ ->setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
+ nonTouchableSurface->mInputInfo->editInfo()->ownerUid = gui::Uid{22222};
// Overriding occlusion mode otherwise the touch would be discarded at InputDispatcher by
// the default obscured/untrusted touch filter introduced in S.
- nonTouchableSurface->mInputInfo.touchOcclusionMode = TouchOcclusionMode::ALLOW;
+ nonTouchableSurface->mInputInfo->editInfo()->touchOcclusionMode = TouchOcclusionMode::ALLOW;
nonTouchableSurface->showAt(100, 100);
injectTap(190, 199);
@@ -853,18 +867,21 @@
}
TEST_F(InputSurfacesTest, touch_flag_partially_obscured_with_crop) {
- std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
+ std::unique_ptr<InputSurface> surface = makeSurface(100, 100, "Test Surface");
surface->showAt(100, 100);
// Add non touchable window to cover touchable window, but parent is cropped to not cover area
// that will be tapped. Window behind gets touch, but with flag
// AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED
- std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100);
- std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100);
- nonTouchableSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
- parentSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
- nonTouchableSurface->mInputInfo.ownerUid = gui::Uid{22222};
- parentSurface->mInputInfo.ownerUid = gui::Uid{22222};
+ std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100, "Parent Surface");
+ std::unique_ptr<InputSurface> nonTouchableSurface =
+ makeSurface(100, 100, "Non-Touchable Surface");
+ nonTouchableSurface->mInputInfo->editInfo()
+ ->setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
+ parentSurface->mInputInfo->editInfo()->setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE,
+ true);
+ nonTouchableSurface->mInputInfo->editInfo()->ownerUid = gui::Uid{22222};
+ parentSurface->mInputInfo->editInfo()->ownerUid = gui::Uid{22222};
nonTouchableSurface->showAt(0, 0);
parentSurface->showAt(100, 100);
@@ -878,17 +895,20 @@
}
TEST_F(InputSurfacesTest, touch_not_obscured_with_crop) {
- std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
+ std::unique_ptr<InputSurface> surface = makeSurface(100, 100, "Test Surface");
surface->showAt(100, 100);
// Add non touchable window to cover touchable window, but parent is cropped to avoid covering
// the touchable window. Window behind gets touch with no obscured flags.
- std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100);
- std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100);
- nonTouchableSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
- parentSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
- nonTouchableSurface->mInputInfo.ownerUid = gui::Uid{22222};
- parentSurface->mInputInfo.ownerUid = gui::Uid{22222};
+ std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100, "Parent Surface");
+ std::unique_ptr<InputSurface> nonTouchableSurface =
+ makeSurface(100, 100, "Non-Touchable Surface");
+ nonTouchableSurface->mInputInfo->editInfo()
+ ->setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
+ parentSurface->mInputInfo->editInfo()->setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE,
+ true);
+ nonTouchableSurface->mInputInfo->editInfo()->ownerUid = gui::Uid{22222};
+ parentSurface->mInputInfo->editInfo()->ownerUid = gui::Uid{22222};
nonTouchableSurface->showAt(0, 0);
parentSurface->showAt(50, 50);
@@ -906,8 +926,9 @@
std::unique_ptr<InputSurface> bufferSurface =
InputSurface::makeBufferInputSurface(mComposerClient, 0, 0);
- bufferSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
- bufferSurface->mInputInfo.ownerUid = gui::Uid{22222};
+ bufferSurface->mInputInfo->editInfo()->setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE,
+ true);
+ bufferSurface->mInputInfo->editInfo()->ownerUid = gui::Uid{22222};
surface->showAt(10, 10);
bufferSurface->showAt(50, 50, Rect::EMPTY_RECT);
@@ -921,8 +942,9 @@
std::unique_ptr<BlastInputSurface> bufferSurface =
BlastInputSurface::makeBlastInputSurface(mComposerClient, 0, 0);
- bufferSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
- bufferSurface->mInputInfo.ownerUid = gui::Uid{22222};
+ bufferSurface->mInputInfo->editInfo()->setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE,
+ true);
+ bufferSurface->mInputInfo->editInfo()->ownerUid = gui::Uid{22222};
surface->showAt(10, 10);
bufferSurface->showAt(50, 50, Rect::EMPTY_RECT);
@@ -964,14 +986,15 @@
}
TEST_F(InputSurfacesTest, strict_unobscured_input_obscured_window) {
- std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
- surface->mInputInfo.ownerUid = gui::Uid{11111};
+ std::unique_ptr<InputSurface> surface = makeSurface(100, 100, "Test Surface");
+ surface->mInputInfo->editInfo()->ownerUid = gui::Uid{11111};
surface->doTransaction(
[&](auto& t, auto& sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); });
surface->showAt(100, 100);
- std::unique_ptr<InputSurface> obscuringSurface = makeSurface(100, 100);
- obscuringSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
- obscuringSurface->mInputInfo.ownerUid = gui::Uid{22222};
+ std::unique_ptr<InputSurface> obscuringSurface = makeSurface(100, 100, "Obscuring Surface");
+ obscuringSurface->mInputInfo->editInfo()->setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE,
+ true);
+ obscuringSurface->mInputInfo->editInfo()->ownerUid = gui::Uid{22222};
obscuringSurface->showAt(100, 100);
injectTap(101, 101);
surface->assertNoEvent();
@@ -983,14 +1006,15 @@
}
TEST_F(InputSurfacesTest, strict_unobscured_input_partially_obscured_window) {
- std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
- surface->mInputInfo.ownerUid = gui::Uid{11111};
+ std::unique_ptr<InputSurface> surface = makeSurface(100, 100, "Test Surface");
+ surface->mInputInfo->editInfo()->ownerUid = gui::Uid{11111};
surface->doTransaction(
[&](auto& t, auto& sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); });
surface->showAt(100, 100);
- std::unique_ptr<InputSurface> obscuringSurface = makeSurface(100, 100);
- obscuringSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true);
- obscuringSurface->mInputInfo.ownerUid = gui::Uid{22222};
+ std::unique_ptr<InputSurface> obscuringSurface = makeSurface(100, 100, "Obscuring Surface");
+ obscuringSurface->mInputInfo->editInfo()->setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE,
+ true);
+ obscuringSurface->mInputInfo->editInfo()->ownerUid = gui::Uid{22222};
obscuringSurface->showAt(190, 190);
injectTap(101, 101);
@@ -1004,10 +1028,10 @@
}
TEST_F(InputSurfacesTest, strict_unobscured_input_alpha_window) {
- std::unique_ptr<InputSurface> parentSurface = makeSurface(300, 300);
+ std::unique_ptr<InputSurface> parentSurface = makeSurface(300, 300, "Parent Surface");
parentSurface->showAt(0, 0, Rect(0, 0, 300, 300));
- std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
+ std::unique_ptr<InputSurface> surface = makeSurface(100, 100, "Test Surface");
surface->showAt(100, 100);
surface->doTransaction([&](auto& t, auto& sc) {
t.setDropInputMode(sc, gui::DropInputMode::OBSCURED);
@@ -1026,10 +1050,10 @@
}
TEST_F(InputSurfacesTest, strict_unobscured_input_cropped_window) {
- std::unique_ptr<InputSurface> parentSurface = makeSurface(300, 300);
+ std::unique_ptr<InputSurface> parentSurface = makeSurface(300, 300, "Parent Surface");
parentSurface->showAt(0, 0, Rect(0, 0, 300, 300));
- std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
+ std::unique_ptr<InputSurface> surface = makeSurface(100, 100, "Test Surface");
surface->doTransaction([&](auto& t, auto& sc) {
t.setDropInputMode(sc, gui::DropInputMode::OBSCURED);
t.reparent(sc, parentSurface->mSurfaceControl);
@@ -1054,7 +1078,7 @@
BlastInputSurface::makeBlastInputSurface(mComposerClient, 0, 0);
surface->showAt(100, 100);
- bufferSurface->mInputInfo.touchableRegion.orSelf(Rect(0, 0, 200, 200));
+ bufferSurface->mInputInfo->editInfo()->touchableRegion.orSelf(Rect(0, 0, 200, 200));
bufferSurface->showAt(100, 100, Rect::EMPTY_RECT);
injectTap(101, 101);
@@ -1092,13 +1116,15 @@
*/
TEST_F(InputSurfacesTest, cropped_container_replaces_touchable_region_with_null_crop) {
std::unique_ptr<InputSurface> parentContainer =
- InputSurface::makeContainerInputSurface(mComposerClient, 0, 0);
+ InputSurface::makeContainerInputSurface(mComposerClient, 0, 0,
+ "Parent Container Surface");
std::unique_ptr<InputSurface> containerSurface =
- InputSurface::makeContainerInputSurface(mComposerClient, 100, 100);
+ InputSurface::makeContainerInputSurface(mComposerClient, 100, 100,
+ "Test Container Surface");
containerSurface->doTransaction(
[&](auto& t, auto& sc) { t.reparent(sc, parentContainer->mSurfaceControl); });
- containerSurface->mInputInfo.replaceTouchableRegionWithCrop = true;
- containerSurface->mInputInfo.touchableRegionCropHandle = nullptr;
+ containerSurface->mInputInfo->editInfo()->replaceTouchableRegionWithCrop = true;
+ containerSurface->mInputInfo->editInfo()->touchableRegionCropHandle = nullptr;
parentContainer->showAt(10, 10, Rect(0, 0, 20, 20));
containerSurface->showAt(10, 10, Rect(0, 0, 5, 5));
@@ -1116,14 +1142,22 @@
* in its parent's touchable region. The input events should be in the layer's coordinate space.
*/
TEST_F(InputSurfacesTest, uncropped_container_replaces_touchable_region_with_null_crop) {
+ std::unique_ptr<InputSurface> bgContainer =
+ InputSurface::makeContainerInputSurface(mComposerClient, 0, 0,
+ "Background Container Surface");
std::unique_ptr<InputSurface> parentContainer =
- InputSurface::makeContainerInputSurface(mComposerClient, 0, 0);
+ InputSurface::makeContainerInputSurface(mComposerClient, 0, 0,
+ "Parent Container Surface");
std::unique_ptr<InputSurface> containerSurface =
- InputSurface::makeContainerInputSurface(mComposerClient, 100, 100);
+ InputSurface::makeContainerInputSurface(mComposerClient, 100, 100,
+ "Test Container Surface");
containerSurface->doTransaction(
[&](auto& t, auto& sc) { t.reparent(sc, parentContainer->mSurfaceControl); });
- containerSurface->mInputInfo.replaceTouchableRegionWithCrop = true;
- containerSurface->mInputInfo.touchableRegionCropHandle = nullptr;
+ containerSurface->mInputInfo->editInfo()->replaceTouchableRegionWithCrop = true;
+ containerSurface->mInputInfo->editInfo()->touchableRegionCropHandle = nullptr;
+ parentContainer->doTransaction(
+ [&](auto& t, auto& sc) { t.reparent(sc, bgContainer->mSurfaceControl); });
+ bgContainer->showAt(0, 0, Rect(0, 0, 100, 100));
parentContainer->showAt(10, 10, Rect(0, 0, 20, 20));
containerSurface->showAt(10, 10, Rect::INVALID_RECT);
@@ -1142,13 +1176,13 @@
*/
TEST_F(InputSurfacesTest, replace_touchable_region_with_crop) {
std::unique_ptr<InputSurface> cropLayer =
- InputSurface::makeContainerInputSurface(mComposerClient, 0, 0);
+ InputSurface::makeContainerInputSurface(mComposerClient, 0, 0, "Crop Layer Surface");
cropLayer->showAt(50, 50, Rect(0, 0, 20, 20));
std::unique_ptr<InputSurface> containerSurface =
- InputSurface::makeContainerInputSurface(mComposerClient, 100, 100);
- containerSurface->mInputInfo.replaceTouchableRegionWithCrop = true;
- containerSurface->mInputInfo.touchableRegionCropHandle =
+ InputSurface::makeContainerInputSurface(mComposerClient, 100, 100, "Container Surface");
+ containerSurface->mInputInfo->editInfo()->replaceTouchableRegionWithCrop = true;
+ containerSurface->mInputInfo->editInfo()->touchableRegionCropHandle =
cropLayer->mSurfaceControl->getHandle();
containerSurface->showAt(10, 10, Rect::INVALID_RECT);
@@ -1194,9 +1228,17 @@
sp<IGraphicBufferConsumer> consumer;
sp<IGraphicBufferProducer> producer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->setConsumerName(String8("Virtual disp consumer"));
+ consumer->setConsumerName(String8("Virtual disp consumer (MultiDisplayTests)"));
consumer->setDefaultBufferSize(width, height);
- mProducers.push_back(producer);
+
+ class StubConsumerListener : public IConsumerListener {
+ virtual void onFrameAvailable(const BufferItem&) override {}
+ virtual void onBuffersReleased() override {}
+ virtual void onSidebandStreamChanged() override {}
+ };
+
+ consumer->consumerConnect(sp<StubConsumerListener>::make(), true);
+ mBufferQueues.push_back({consumer, producer});
std::string name = "VirtualDisplay";
name += std::to_string(mVirtualDisplays.size());
@@ -1207,13 +1249,13 @@
t.setDisplayLayerStack(token, layerStack);
t.setDisplayProjection(token, ui::ROTATION_0, {0, 0, width, height},
{offsetX, offsetY, offsetX + width, offsetY + height});
- t.apply(true);
+ t.apply(/*synchronously=*/true);
mVirtualDisplays.push_back(token);
}
std::vector<sp<IBinder>> mVirtualDisplays;
- std::vector<sp<IGraphicBufferProducer>> mProducers;
+ std::vector<std::tuple<sp<IGraphicBufferConsumer>, sp<IGraphicBufferProducer>>> mBufferQueues;
};
TEST_F(MultiDisplayTests, drop_touch_if_layer_on_invalid_display) {
diff --git a/libs/gui/tests/FillBuffer.cpp b/libs/gui/tests/FillBuffer.cpp
index b60995a..11383d9 100644
--- a/libs/gui/tests/FillBuffer.cpp
+++ b/libs/gui/tests/FillBuffer.cpp
@@ -76,7 +76,7 @@
}
void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride) {
- const size_t PIXEL_SIZE = 4;
+ constexpr size_t PIXEL_SIZE = 4;
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
off_t offset = (y * stride + x) * PIXEL_SIZE;
@@ -89,6 +89,21 @@
}
}
+void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride, uint8_t r, uint8_t g, uint8_t b,
+ uint8_t a) {
+ constexpr size_t PIXEL_SIZE = 4;
+
+ for (int x = 0; x < w; x++) {
+ for (int y = 0; y < h; y++) {
+ off_t offset = (y * stride + x) * PIXEL_SIZE;
+ buf[offset] = r;
+ buf[offset + 1] = g;
+ buf[offset + 2] = b;
+ buf[offset + 3] = a;
+ }
+ }
+}
+
void produceOneRGBA8Frame(const sp<ANativeWindow>& anw) {
android_native_buffer_t* anb;
ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(anw.get(),
diff --git a/libs/gui/tests/FillBuffer.h b/libs/gui/tests/FillBuffer.h
index b584179..f5d6b8b 100644
--- a/libs/gui/tests/FillBuffer.h
+++ b/libs/gui/tests/FillBuffer.h
@@ -30,6 +30,8 @@
const android_native_rect_t& rect);
void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride);
+void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride, uint8_t r, uint8_t g, uint8_t b,
+ uint8_t a);
// Produce a single RGBA8 frame by filling a buffer with a checkerboard pattern
// using the CPU. This assumes that the ANativeWindow is already configured to
diff --git a/libs/gui/tests/FrameRateUtilsTest.cpp b/libs/gui/tests/FrameRateUtilsTest.cpp
index 04bfb28..c502533 100644
--- a/libs/gui/tests/FrameRateUtilsTest.cpp
+++ b/libs/gui/tests/FrameRateUtilsTest.cpp
@@ -34,7 +34,7 @@
ANATIVEWINDOW_CHANGE_FRAME_RATE_ALWAYS, ""));
EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, ""));
- EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_GTE,
+ EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_AT_LEAST,
ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, ""));
// Privileged APIs.
@@ -62,7 +62,7 @@
// Invalid compatibility.
EXPECT_FALSE(
ValidateFrameRate(60.0f, -1, ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, ""));
- EXPECT_FALSE(ValidateFrameRate(60.0f, 2, ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, ""));
+ EXPECT_FALSE(ValidateFrameRate(60.0f, 3, ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS, ""));
// Invalid change frame rate strategy.
if (flags::bq_setframerate()) {
diff --git a/libs/gui/tests/Malicious.cpp b/libs/gui/tests/Malicious.cpp
index 376420c..cc16383 100644
--- a/libs/gui/tests/Malicious.cpp
+++ b/libs/gui/tests/Malicious.cpp
@@ -129,7 +129,7 @@
int32_t mExpectedSlot = 0;
};
-class FakeListener : public BnConsumerListener {
+class FakeListener : public IConsumerListener {
public:
void onFrameAvailable(const BufferItem&) override {}
void onBuffersReleased() override {}
diff --git a/libs/gui/tests/MockConsumer.h b/libs/gui/tests/MockConsumer.h
index 4a6c51c..2e8bc63 100644
--- a/libs/gui/tests/MockConsumer.h
+++ b/libs/gui/tests/MockConsumer.h
@@ -18,7 +18,7 @@
namespace android {
-struct MockConsumer : public BnConsumerListener {
+struct MockConsumer : public IConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
diff --git a/libs/gui/tests/MultiTextureConsumer_test.cpp b/libs/gui/tests/MultiTextureConsumer_test.cpp
index 2428bb3..7ae6f40 100644
--- a/libs/gui/tests/MultiTextureConsumer_test.cpp
+++ b/libs/gui/tests/MultiTextureConsumer_test.cpp
@@ -34,8 +34,8 @@
virtual void SetUp() {
GLTest::SetUp();
- mGlConsumer = new GLConsumer(TEX_ID, GLConsumer::TEXTURE_EXTERNAL, true, false);
- mSurface = mGlConsumer->getSurface();
+ std::tie(mGlConsumer, mSurface) =
+ GLConsumer::create(TEX_ID, GLConsumer::TEXTURE_EXTERNAL, true, false);
mANW = mSurface.get();
}
diff --git a/libs/gui/tests/RegionSampling_test.cpp b/libs/gui/tests/RegionSampling_test.cpp
index a0d8c53..c35efe2 100644
--- a/libs/gui/tests/RegionSampling_test.cpp
+++ b/libs/gui/tests/RegionSampling_test.cpp
@@ -40,7 +40,7 @@
std::unique_lock<decltype(mutex_)> lk(mutex_);
auto check_event = [](auto const& ev) -> bool {
- return ev.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
+ return ev.header.type == DisplayEventType::DISPLAY_EVENT_VSYNC;
};
DisplayEventReceiver::Event ev_;
int evs = receiver_.getEvents(&ev_, 1);
diff --git a/libs/gui/tests/StreamSplitter_test.cpp b/libs/gui/tests/StreamSplitter_test.cpp
index f34b03e..9570a36 100644
--- a/libs/gui/tests/StreamSplitter_test.cpp
+++ b/libs/gui/tests/StreamSplitter_test.cpp
@@ -32,7 +32,7 @@
class StreamSplitterTest : public ::testing::Test {};
-struct FakeListener : public BnConsumerListener {
+struct FakeListener : public IConsumerListener {
virtual void onFrameAvailable(const BufferItem& /* item */) {}
virtual void onBuffersReleased() {}
virtual void onSidebandStreamChanged() {}
@@ -95,8 +95,7 @@
ASSERT_EQ(*dataOut, TEST_DATA);
ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
- ASSERT_EQ(OK, outputConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+ ASSERT_EQ(OK, outputConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, Fence::NO_FENCE));
// This should succeed even with allocation disabled since it will have
// received the buffer back from the output BufferQueue
@@ -168,9 +167,9 @@
ASSERT_EQ(*dataOut, TEST_DATA);
ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
- ASSERT_EQ(OK, outputConsumers[output]->releaseBuffer(item.mSlot,
- item.mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
- Fence::NO_FENCE));
+ ASSERT_EQ(OK,
+ outputConsumers[output]->releaseBuffer(item.mSlot, item.mFrameNumber,
+ Fence::NO_FENCE));
}
// This should succeed even with allocation disabled since it will have
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index 59d05b6..d3434ea 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -40,8 +40,7 @@
}
virtual void SetUp() {
- mST = new GLConsumer(123, GLConsumer::TEXTURE_EXTERNAL, true, false);
- mSTC = mST->getSurface();
+ std::tie(mST, mSTC) = GLConsumer::create(123, GLConsumer::TEXTURE_EXTERNAL, true, false);
mANW = mSTC;
// We need a valid GL context so we can test updateTexImage()
@@ -727,8 +726,7 @@
ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
for (int i = 0; i < NUM_SURFACE_TEXTURES; i++) {
- sp<GLConsumer> st(new GLConsumer(i, GLConsumer::TEXTURE_EXTERNAL, true, false));
- sp<Surface> stc = st->getSurface();
+ auto [st, stc] = GLConsumer::create(i, GLConsumer::TEXTURE_EXTERNAL, true, false);
mEglSurfaces[i] = eglCreateWindowSurface(mEglDisplay, myConfig,
static_cast<ANativeWindow*>(stc.get()), nullptr);
ASSERT_EQ(EGL_SUCCESS, eglGetError());
diff --git a/libs/gui/tests/SurfaceTextureGL.h b/libs/gui/tests/SurfaceTextureGL.h
index 1309635..eb31cd1 100644
--- a/libs/gui/tests/SurfaceTextureGL.h
+++ b/libs/gui/tests/SurfaceTextureGL.h
@@ -38,8 +38,7 @@
void SetUp() {
GLTest::SetUp();
- mST = new GLConsumer(TEX_ID, GLConsumer::TEXTURE_EXTERNAL, true, false);
- mSTC = mST->getSurface();
+ std::tie(mST, mSTC) = GLConsumer::create(TEX_ID, GLConsumer::TEXTURE_EXTERNAL, true, false);
mANW = mSTC;
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), TEST_PRODUCER_USAGE_BITS));
mTextureRenderer = new TextureRenderer(TEX_ID, mST);
diff --git a/libs/gui/tests/SurfaceTextureGL_test.cpp b/libs/gui/tests/SurfaceTextureGL_test.cpp
index 449533a..b22b853 100644
--- a/libs/gui/tests/SurfaceTextureGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGL_test.cpp
@@ -17,6 +17,8 @@
#define LOG_TAG "SurfaceTextureGL_test"
//#define LOG_NDEBUG 0
+#include <gmock/gmock.h>
+
#include "SurfaceTextureGL.h"
#include "DisconnectWaiter.h"
@@ -735,4 +737,30 @@
ASSERT_NE(NO_ERROR, mST->updateTexImage());
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+TEST_F(SurfaceTextureGLTest, TestUnlimitedSlots) {
+ ASSERT_EQ(OK, mSTC->connect(NATIVE_WINDOW_API_CPU, sp<StubSurfaceListener>::make()));
+ ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(256));
+
+ std::vector<Surface::BatchBuffer> buffers(256);
+ ASSERT_EQ(OK, mSTC->dequeueBuffers(&buffers));
+ ASSERT_EQ(256u, buffers.size());
+ ASSERT_THAT(buffers, Each(Field(&Surface::BatchBuffer::buffer, ::testing::NotNull())));
+
+ for (size_t i = 0; i < buffers.size(); ++i) {
+ sp<GraphicBuffer> graphicBuffer = GraphicBuffer::from(buffers[i].buffer);
+ sp<Fence> fence = sp<Fence>::make(buffers[i].fenceFd);
+
+ void* buf;
+ ASSERT_EQ(OK, graphicBuffer->lock(AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, &buf));
+ fillRGBA8Buffer((uint8_t*)buf, graphicBuffer->getWidth(), graphicBuffer->getHeight(),
+ graphicBuffer->getStride(), i, i, i, i);
+ graphicBuffer->unlock();
+
+ ASSERT_EQ(OK, mSTC->queueBuffer(graphicBuffer, fence));
+ ASSERT_EQ(OK, mST->updateTexImage());
+ checkPixel(0, 0, i, i, i, i);
+ }
+}
+#endif
} // namespace android
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 88893b6..eb55e3b 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -14,13 +14,10 @@
* limitations under the License.
*/
-#include "gui/view/Surface.h"
-#include "Constants.h"
-#include "MockConsumer.h"
-
#include <gtest/gtest.h>
#include <SurfaceFlingerProperties.h>
+#include <android/gui/IActivePictureListener.h>
#include <android/gui/IDisplayEventConnection.h>
#include <android/gui/ISurfaceComposer.h>
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
@@ -35,10 +32,13 @@
#include <gui/IConsumerListener.h>
#include <gui/IGraphicBufferConsumer.h>
#include <gui/IGraphicBufferProducer.h>
+#include <gui/IProducerListener.h>
#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/SyncScreenCaptureListener.h>
+#include <gui/view/Surface.h>
+#include <nativebase/nativebase.h>
#include <private/gui/ComposerService.h>
#include <private/gui/ComposerServiceAIDL.h>
#include <sys/types.h>
@@ -46,6 +46,7 @@
#include <ui/BufferQueueDefs.h>
#include <ui/DisplayMode.h>
#include <ui/GraphicBuffer.h>
+#include <ui/PixelFormat.h>
#include <ui/Rect.h>
#include <utils/Errors.h>
#include <utils/String8.h>
@@ -54,9 +55,12 @@
#include <cstddef>
#include <cstdint>
#include <future>
+#include <iterator>
#include <limits>
#include <thread>
+#include "Constants.h"
+#include "MockConsumer.h"
#include "testserver/TestServerClient.h"
namespace android {
@@ -201,9 +205,9 @@
releasedItems.resize(1+extraDiscardedBuffers);
for (size_t i = 0; i < releasedItems.size(); i++) {
ASSERT_EQ(NO_ERROR, consumer->acquireBuffer(&releasedItems[i], 0));
- ASSERT_EQ(NO_ERROR, consumer->releaseBuffer(releasedItems[i].mSlot,
- releasedItems[i].mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
- Fence::NO_FENCE));
+ ASSERT_EQ(NO_ERROR,
+ consumer->releaseBuffer(releasedItems[i].mSlot, releasedItems[i].mFrameNumber,
+ Fence::NO_FENCE));
}
int32_t expectedReleaseCb = (enableReleasedCb ? releasedItems.size() : 0);
if (hasSurfaceListener) {
@@ -290,9 +294,7 @@
TEST_F(SurfaceTest, QueryConsumerUsage) {
const int TEST_USAGE_FLAGS =
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER;
- sp<BufferItemConsumer> c = new BufferItemConsumer(TEST_USAGE_FLAGS);
-
- sp<Surface> s = c->getSurface();
+ auto [c, s] = BufferItemConsumer::create(TEST_USAGE_FLAGS);
sp<ANativeWindow> anw(s);
int flags = -1;
@@ -305,10 +307,8 @@
TEST_F(SurfaceTest, QueryDefaultBuffersDataSpace) {
const android_dataspace TEST_DATASPACE = HAL_DATASPACE_V0_SRGB;
- sp<CpuConsumer> cpuConsumer = new CpuConsumer(1);
+ auto [cpuConsumer, s] = CpuConsumer::create(1);
cpuConsumer->setDefaultBufferDataSpace(TEST_DATASPACE);
-
- sp<Surface> s = cpuConsumer->getSurface();
sp<ANativeWindow> anw(s);
android_dataspace dataSpace;
@@ -321,8 +321,7 @@
}
TEST_F(SurfaceTest, SettingGenerationNumber) {
- sp<CpuConsumer> cpuConsumer = new CpuConsumer(1);
- sp<Surface> surface = cpuConsumer->getSurface();
+ auto [cpuConsumer, surface] = CpuConsumer::create(1);
sp<ANativeWindow> window(surface);
// Allocate a buffer with a generation number of 0
@@ -599,7 +598,7 @@
ASSERT_GE(after, lastDequeueTime);
}
-class FakeConsumer : public BnConsumerListener {
+class FakeConsumer : public IConsumerListener {
public:
void onFrameAvailable(const BufferItem& /*item*/) override {}
void onBuffersReleased() override {}
@@ -1015,6 +1014,19 @@
return binder::Status::ok();
}
+ binder::Status addActivePictureListener(const sp<gui::IActivePictureListener>&) {
+ return binder::Status::ok();
+ }
+
+ binder::Status removeActivePictureListener(const sp<gui::IActivePictureListener>&) {
+ return binder::Status::ok();
+ }
+
+ binder::Status getMaxLayerPictureProfiles(const sp<IBinder>& /*display*/,
+ int32_t* /*outMaxProfiles*/) {
+ return binder::Status::ok();
+ }
+
protected:
IBinder* onAsBinder() override { return nullptr; }
@@ -2163,8 +2175,7 @@
const int BUFFER_COUNT = 16;
const int BATCH_SIZE = 8;
- sp<CpuConsumer> cpuConsumer = new CpuConsumer(1);
- sp<Surface> surface = cpuConsumer->getSurface();
+ auto [cpuConsumer, surface] = CpuConsumer::create(1);
sp<ANativeWindow> window(surface);
sp<StubSurfaceListener> listener = new StubSurfaceListener();
@@ -2212,8 +2223,7 @@
const int BUFFER_COUNT = 16;
const int BATCH_SIZE = 8;
- sp<CpuConsumer> cpuConsumer = new CpuConsumer(1);
- sp<Surface> surface = cpuConsumer->getSurface();
+ auto [cpuConsumer, surface] = CpuConsumer::create(1);
sp<ANativeWindow> window(surface);
sp<StubSurfaceListener> listener = new StubSurfaceListener();
@@ -2360,8 +2370,7 @@
sp<IGraphicBufferConsumer> bqConsumer;
BufferQueue::createBufferQueue(&bqProducer, &bqConsumer);
- sp<BufferItemConsumer> consumer = sp<BufferItemConsumer>::make(bqConsumer, 3);
- sp<Surface> surface = sp<Surface>::make(bqProducer);
+ auto [consumer, surface] = BufferItemConsumer::create(3);
sp<ImmediateReleaseConsumerListener> consumerListener =
sp<ImmediateReleaseConsumerListener>::make(consumer);
consumer->setFrameAvailableListener(consumerListener);
@@ -2519,4 +2528,128 @@
}
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
+TEST_F(SurfaceTest, UnlimitedSlots_FailsOnIncompatibleConsumer) {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+
+ sp<IConsumerListener> consumerListener = sp<FakeConsumer>::make();
+
+ EXPECT_EQ(OK, consumer->allowUnlimitedSlots(false));
+ EXPECT_EQ(OK, consumer->consumerConnect(consumerListener, /* consumerListener */ true));
+
+ sp<Surface> surface = sp<Surface>::make(producer);
+ sp<SurfaceListener> surfaceListener = sp<StubSurfaceListener>::make();
+ EXPECT_EQ(OK, surface->connect(NATIVE_WINDOW_API_CPU, surfaceListener));
+
+ EXPECT_NE(OK, surface->setMaxDequeuedBufferCount(128))
+ << "We shouldn't be able to set high max buffer counts if the consumer doesn't allow "
+ "it";
+}
+
+TEST_F(SurfaceTest, UnlimitedSlots_CanDequeueAndQueueMoreThanOldMaximum) {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+
+ sp<IConsumerListener> consumerListener = sp<FakeConsumer>::make();
+
+ EXPECT_EQ(OK, consumer->allowUnlimitedSlots(true));
+ EXPECT_EQ(OK, consumer->consumerConnect(consumerListener, /* consumerListener */ true));
+ EXPECT_EQ(OK, consumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888));
+ EXPECT_EQ(OK, consumer->setConsumerUsageBits(AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN));
+
+ sp<Surface> surface = sp<Surface>::make(producer);
+ sp<SurfaceListener> surfaceListener = sp<StubSurfaceListener>::make();
+ EXPECT_EQ(OK, surface->connect(NATIVE_WINDOW_API_CPU, surfaceListener));
+
+ EXPECT_EQ(OK, surface->setMaxDequeuedBufferCount(128))
+ << "If unlimited slots are allowed, we should be able increase the max dequeued buffer "
+ "count arbitrarily";
+
+ std::vector<std::tuple<sp<GraphicBuffer>, sp<Fence>, int>> buffers;
+ for (int i = 0; i < 128; i++) {
+ sp<GraphicBuffer> buffer;
+ sp<Fence> fence;
+ ASSERT_EQ(OK, surface->dequeueBuffer(&buffer, &fence)) << "Unable to dequeue buffer #" << i;
+ buffers.push_back({buffer, fence, i});
+ }
+
+ for (auto& [buffer, fence, idx] : buffers) {
+ ASSERT_EQ(OK, surface->queueBuffer(buffer, fence)) << "Unable to queue buffer #" << idx;
+ }
+}
+
+TEST_F(SurfaceTest, UnlimitedSlots_CanDequeueAndDetachMoreThanOldMaximum) {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+
+ sp<IConsumerListener> consumerListener = sp<FakeConsumer>::make();
+
+ EXPECT_EQ(OK, consumer->allowUnlimitedSlots(true));
+ EXPECT_EQ(OK, consumer->consumerConnect(consumerListener, /* consumerListener */ true));
+ EXPECT_EQ(OK, consumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888));
+ EXPECT_EQ(OK, consumer->setConsumerUsageBits(AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN));
+
+ sp<Surface> surface = sp<Surface>::make(producer);
+ sp<SurfaceListener> surfaceListener = sp<StubSurfaceListener>::make();
+ EXPECT_EQ(OK, surface->connect(NATIVE_WINDOW_API_CPU, surfaceListener));
+
+ EXPECT_EQ(OK, surface->setMaxDequeuedBufferCount(128))
+ << "If unlimited slots are allowed, we should be able increase the max dequeued buffer "
+ "count arbitrarily";
+
+ std::vector<std::tuple<sp<GraphicBuffer>, sp<Fence>, int>> buffers;
+ for (int i = 0; i < 128; i++) {
+ sp<GraphicBuffer> buffer;
+ sp<Fence> fence;
+ ASSERT_EQ(OK, surface->dequeueBuffer(&buffer, &fence)) << "Unable to dequeue buffer #" << i;
+ buffers.push_back({buffer, fence, i});
+ }
+
+ for (auto& [buffer, _, idx] : buffers) {
+ ASSERT_EQ(OK, surface->detachBuffer(buffer)) << "Unable to detach buffer #" << idx;
+ }
+}
+
+TEST_F(SurfaceTest, UnlimitedSlots_BatchOperations) {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+
+ sp<IConsumerListener> consumerListener = sp<FakeConsumer>::make();
+
+ EXPECT_EQ(OK, consumer->allowUnlimitedSlots(true));
+ EXPECT_EQ(OK, consumer->consumerConnect(consumerListener, /* consumerListener */ true));
+ EXPECT_EQ(OK, consumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888));
+ EXPECT_EQ(OK, consumer->setConsumerUsageBits(AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN));
+
+ sp<Surface> surface = sp<Surface>::make(producer);
+ sp<SurfaceListener> surfaceListener = sp<StubSurfaceListener>::make();
+ EXPECT_EQ(OK, surface->connect(NATIVE_WINDOW_API_CPU, surfaceListener));
+
+ EXPECT_EQ(OK, surface->setMaxDequeuedBufferCount(128))
+ << "If unlimited slots are allowed, we should be able increase the max dequeued buffer "
+ "count arbitrarily";
+
+ std::vector<Surface::BatchBuffer> buffers(128);
+ EXPECT_EQ(OK, surface->dequeueBuffers(&buffers));
+ EXPECT_EQ(128u, buffers.size());
+
+ std::vector<Surface::BatchQueuedBuffer> queuedBuffers;
+ std::transform(buffers.begin(), buffers.end(), std::back_inserter(queuedBuffers),
+ [](Surface::BatchBuffer& buffer) {
+ Surface::BatchQueuedBuffer out;
+ out.buffer = buffer.buffer;
+ out.fenceFd = buffer.fenceFd;
+ return out;
+ });
+
+ std::vector<SurfaceQueueBufferOutput> outputs;
+ EXPECT_EQ(OK, surface->queueBuffers(queuedBuffers, &outputs));
+ EXPECT_EQ(128u, outputs.size());
+}
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)
} // namespace android
diff --git a/libs/gui/tests/WindowInfo_test.cpp b/libs/gui/tests/WindowInfo_test.cpp
index ce22082..e3f9a07 100644
--- a/libs/gui/tests/WindowInfo_test.cpp
+++ b/libs/gui/tests/WindowInfo_test.cpp
@@ -40,7 +40,18 @@
ASSERT_EQ(OK, i.writeToParcel(&p));
p.setDataPosition(0);
i2.readFromParcel(&p);
- ASSERT_TRUE(i2.token == nullptr);
+ ASSERT_EQ(i2.token, nullptr);
+}
+
+TEST(WindowInfo, ParcellingWithoutCloneTransform) {
+ WindowInfo i, i2;
+ i.cloneLayerStackTransform.reset();
+
+ Parcel p;
+ ASSERT_EQ(OK, i.writeToParcel(&p));
+ p.setDataPosition(0);
+ i2.readFromParcel(&p);
+ ASSERT_EQ(i2.cloneLayerStackTransform, std::nullopt);
}
TEST(WindowInfo, Parcelling) {
@@ -71,6 +82,8 @@
i.applicationInfo.token = new BBinder();
i.applicationInfo.dispatchingTimeoutMillis = 0x12345678ABCD;
i.focusTransferTarget = new BBinder();
+ i.cloneLayerStackTransform = ui::Transform();
+ i.cloneLayerStackTransform->set({5, -1, 100, 4, 0, 40, 0, 0, 1});
Parcel p;
i.writeToParcel(&p);
@@ -100,6 +113,7 @@
ASSERT_EQ(i.touchableRegionCropHandle, i2.touchableRegionCropHandle);
ASSERT_EQ(i.applicationInfo, i2.applicationInfo);
ASSERT_EQ(i.focusTransferTarget, i2.focusTransferTarget);
+ ASSERT_EQ(i.cloneLayerStackTransform, i2.cloneLayerStackTransform);
}
TEST(InputApplicationInfo, Parcelling) {
diff --git a/libs/gui/tests/benchmarks/Android.bp b/libs/gui/tests/benchmarks/Android.bp
new file mode 100644
index 0000000..a728bef
--- /dev/null
+++ b/libs/gui/tests/benchmarks/Android.bp
@@ -0,0 +1,27 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
+cc_benchmark {
+ name: "libgui_benchmarks",
+ srcs: [
+ "*.cpp",
+ ],
+ defaults: ["libgui-defaults"],
+ static_libs: [
+ "libgmock",
+ "libgtest",
+ ],
+ shared_libs: [
+ "libgui",
+ ],
+ header_libs: [
+ "libsurfaceflinger_mocks_headers",
+ "surfaceflinger_tests_common_headers",
+ ],
+}
diff --git a/libs/gui/tests/benchmarks/Transaction_benchmarks.cpp b/libs/gui/tests/benchmarks/Transaction_benchmarks.cpp
new file mode 100644
index 0000000..0a51895
--- /dev/null
+++ b/libs/gui/tests/benchmarks/Transaction_benchmarks.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2024 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 <benchmark/benchmark.h>
+#include <cstddef>
+#include <optional>
+#include <vector>
+#include "binder/Parcel.h"
+#include "gui/SurfaceComposerClient.h"
+#include "gui/SurfaceControl.h"
+#include "log/log_main.h"
+
+namespace android {
+namespace {
+using android::hardware::graphics::common::V1_1::BufferUsage;
+
+std::vector<sp<SurfaceControl>> createSurfaceControl(const char* name, size_t num) {
+ sp<SurfaceComposerClient> client = sp<SurfaceComposerClient>::make();
+ LOG_FATAL_IF(client->initCheck() != OK, "Could not init SurfaceComposerClient");
+ std::vector<sp<SurfaceControl>> surfaceControls;
+ for (size_t i = 0; i < num; i++) {
+ surfaceControls.push_back(
+ client->createSurface(String8(name), 0, 0, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceBufferState));
+ }
+ return surfaceControls;
+}
+
+void applyTransaction(benchmark::State& state) {
+ std::vector<sp<SurfaceControl>> surfaceControls = createSurfaceControl(__func__, 5 /* num */);
+ for (auto _ : state) {
+ SurfaceComposerClient::Transaction t;
+ for (auto& sc : surfaceControls) {
+ t.setCrop(sc, FloatRect{1, 2, 3, 4});
+ t.setAutoRefresh(sc, true);
+ t.hide(sc);
+ t.setAlpha(sc, 0.5);
+ t.setCornerRadius(sc, 0.8);
+ }
+ Parcel p;
+ t.writeToParcel(&p);
+ t.clear();
+ benchmark::DoNotOptimize(t);
+ }
+}
+BENCHMARK(applyTransaction);
+
+// Mimic a buffer transaction with callbacks
+void applyBufferTransaction(benchmark::State& state) {
+ std::vector<sp<SurfaceControl>> surfaceControls = createSurfaceControl(__func__, 5 /* num */);
+ std::vector<sp<GraphicBuffer>> buffers;
+ for (size_t i = 0; i < surfaceControls.size(); i++) {
+ int64_t usageFlags = BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE;
+ buffers.emplace_back(
+ sp<GraphicBuffer>::make(5, 5, PIXEL_FORMAT_RGBA_8888, 1, usageFlags, "test"));
+ }
+
+ for (auto _ : state) {
+ SurfaceComposerClient::Transaction t;
+ int i = 0;
+ for (auto& sc : surfaceControls) {
+ std::function<void(const ReleaseCallbackId&, const sp<Fence>& /*releaseFence*/,
+ std::optional<uint32_t> currentMaxAcquiredBufferCount)>
+ releaseBufferCallback;
+ t.setBuffer(sc, buffers[i], std::nullopt, std::nullopt, 5, releaseBufferCallback);
+ }
+ Parcel p;
+ // proxy for applying the transaction
+ t.writeToParcel(&p);
+ t.clear();
+ benchmark::DoNotOptimize(t);
+ }
+}
+BENCHMARK(applyBufferTransaction);
+
+void mergeTransaction(benchmark::State& state) {
+ std::vector<sp<SurfaceControl>> surfaceControls = createSurfaceControl(__func__, 5 /* num */);
+ for (auto _ : state) {
+ SurfaceComposerClient::Transaction t1;
+ for (auto& sc : surfaceControls) {
+ t1.setCrop(sc, FloatRect{1, 2, 3, 4});
+ t1.setAutoRefresh(sc, true);
+ t1.hide(sc);
+ t1.setAlpha(sc, 0.5);
+ t1.setCornerRadius(sc, 0.8);
+ }
+
+ SurfaceComposerClient::Transaction t2;
+ for (auto& sc : surfaceControls) {
+ t2.hide(sc);
+ t2.setAlpha(sc, 0.5);
+ t2.setCornerRadius(sc, 0.8);
+ t2.setBackgroundBlurRadius(sc, 5);
+ }
+ t1.merge(std::move(t2));
+ benchmark::DoNotOptimize(t1);
+ }
+}
+BENCHMARK(mergeTransaction);
+
+void readTransactionFromParcel(benchmark::State& state) {
+ std::vector<sp<SurfaceControl>> surfaceControls = createSurfaceControl(__func__, 5 /* num */);
+ SurfaceComposerClient::Transaction t;
+ for (auto& sc : surfaceControls) {
+ t.setCrop(sc, FloatRect{1, 2, 3, 4});
+ t.setAutoRefresh(sc, true);
+ t.hide(sc);
+ t.setAlpha(sc, 0.5);
+ t.setCornerRadius(sc, 0.8);
+ }
+ Parcel p;
+ t.writeToParcel(&p);
+ t.clear();
+
+ for (auto _ : state) {
+ SurfaceComposerClient::Transaction t2;
+ t2.readFromParcel(&p);
+ p.setDataPosition(0);
+ benchmark::DoNotOptimize(t2);
+ }
+}
+BENCHMARK(readTransactionFromParcel);
+
+} // namespace
+} // namespace android
diff --git a/libs/binder/trusty/ndk/include/android/llndk-versioning.h b/libs/gui/tests/benchmarks/main.cpp
similarity index 82%
rename from libs/binder/trusty/ndk/include/android/llndk-versioning.h
rename to libs/gui/tests/benchmarks/main.cpp
index e955a34..685c7c6 100644
--- a/libs/binder/trusty/ndk/include/android/llndk-versioning.h
+++ b/libs/gui/tests/benchmarks/main.cpp
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#pragma once
-// TODO(b/349936395): set to true for Trusty
-#define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) (false)
+#include <benchmark/benchmark.h>
+BENCHMARK_MAIN();
diff --git a/libs/gui/tests/testserver/TestServer.cpp b/libs/gui/tests/testserver/TestServer.cpp
index cd8824e..17d1b4a 100644
--- a/libs/gui/tests/testserver/TestServer.cpp
+++ b/libs/gui/tests/testserver/TestServer.cpp
@@ -45,7 +45,7 @@
namespace android {
namespace {
-class TestConsumerListener : public BnConsumerListener {
+class TestConsumerListener : public IConsumerListener {
virtual void onFrameAvailable(const BufferItem&) override {}
virtual void onBuffersReleased() override {}
virtual void onSidebandStreamChanged() override {}
diff --git a/libs/gui/view/Surface.cpp b/libs/gui/view/Surface.cpp
index 84c2a6a..2cf7081 100644
--- a/libs/gui/view/Surface.cpp
+++ b/libs/gui/view/Surface.cpp
@@ -121,6 +121,42 @@
return str.value_or(String16());
}
+#if WB_LIBCAMERASERVICE_WITH_DEPENDENCIES
+Surface Surface::fromSurface(const sp<android::Surface>& surface) {
+ if (surface == nullptr) {
+ ALOGE("%s: Error: view::Surface::fromSurface failed due to null surface.", __FUNCTION__);
+ return Surface();
+ }
+ Surface s;
+ s.name = String16(surface->getConsumerName());
+ s.graphicBufferProducer = surface->getIGraphicBufferProducer();
+ s.surfaceControlHandle = surface->getSurfaceControlHandle();
+ return s;
+}
+
+sp<android::Surface> Surface::toSurface() const {
+ if (graphicBufferProducer == nullptr) return nullptr;
+ return new android::Surface(graphicBufferProducer, false, surfaceControlHandle);
+}
+
+status_t Surface::getUniqueId(uint64_t* out_id) const {
+ if (graphicBufferProducer == nullptr) {
+ ALOGE("android::viewSurface::getUniqueId() failed because it's not initialized.");
+ return UNEXPECTED_NULL;
+ }
+ status_t status = graphicBufferProducer->getUniqueId(out_id);
+ if (status != OK) {
+ ALOGE("android::viewSurface::getUniqueId() failed.");
+ return status;
+ }
+ return OK;
+}
+
+bool Surface::isEmpty() const {
+ return graphicBufferProducer == nullptr;
+}
+#endif
+
std::string Surface::toString() const {
std::stringstream out;
out << name;
diff --git a/libs/input/AccelerationCurve.cpp b/libs/input/AccelerationCurve.cpp
index 0a92a71..1ed9794 100644
--- a/libs/input/AccelerationCurve.cpp
+++ b/libs/input/AccelerationCurve.cpp
@@ -40,6 +40,18 @@
constexpr std::array<double, 15> kSensitivityFactors = {1, 2, 4, 6, 7, 8, 9, 10,
11, 12, 13, 14, 16, 18, 20};
+// Calculates the base gain for a given pointer sensitivity value.
+//
+// The base gain is a scaling factor that is applied to the pointer movement.
+// Higher sensitivity values result in larger base gains, which in turn result
+// in faster pointer movements.
+//
+// The base gain is calculated using a linear mapping function that maps the
+// sensitivity range [-7, 7] to a base gain range [1.0, 3.5].
+double calculateBaseGain(int32_t sensitivity) {
+ return 1.0 + (sensitivity + 7) * (3.5 - 1.0) / (7 + 7);
+}
+
} // namespace
std::vector<AccelerationCurveSegment> createAccelerationCurveForPointerSensitivity(
@@ -60,4 +72,13 @@
return output;
}
+std::vector<AccelerationCurveSegment> createFlatAccelerationCurve(int32_t sensitivity) {
+ LOG_ALWAYS_FATAL_IF(sensitivity < -7 || sensitivity > 7, "Invalid pointer sensitivity value");
+ std::vector<AccelerationCurveSegment> output = {
+ AccelerationCurveSegment{std::numeric_limits<double>::infinity(),
+ calculateBaseGain(sensitivity),
+ /* reciprocal = */ 0}};
+ return output;
+}
+
} // namespace android
\ No newline at end of file
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index e4e81ad..ff26184 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -27,9 +27,9 @@
name: "inputconstants_aidl",
srcs: [
"android/os/IInputConstants.aidl",
+ "android/os/InputConfig.aidl",
"android/os/InputEventInjectionResult.aidl",
"android/os/InputEventInjectionSync.aidl",
- "android/os/InputConfig.aidl",
"android/os/MotionEventFlag.aidl",
"android/os/PointerIconType.aidl",
],
@@ -85,56 +85,63 @@
source_stem: "bindings",
bindgen_flags: [
- "--verbose",
- "--allowlist-var=AMOTION_EVENT_ACTION_CANCEL",
- "--allowlist-var=AMOTION_EVENT_ACTION_UP",
- "--allowlist-var=AMOTION_EVENT_ACTION_POINTER_DOWN",
- "--allowlist-var=AMOTION_EVENT_ACTION_DOWN",
- "--allowlist-var=AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT",
- "--allowlist-var=MAX_POINTER_ID",
- "--allowlist-var=AINPUT_SOURCE_CLASS_NONE",
- "--allowlist-var=AINPUT_SOURCE_CLASS_BUTTON",
- "--allowlist-var=AINPUT_SOURCE_CLASS_POINTER",
- "--allowlist-var=AINPUT_SOURCE_CLASS_NAVIGATION",
- "--allowlist-var=AINPUT_SOURCE_CLASS_POSITION",
- "--allowlist-var=AINPUT_SOURCE_CLASS_JOYSTICK",
- "--allowlist-var=AINPUT_SOURCE_UNKNOWN",
- "--allowlist-var=AINPUT_SOURCE_KEYBOARD",
- "--allowlist-var=AINPUT_SOURCE_DPAD",
- "--allowlist-var=AINPUT_SOURCE_GAMEPAD",
- "--allowlist-var=AINPUT_SOURCE_TOUCHSCREEN",
- "--allowlist-var=AINPUT_SOURCE_MOUSE",
- "--allowlist-var=AINPUT_SOURCE_STYLUS",
- "--allowlist-var=AINPUT_SOURCE_BLUETOOTH_STYLUS",
- "--allowlist-var=AINPUT_SOURCE_TRACKBALL",
- "--allowlist-var=AINPUT_SOURCE_MOUSE_RELATIVE",
- "--allowlist-var=AINPUT_SOURCE_TOUCHPAD",
- "--allowlist-var=AINPUT_SOURCE_TOUCH_NAVIGATION",
- "--allowlist-var=AINPUT_SOURCE_JOYSTICK",
- "--allowlist-var=AINPUT_SOURCE_HDMI",
- "--allowlist-var=AINPUT_SOURCE_SENSOR",
- "--allowlist-var=AINPUT_SOURCE_ROTARY_ENCODER",
+ "--allowlist-var=AINPUT_KEYBOARD_TYPE_ALPHABETIC",
"--allowlist-var=AINPUT_KEYBOARD_TYPE_NONE",
"--allowlist-var=AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC",
- "--allowlist-var=AINPUT_KEYBOARD_TYPE_ALPHABETIC",
- "--allowlist-var=AMETA_NONE",
- "--allowlist-var=AMETA_ALT_ON",
+ "--allowlist-var=AINPUT_SOURCE_BLUETOOTH_STYLUS",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_BUTTON",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_JOYSTICK",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_NAVIGATION",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_NONE",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_POINTER",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_POSITION",
+ "--allowlist-var=AINPUT_SOURCE_DPAD",
+ "--allowlist-var=AINPUT_SOURCE_GAMEPAD",
+ "--allowlist-var=AINPUT_SOURCE_HDMI",
+ "--allowlist-var=AINPUT_SOURCE_JOYSTICK",
+ "--allowlist-var=AINPUT_SOURCE_KEYBOARD",
+ "--allowlist-var=AINPUT_SOURCE_MOUSE",
+ "--allowlist-var=AINPUT_SOURCE_MOUSE_RELATIVE",
+ "--allowlist-var=AINPUT_SOURCE_ROTARY_ENCODER",
+ "--allowlist-var=AINPUT_SOURCE_SENSOR",
+ "--allowlist-var=AINPUT_SOURCE_STYLUS",
+ "--allowlist-var=AINPUT_SOURCE_TOUCHPAD",
+ "--allowlist-var=AINPUT_SOURCE_TOUCHSCREEN",
+ "--allowlist-var=AINPUT_SOURCE_TOUCH_NAVIGATION",
+ "--allowlist-var=AINPUT_SOURCE_TRACKBALL",
+ "--allowlist-var=AINPUT_SOURCE_UNKNOWN",
"--allowlist-var=AMETA_ALT_LEFT_ON",
+ "--allowlist-var=AMETA_ALT_ON",
"--allowlist-var=AMETA_ALT_RIGHT_ON",
- "--allowlist-var=AMETA_SHIFT_ON",
- "--allowlist-var=AMETA_SHIFT_LEFT_ON",
- "--allowlist-var=AMETA_SHIFT_RIGHT_ON",
- "--allowlist-var=AMETA_SYM_ON",
- "--allowlist-var=AMETA_FUNCTION_ON",
- "--allowlist-var=AMETA_CTRL_ON",
- "--allowlist-var=AMETA_CTRL_LEFT_ON",
- "--allowlist-var=AMETA_CTRL_RIGHT_ON",
- "--allowlist-var=AMETA_META_ON",
- "--allowlist-var=AMETA_META_LEFT_ON",
- "--allowlist-var=AMETA_META_RIGHT_ON",
"--allowlist-var=AMETA_CAPS_LOCK_ON",
+ "--allowlist-var=AMETA_CTRL_LEFT_ON",
+ "--allowlist-var=AMETA_CTRL_ON",
+ "--allowlist-var=AMETA_CTRL_RIGHT_ON",
+ "--allowlist-var=AMETA_FUNCTION_ON",
+ "--allowlist-var=AMETA_META_LEFT_ON",
+ "--allowlist-var=AMETA_META_ON",
+ "--allowlist-var=AMETA_META_RIGHT_ON",
+ "--allowlist-var=AMETA_NONE",
"--allowlist-var=AMETA_NUM_LOCK_ON",
"--allowlist-var=AMETA_SCROLL_LOCK_ON",
+ "--allowlist-var=AMETA_SHIFT_LEFT_ON",
+ "--allowlist-var=AMETA_SHIFT_ON",
+ "--allowlist-var=AMETA_SHIFT_RIGHT_ON",
+ "--allowlist-var=AMETA_SYM_ON",
+ "--allowlist-var=AMOTION_EVENT_ACTION_CANCEL",
+ "--allowlist-var=AMOTION_EVENT_ACTION_DOWN",
+ "--allowlist-var=AMOTION_EVENT_ACTION_POINTER_DOWN",
+ "--allowlist-var=AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT",
+ "--allowlist-var=AMOTION_EVENT_ACTION_UP",
+ "--allowlist-var=AMOTION_EVENT_BUTTON_BACK",
+ "--allowlist-var=AMOTION_EVENT_BUTTON_FORWARD",
+ "--allowlist-var=AMOTION_EVENT_BUTTON_PRIMARY",
+ "--allowlist-var=AMOTION_EVENT_BUTTON_SECONDARY",
+ "--allowlist-var=AMOTION_EVENT_BUTTON_STYLUS_PRIMARY",
+ "--allowlist-var=AMOTION_EVENT_BUTTON_STYLUS_SECONDARY",
+ "--allowlist-var=AMOTION_EVENT_BUTTON_TERTIARY",
+ "--allowlist-var=MAX_POINTER_ID",
+ "--verbose",
],
static_libs: [
@@ -143,9 +150,9 @@
],
shared_libs: ["libc++"],
header_libs: [
- "native_headers",
- "jni_headers",
"flatbuffer_headers",
+ "jni_headers",
+ "native_headers",
],
}
@@ -179,8 +186,8 @@
host_supported: true,
cflags: [
"-Wall",
- "-Wextra",
"-Werror",
+ "-Wextra",
],
srcs: [
"FromRustToCpp.cpp",
@@ -205,31 +212,34 @@
cpp_std: "c++20",
host_supported: true,
cflags: [
+ "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
"-Wall",
- "-Wextra",
"-Werror",
+ "-Wextra",
"-Wno-unused-parameter",
- "-Wthread-safety",
"-Wshadow",
"-Wshadow-field-in-constructor-modified",
"-Wshadow-uncaptured-local",
- "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
+ "-Wthread-safety",
],
srcs: [
"AccelerationCurve.cpp",
+ "CoordinateFilter.cpp",
"Input.cpp",
"InputConsumer.cpp",
"InputConsumerNoResampling.cpp",
"InputDevice.cpp",
"InputEventLabels.cpp",
+ "InputFlags.cpp",
"InputTransport.cpp",
"InputVerifier.cpp",
- "Keyboard.cpp",
"KeyCharacterMap.cpp",
- "KeyboardClassifier.cpp",
"KeyLayoutMap.cpp",
+ "Keyboard.cpp",
+ "KeyboardClassifier.cpp",
"MotionPredictor.cpp",
"MotionPredictorMetricsManager.cpp",
+ "OneEuroFilter.cpp",
"PrintTools.cpp",
"PropertyMap.cpp",
"Resampler.cpp",
@@ -260,12 +270,13 @@
shared_libs: [
"android.companion.virtualdevice.flags-aconfig-cc",
+ "libPlatformProperties",
+ "libaconfig_storage_read_api_cc",
"libbase",
"libbinder",
"libbinder_ndk",
"libcutils",
"liblog",
- "libPlatformProperties",
"libtinyxml2",
"libutils",
"libz", // needed by libkernelconfigs
@@ -284,15 +295,15 @@
static_libs: [
"inputconstants-cpp",
- "libui-types",
- "libtflite_static",
"libkernelconfigs",
+ "libtflite_static",
+ "libui-types",
],
whole_static_libs: [
"com.android.input.flags-aconfig-cc",
- "libinput_rust_ffi",
"iinputflinger_aidl_lib_static",
+ "libinput_rust_ffi",
],
export_static_lib_headers: [
@@ -307,8 +318,8 @@
target: {
android: {
required: [
- "motion_predictor_model_prebuilt",
"motion_predictor_model_config",
+ "motion_predictor_model_prebuilt",
],
static_libs: [
"libstatslog_libinput",
@@ -369,9 +380,9 @@
cpp_std: "c++20",
host_supported: true,
shared_libs: [
- "libutils",
"libbase",
"liblog",
+ "libutils",
],
}
diff --git a/libs/input/CoordinateFilter.cpp b/libs/input/CoordinateFilter.cpp
new file mode 100644
index 0000000..a32685b
--- /dev/null
+++ b/libs/input/CoordinateFilter.cpp
@@ -0,0 +1,31 @@
+/**
+ * Copyright 2024 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 "CoordinateFilter"
+
+#include <input/CoordinateFilter.h>
+
+namespace android {
+
+CoordinateFilter::CoordinateFilter(float minCutoffFreq, float beta)
+ : mXFilter{minCutoffFreq, beta}, mYFilter{minCutoffFreq, beta} {}
+
+void CoordinateFilter::filter(std::chrono::nanoseconds timestamp, PointerCoords& coords) {
+ coords.setAxisValue(AMOTION_EVENT_AXIS_X, mXFilter.filter(timestamp, coords.getX()));
+ coords.setAxisValue(AMOTION_EVENT_AXIS_Y, mYFilter.filter(timestamp, coords.getY()));
+}
+
+} // namespace android
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index a2bb345..155ea00 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -284,6 +284,36 @@
return false;
}
+bool isStylusHoverEvent(uint32_t source, const std::vector<PointerProperties>& properties,
+ int32_t action) {
+ return isStylusEvent(source, properties) && isHoverAction(action);
+}
+
+bool isFromMouse(uint32_t source, ToolType toolType) {
+ return isFromSource(source, AINPUT_SOURCE_MOUSE) && toolType == ToolType::MOUSE;
+}
+
+bool isFromTouchpad(uint32_t source, ToolType toolType) {
+ return isFromSource(source, AINPUT_SOURCE_MOUSE) && toolType == ToolType::FINGER;
+}
+
+bool isFromDrawingTablet(uint32_t source, ToolType toolType) {
+ return isFromSource(source, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS) &&
+ isStylusToolType(toolType);
+}
+
+bool isHoverAction(int32_t action) {
+ return action == AMOTION_EVENT_ACTION_HOVER_ENTER ||
+ action == AMOTION_EVENT_ACTION_HOVER_MOVE || action == AMOTION_EVENT_ACTION_HOVER_EXIT;
+}
+
+bool isMouseOrTouchpad(uint32_t sources) {
+ // Check if this is a mouse or touchpad, but not a drawing tablet.
+ return isFromSource(sources, AINPUT_SOURCE_MOUSE_RELATIVE) ||
+ (isFromSource(sources, AINPUT_SOURCE_MOUSE) &&
+ !isFromSource(sources, AINPUT_SOURCE_STYLUS));
+}
+
VerifiedKeyEvent verifiedKeyEventFromKeyEvent(const KeyEvent& event) {
return {{VerifiedInputEvent::Type::KEY, event.getDeviceId(), event.getEventTime(),
event.getSource(), event.getDisplayId()},
@@ -685,11 +715,12 @@
const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
if (CC_UNLIKELY(pointerIndex < 0 || pointerIndex >= getPointerCount())) {
- LOG(FATAL) << __func__ << ": Invalid pointer index " << pointerIndex << " for " << *this;
+ LOG(FATAL) << __func__ << ": Invalid pointer index " << pointerIndex << " for "
+ << safeDump();
}
const size_t position = getHistorySize() * getPointerCount() + pointerIndex;
if (CC_UNLIKELY(position < 0 || position >= mSamplePointerCoords.size())) {
- LOG(FATAL) << __func__ << ": Invalid array index " << position << " for " << *this;
+ LOG(FATAL) << __func__ << ": Invalid array index " << position << " for " << safeDump();
}
return &mSamplePointerCoords[position];
}
@@ -705,15 +736,16 @@
const PointerCoords* MotionEvent::getHistoricalRawPointerCoords(
size_t pointerIndex, size_t historicalIndex) const {
if (CC_UNLIKELY(pointerIndex < 0 || pointerIndex >= getPointerCount())) {
- LOG(FATAL) << __func__ << ": Invalid pointer index " << pointerIndex << " for " << *this;
+ LOG(FATAL) << __func__ << ": Invalid pointer index " << pointerIndex << " for "
+ << safeDump();
}
if (CC_UNLIKELY(historicalIndex < 0 || historicalIndex > getHistorySize())) {
LOG(FATAL) << __func__ << ": Invalid historical index " << historicalIndex << " for "
- << *this;
+ << safeDump();
}
const size_t position = historicalIndex * getPointerCount() + pointerIndex;
if (CC_UNLIKELY(position < 0 || position >= mSamplePointerCoords.size())) {
- LOG(FATAL) << __func__ << ": Invalid array index " << position << " for " << *this;
+ LOG(FATAL) << __func__ << ": Invalid array index " << position << " for " << safeDump();
}
return &mSamplePointerCoords[position];
}
@@ -1144,6 +1176,53 @@
// clang-format on
}
+std::string MotionEvent::safeDump() const {
+ std::stringstream out;
+ // Field names have the m prefix here to make it easy to distinguish safeDump output from
+ // operator<< output in logs.
+ out << "MotionEvent { mAction=" << MotionEvent::actionToString(mAction);
+ if (mActionButton != 0) {
+ out << ", mActionButton=" << mActionButton;
+ }
+ if (mButtonState != 0) {
+ out << ", mButtonState=" << mButtonState;
+ }
+ if (mClassification != MotionClassification::NONE) {
+ out << ", mClassification=" << motionClassificationToString(mClassification);
+ }
+ if (mMetaState != 0) {
+ out << ", mMetaState=" << mMetaState;
+ }
+ if (mFlags != 0) {
+ out << ", mFlags=0x" << std::hex << mFlags << std::dec;
+ }
+ if (mEdgeFlags != 0) {
+ out << ", mEdgeFlags=" << mEdgeFlags;
+ }
+ out << ", mDownTime=" << mDownTime;
+ out << ", mDeviceId=" << mDeviceId;
+ out << ", mSource=" << inputEventSourceToString(mSource);
+ out << ", mDisplayId=" << mDisplayId;
+ out << ", mEventId=0x" << std::hex << mId << std::dec;
+ // Since we're not assuming the data is at all valid, we also limit the number of items that
+ // might be printed from vectors, in case the vector's size field is corrupted.
+ out << ", mPointerProperties=(" << mPointerProperties.size() << ")[";
+ for (size_t i = 0; i < mPointerProperties.size() && i < MAX_POINTERS; i++) {
+ out << (i > 0 ? ", " : "") << mPointerProperties.at(i);
+ }
+ out << "], mSampleEventTimes=(" << mSampleEventTimes.size() << ")[";
+ for (size_t i = 0; i < mSampleEventTimes.size() && i < 256; i++) {
+ out << (i > 0 ? ", " : "") << mSampleEventTimes.at(i);
+ }
+ out << "], mSamplePointerCoords=(" << mSamplePointerCoords.size() << ")[";
+ for (size_t i = 0; i < mSamplePointerCoords.size() && i < MAX_POINTERS; i++) {
+ const PointerCoords& coords = mSamplePointerCoords.at(i);
+ out << (i > 0 ? ", " : "") << "(" << coords.getX() << ", " << coords.getY() << ")";
+ }
+ out << "] }";
+ return out.str();
+}
+
std::ostream& operator<<(std::ostream& out, const MotionEvent& event) {
out << "MotionEvent { action=" << MotionEvent::actionToString(event.getAction());
if (event.getActionButton() != 0) {
diff --git a/libs/input/InputConsumerNoResampling.cpp b/libs/input/InputConsumerNoResampling.cpp
index 9665de7..6087461 100644
--- a/libs/input/InputConsumerNoResampling.cpp
+++ b/libs/input/InputConsumerNoResampling.cpp
@@ -18,6 +18,7 @@
#define ATRACE_TAG ATRACE_TAG_INPUT
#include <inttypes.h>
+#include <set>
#include <android-base/logging.h>
#include <android-base/properties.h>
@@ -169,6 +170,12 @@
msg.body.timeline.graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = presentTime;
return msg;
}
+
+std::ostream& operator<<(std::ostream& out, const InputMessage& msg) {
+ out << ftl::enum_string(msg.header.type);
+ return out;
+}
+
} // namespace
// --- InputConsumerNoResampling ---
@@ -193,13 +200,6 @@
InputConsumerNoResampling::~InputConsumerNoResampling() {
ensureCalledOnLooperThread(__func__);
- while (!mOutboundQueue.empty()) {
- processOutboundEvents();
- // This is our last chance to ack the events. If we don't ack them here, we will get an ANR,
- // so keep trying to send the events as long as they are present in the queue.
- }
-
- setFdEvents(0);
// If there are any remaining unread batches, send an ack for them and don't deliver
// them to callbacks.
for (auto& [_, batches] : mBatches) {
@@ -208,6 +208,12 @@
batches.pop();
}
}
+
+ while (!mOutboundQueue.empty()) {
+ processOutboundEvents();
+ // This is our last chance to ack the events. If we don't ack them here, we will get an ANR,
+ // so keep trying to send the events as long as they are present in the queue.
+ }
// However, it is still up to the app to finish any events that have already been delivered
// to the callbacks. If we wanted to change that behaviour and auto-finish all unfinished events
// that were already sent to callbacks, we could potentially loop through "mConsumeTimes"
@@ -216,6 +222,10 @@
const size_t unfinishedEvents = mConsumeTimes.size();
LOG_IF(INFO, unfinishedEvents != 0)
<< getName() << " has " << unfinishedEvents << " unfinished event(s)";
+ // Remove the fd from epoll, so that Looper does not call 'handleReceiveCallback' anymore.
+ // This must be done at the end of the destructor; otherwise, some of the other functions may
+ // call 'setFdEvents' as a side-effect, thus adding the fd back to the epoll set of the looper.
+ setFdEvents(0);
}
int InputConsumerNoResampling::handleReceiveCallback(int events) {
@@ -269,6 +279,15 @@
return; // try again later
}
+ if (result == DEAD_OBJECT) {
+ // If there's no one to receive events in the channel, there's no point in sending them.
+ // Drop all outbound events.
+ LOG(INFO) << "Channel " << mChannel->getName() << " died. Dropping outbound event "
+ << outboundMsg;
+ mOutboundQueue.pop();
+ setFdEvents(0);
+ continue;
+ }
// Some other error. Give up
LOG(FATAL) << "Failed to send outbound event on channel '" << mChannel->getName()
<< "'. status=" << statusToString(result) << "(" << result << ")";
@@ -357,7 +376,8 @@
mBatches[deviceId].emplace(msg);
} else {
// consume all pending batches for this device immediately
- consumeBatchedInputEvents(deviceId, /*requestedFrameTime=*/std::nullopt);
+ consumeBatchedInputEvents(deviceId, /*requestedFrameTime=*/
+ std::numeric_limits<nsecs_t>::max());
if (canResample &&
(action == AMOTION_EVENT_ACTION_UP || action == AMOTION_EVENT_ACTION_CANCEL)) {
LOG_IF(INFO, mResamplers.erase(deviceId) == 0)
@@ -480,7 +500,7 @@
}
std::pair<std::unique_ptr<MotionEvent>, std::optional<uint32_t>>
-InputConsumerNoResampling::createBatchedMotionEvent(const nsecs_t requestedFrameTime,
+InputConsumerNoResampling::createBatchedMotionEvent(const std::optional<nsecs_t> requestedFrameTime,
std::queue<InputMessage>& messages) {
std::unique_ptr<MotionEvent> motionEvent;
std::optional<uint32_t> firstSeqForBatch;
@@ -491,7 +511,11 @@
const nanoseconds resampleLatency = (resampler != mResamplers.cend())
? resampler->second->getResampleLatency()
: nanoseconds{0};
- const nanoseconds adjustedFrameTime = nanoseconds{requestedFrameTime} - resampleLatency;
+ // When batching is not enabled, we want to consume all events. That's equivalent to having an
+ // infinite requestedFrameTime.
+ const nanoseconds adjustedFrameTime = (requestedFrameTime.has_value())
+ ? (nanoseconds{*requestedFrameTime} - resampleLatency)
+ : nanoseconds{std::numeric_limits<nsecs_t>::max()};
while (!messages.empty() &&
(messages.front().body.motion.eventTime <= adjustedFrameTime.count())) {
@@ -513,8 +537,9 @@
if (!messages.empty()) {
futureSample = &messages.front();
}
- if ((motionEvent != nullptr) && (resampler != mResamplers.cend())) {
- resampler->second->resampleMotionEvent(nanoseconds{requestedFrameTime}, *motionEvent,
+ if ((motionEvent != nullptr) && (resampler != mResamplers.cend()) &&
+ (requestedFrameTime.has_value())) {
+ resampler->second->resampleMotionEvent(nanoseconds{*requestedFrameTime}, *motionEvent,
futureSample);
}
@@ -524,16 +549,13 @@
bool InputConsumerNoResampling::consumeBatchedInputEvents(
std::optional<DeviceId> deviceId, std::optional<nsecs_t> requestedFrameTime) {
ensureCalledOnLooperThread(__func__);
- // When batching is not enabled, we want to consume all events. That's equivalent to having an
- // infinite requestedFrameTime.
- requestedFrameTime = requestedFrameTime.value_or(std::numeric_limits<nsecs_t>::max());
bool producedEvents = false;
for (auto deviceIdIter = (deviceId.has_value()) ? (mBatches.find(*deviceId))
: (mBatches.begin());
deviceIdIter != mBatches.cend(); ++deviceIdIter) {
std::queue<InputMessage>& messages = deviceIdIter->second;
- auto [motion, firstSeqForBatch] = createBatchedMotionEvent(*requestedFrameTime, messages);
+ auto [motion, firstSeqForBatch] = createBatchedMotionEvent(requestedFrameTime, messages);
if (motion != nullptr) {
LOG_ALWAYS_FATAL_IF(!firstSeqForBatch.has_value());
mCallbacks.onMotionEvent(std::move(motion), *firstSeqForBatch);
diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp
index c903031..4a6f66e 100644
--- a/libs/input/InputDevice.cpp
+++ b/libs/input/InputDevice.cpp
@@ -191,7 +191,9 @@
mKeyboardLayoutInfo(other.mKeyboardLayoutInfo),
mSources(other.mSources),
mKeyboardType(other.mKeyboardType),
- mKeyCharacterMap(other.mKeyCharacterMap),
+ mKeyCharacterMap(other.mKeyCharacterMap
+ ? std::make_unique<KeyCharacterMap>(*other.mKeyCharacterMap)
+ : nullptr),
mUsiVersion(other.mUsiVersion),
mAssociatedDisplayId(other.mAssociatedDisplayId),
mEnabled(other.mEnabled),
@@ -204,6 +206,34 @@
mLights(other.mLights),
mViewBehavior(other.mViewBehavior) {}
+InputDeviceInfo& InputDeviceInfo::operator=(const InputDeviceInfo& other) {
+ mId = other.mId;
+ mGeneration = other.mGeneration;
+ mControllerNumber = other.mControllerNumber;
+ mIdentifier = other.mIdentifier;
+ mAlias = other.mAlias;
+ mIsExternal = other.mIsExternal;
+ mHasMic = other.mHasMic;
+ mKeyboardLayoutInfo = other.mKeyboardLayoutInfo;
+ mSources = other.mSources;
+ mKeyboardType = other.mKeyboardType;
+ mKeyCharacterMap = other.mKeyCharacterMap
+ ? std::make_unique<KeyCharacterMap>(*other.mKeyCharacterMap)
+ : nullptr;
+ mUsiVersion = other.mUsiVersion;
+ mAssociatedDisplayId = other.mAssociatedDisplayId;
+ mEnabled = other.mEnabled;
+ mHasVibrator = other.mHasVibrator;
+ mHasBattery = other.mHasBattery;
+ mHasButtonUnderPad = other.mHasButtonUnderPad;
+ mHasSensor = other.mHasSensor;
+ mMotionRanges = other.mMotionRanges;
+ mSensors = other.mSensors;
+ mLights = other.mLights;
+ mViewBehavior = other.mViewBehavior;
+ return *this;
+}
+
InputDeviceInfo::~InputDeviceInfo() {
}
diff --git a/libs/input/InputEventLabels.cpp b/libs/input/InputEventLabels.cpp
index 8db0ca5..b537feb 100644
--- a/libs/input/InputEventLabels.cpp
+++ b/libs/input/InputEventLabels.cpp
@@ -350,7 +350,26 @@
DEFINE_KEYCODE(MACRO_3), \
DEFINE_KEYCODE(MACRO_4), \
DEFINE_KEYCODE(EMOJI_PICKER), \
- DEFINE_KEYCODE(SCREENSHOT)
+ DEFINE_KEYCODE(SCREENSHOT), \
+ DEFINE_KEYCODE(DICTATE), \
+ DEFINE_KEYCODE(NEW), \
+ DEFINE_KEYCODE(CLOSE), \
+ DEFINE_KEYCODE(DO_NOT_DISTURB), \
+ DEFINE_KEYCODE(PRINT), \
+ DEFINE_KEYCODE(LOCK), \
+ DEFINE_KEYCODE(FULLSCREEN), \
+ DEFINE_KEYCODE(F13), \
+ DEFINE_KEYCODE(F14), \
+ DEFINE_KEYCODE(F15), \
+ DEFINE_KEYCODE(F16), \
+ DEFINE_KEYCODE(F17), \
+ DEFINE_KEYCODE(F18), \
+ DEFINE_KEYCODE(F19),\
+ DEFINE_KEYCODE(F20), \
+ DEFINE_KEYCODE(F21), \
+ DEFINE_KEYCODE(F22), \
+ DEFINE_KEYCODE(F23), \
+ DEFINE_KEYCODE(F24)
// NOTE: If you add a new axis here you must also add it to several other files.
// Refer to frameworks/base/core/java/android/view/MotionEvent.java for the full list.
diff --git a/libs/input/InputFlags.cpp b/libs/input/InputFlags.cpp
new file mode 100644
index 0000000..f866f9b
--- /dev/null
+++ b/libs/input/InputFlags.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2025 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 <input/InputFlags.h>
+
+#include <android-base/logging.h>
+#include <com_android_input_flags.h>
+#include <cutils/properties.h>
+
+#include <string>
+
+namespace android {
+
+bool InputFlags::connectedDisplaysCursorEnabled() {
+ static std::optional<bool> cachedDevOption;
+ if (!cachedDevOption.has_value()) {
+ char value[PROPERTY_VALUE_MAX];
+ constexpr static auto sysprop_name = "persist.wm.debug.desktop_experience_devopts";
+ const int devOptionEnabled =
+ property_get(sysprop_name, value, nullptr) > 0 ? std::atoi(value) : 0;
+ cachedDevOption = devOptionEnabled == 1;
+ }
+ if (cachedDevOption.value_or(false)) {
+ return true;
+ }
+ return com::android::input::flags::connected_displays_cursor();
+}
+
+bool InputFlags::connectedDisplaysCursorAndAssociatedDisplayCursorBugfixEnabled() {
+ return connectedDisplaysCursorEnabled() &&
+ com::android::input::flags::connected_displays_associated_display_cursor_bugfix();
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 77dcaa9..d388d48 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -327,8 +327,8 @@
android::base::unique_fd fd, sp<IBinder> token) {
const int result = fcntl(fd, F_SETFL, O_NONBLOCK);
if (result != 0) {
- LOG_ALWAYS_FATAL("channel '%s' ~ Could not make socket non-blocking: %s", name.c_str(),
- strerror(errno));
+ LOG_ALWAYS_FATAL("channel '%s' ~ Could not make socket (%d) non-blocking: %s", name.c_str(),
+ fd.get(), strerror(errno));
return nullptr;
}
// using 'new' to access a non-public constructor
@@ -583,15 +583,6 @@
StringPrintf("publishMotionEvent(inputChannel=%s, action=%s)",
mChannel->getName().c_str(),
MotionEvent::actionToString(action).c_str()));
- if (verifyEvents()) {
- Result<void> result =
- mInputVerifier.processMovement(deviceId, source, action, pointerCount,
- pointerProperties, pointerCoords, flags);
- if (!result.ok()) {
- LOG(ERROR) << "Bad stream: " << result.error();
- return BAD_VALUE;
- }
- }
if (debugTransportPublisher()) {
std::string transformString;
transform.dump(transformString, "transform", " ");
@@ -657,8 +648,18 @@
msg.body.motion.pointers[i].properties = pointerProperties[i];
msg.body.motion.pointers[i].coords = pointerCoords[i];
}
+ const status_t status = mChannel->sendMessage(&msg);
- return mChannel->sendMessage(&msg);
+ if (status == OK && verifyEvents()) {
+ Result<void> result = mInputVerifier.processMovement(deviceId, source, action, actionButton,
+ pointerCount, pointerProperties,
+ pointerCoords, flags, buttonState);
+ if (!result.ok()) {
+ LOG(ERROR) << "Bad stream: " << result.error();
+ return BAD_VALUE;
+ }
+ }
+ return status;
}
status_t InputPublisher::publishFocusEvent(uint32_t seq, int32_t eventId, bool hasFocus) {
diff --git a/libs/input/InputVerifier.cpp b/libs/input/InputVerifier.cpp
index cec2445..7811ace 100644
--- a/libs/input/InputVerifier.cpp
+++ b/libs/input/InputVerifier.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "InputVerifier"
#include <android-base/logging.h>
+#include <com_android_input_flags.h>
#include <input/InputVerifier.h>
#include "input_cxx_bridge.rs.h"
@@ -26,17 +27,23 @@
using DeviceId = int32_t;
+namespace input_flags = com::android::input::flags;
+
namespace android {
// --- InputVerifier ---
InputVerifier::InputVerifier(const std::string& name)
- : mVerifier(android::input::verifier::create(rust::String::lossy(name))){};
+ : mVerifier(
+ android::input::verifier::create(rust::String::lossy(name),
+ input_flags::enable_button_state_verification())) {
+}
Result<void> InputVerifier::processMovement(DeviceId deviceId, int32_t source, int32_t action,
- uint32_t pointerCount,
+ int32_t actionButton, uint32_t pointerCount,
const PointerProperties* pointerProperties,
- const PointerCoords* pointerCoords, int32_t flags) {
+ const PointerCoords* pointerCoords, int32_t flags,
+ int32_t buttonState) {
std::vector<RustPointerProperties> rpp;
for (size_t i = 0; i < pointerCount; i++) {
rpp.emplace_back(RustPointerProperties{.id = pointerProperties[i].id});
@@ -44,7 +51,9 @@
rust::Slice<const RustPointerProperties> properties{rpp.data(), rpp.size()};
rust::String errorMessage =
android::input::verifier::process_movement(*mVerifier, deviceId, source, action,
- properties, static_cast<uint32_t>(flags));
+ actionButton, properties,
+ static_cast<uint32_t>(flags),
+ static_cast<uint32_t>(buttonState));
if (errorMessage.empty()) {
return {};
} else {
diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp
index d775327..d2c49b1 100644
--- a/libs/input/KeyCharacterMap.cpp
+++ b/libs/input/KeyCharacterMap.cpp
@@ -84,15 +84,15 @@
KeyCharacterMap::KeyCharacterMap(const std::string& filename) : mLoadFileName(filename) {}
-base::Result<std::shared_ptr<KeyCharacterMap>> KeyCharacterMap::load(const std::string& filename,
+base::Result<std::unique_ptr<KeyCharacterMap>> KeyCharacterMap::load(const std::string& filename,
Format format) {
Tokenizer* tokenizer;
status_t status = Tokenizer::open(String8(filename.c_str()), &tokenizer);
if (status) {
return Errorf("Error {} opening key character map file {}.", status, filename.c_str());
}
- std::shared_ptr<KeyCharacterMap> map =
- std::shared_ptr<KeyCharacterMap>(new KeyCharacterMap(filename));
+ std::unique_ptr<KeyCharacterMap> map =
+ std::unique_ptr<KeyCharacterMap>(new KeyCharacterMap(filename));
if (!map.get()) {
ALOGE("Error allocating key character map.");
return Errorf("Error allocating key character map.");
@@ -615,7 +615,7 @@
ALOGE("%s: Null parcel", __func__);
return nullptr;
}
- std::string loadFileName = parcel->readCString();
+ std::string loadFileName = parcel->readString8().c_str();
std::unique_ptr<KeyCharacterMap> map =
std::make_unique<KeyCharacterMap>(KeyCharacterMap(loadFileName));
map->mType = static_cast<KeyCharacterMap::KeyboardType>(parcel->readInt32());
@@ -704,7 +704,7 @@
ALOGE("%s: Null parcel", __func__);
return;
}
- parcel->writeCString(mLoadFileName.c_str());
+ parcel->writeString8(String8(mLoadFileName.c_str()));
parcel->writeInt32(static_cast<int32_t>(mType));
parcel->writeBool(mLayoutOverlayApplied);
diff --git a/libs/input/KeyboardClassifier.cpp b/libs/input/KeyboardClassifier.cpp
index 0c2c7be..2a83919 100644
--- a/libs/input/KeyboardClassifier.cpp
+++ b/libs/input/KeyboardClassifier.cpp
@@ -57,14 +57,14 @@
uint32_t deviceClasses) {
if (mRustClassifier) {
RustInputDeviceIdentifier rustIdentifier;
- rustIdentifier.name = identifier.name;
- rustIdentifier.location = identifier.location;
- rustIdentifier.unique_id = identifier.uniqueId;
+ rustIdentifier.name = rust::String::lossy(identifier.name);
+ rustIdentifier.location = rust::String::lossy(identifier.location);
+ rustIdentifier.unique_id = rust::String::lossy(identifier.uniqueId);
rustIdentifier.bus = identifier.bus;
rustIdentifier.vendor = identifier.vendor;
rustIdentifier.product = identifier.product;
rustIdentifier.version = identifier.version;
- rustIdentifier.descriptor = identifier.descriptor;
+ rustIdentifier.descriptor = rust::String::lossy(identifier.descriptor);
android::input::keyboardClassifier::notifyKeyboardChanged(**mRustClassifier, deviceId,
rustIdentifier, deviceClasses);
} else {
diff --git a/libs/input/OneEuroFilter.cpp b/libs/input/OneEuroFilter.cpp
new file mode 100644
index 0000000..7b0d104
--- /dev/null
+++ b/libs/input/OneEuroFilter.cpp
@@ -0,0 +1,87 @@
+/**
+ * Copyright 2024 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 "OneEuroFilter"
+
+#include <chrono>
+#include <cmath>
+
+#include <android-base/logging.h>
+#include <input/CoordinateFilter.h>
+
+namespace android {
+namespace {
+
+using namespace std::literals::chrono_literals;
+
+const float kHertzPerGigahertz = 1E9f;
+const float kGigahertzPerHertz = 1E-9f;
+
+// filteredSpeed's units are position per nanosecond. beta's units are 1 / position.
+inline float cutoffFreq(float minCutoffFreq, float beta, float filteredSpeed) {
+ return kHertzPerGigahertz *
+ ((minCutoffFreq * kGigahertzPerHertz) + beta * std::abs(filteredSpeed));
+}
+
+inline float smoothingFactor(std::chrono::nanoseconds samplingPeriod, float cutoffFreq) {
+ const float constant = 2.0f * M_PI * samplingPeriod.count() * (cutoffFreq * kGigahertzPerHertz);
+ return constant / (constant + 1);
+}
+
+inline float lowPassFilter(float rawValue, float prevFilteredValue, float smoothingFactor) {
+ return smoothingFactor * rawValue + (1 - smoothingFactor) * prevFilteredValue;
+}
+
+} // namespace
+
+OneEuroFilter::OneEuroFilter(float minCutoffFreq, float beta, float speedCutoffFreq)
+ : mMinCutoffFreq{minCutoffFreq}, mBeta{beta}, mSpeedCutoffFreq{speedCutoffFreq} {}
+
+float OneEuroFilter::filter(std::chrono::nanoseconds timestamp, float rawPosition) {
+ LOG_IF(FATAL, mPrevTimestamp.has_value() && (*mPrevTimestamp >= timestamp))
+ << "Timestamp must be greater than mPrevTimestamp. Timestamp: " << timestamp.count()
+ << "ns. mPrevTimestamp: " << mPrevTimestamp->count() << "ns";
+
+ const std::chrono::nanoseconds samplingPeriod =
+ (mPrevTimestamp.has_value()) ? (timestamp - *mPrevTimestamp) : 1s;
+
+ const float rawVelocity = (mPrevFilteredPosition.has_value())
+ ? ((rawPosition - *mPrevFilteredPosition) / (samplingPeriod.count()))
+ : 0.0f;
+
+ const float speedSmoothingFactor = smoothingFactor(samplingPeriod, mSpeedCutoffFreq);
+
+ const float filteredVelocity = (mPrevFilteredVelocity.has_value())
+ ? lowPassFilter(rawVelocity, *mPrevFilteredVelocity, speedSmoothingFactor)
+ : rawVelocity;
+
+ const float positionCutoffFreq = cutoffFreq(mMinCutoffFreq, mBeta, filteredVelocity);
+
+ const float positionSmoothingFactor = smoothingFactor(samplingPeriod, positionCutoffFreq);
+
+ const float filteredPosition = (mPrevFilteredPosition.has_value())
+ ? lowPassFilter(rawPosition, *mPrevFilteredPosition, positionSmoothingFactor)
+ : rawPosition;
+
+ mPrevTimestamp = timestamp;
+ mPrevRawPosition = rawPosition;
+ mPrevFilteredVelocity = filteredVelocity;
+ mPrevFilteredPosition = filteredPosition;
+
+ return filteredPosition;
+}
+
+} // namespace android
diff --git a/libs/input/Resampler.cpp b/libs/input/Resampler.cpp
index e2cc6fb..3ab132d 100644
--- a/libs/input/Resampler.cpp
+++ b/libs/input/Resampler.cpp
@@ -18,6 +18,7 @@
#include <algorithm>
#include <chrono>
+#include <iomanip>
#include <ostream>
#include <android-base/logging.h>
@@ -37,6 +38,11 @@
true;
#endif
+/**
+ * Log debug messages about timestamp and coordinates of event resampling.
+ * Enable this via "adb shell setprop log.tag.LegacyResamplerResampling DEBUG"
+ * (requires restart)
+ */
bool debugResampling() {
if (!IS_DEBUGGABLE_BUILD) {
static const bool DEBUG_TRANSPORT_RESAMPLING =
@@ -107,46 +113,44 @@
const size_t latestIndex = numSamples - 1;
const size_t secondToLatestIndex = (latestIndex > 0) ? (latestIndex - 1) : 0;
for (size_t sampleIndex = secondToLatestIndex; sampleIndex < numSamples; ++sampleIndex) {
- std::vector<Pointer> pointers;
- const size_t numPointers = motionEvent.getPointerCount();
- for (size_t pointerIndex = 0; pointerIndex < numPointers; ++pointerIndex) {
- pointers.push_back(Pointer{*(motionEvent.getPointerProperties(pointerIndex)),
- *(motionEvent.getHistoricalRawPointerCoords(pointerIndex,
- sampleIndex))});
+ PointerMap pointerMap;
+ for (size_t pointerIndex = 0; pointerIndex < motionEvent.getPointerCount();
+ ++pointerIndex) {
+ pointerMap.insert(Pointer{*(motionEvent.getPointerProperties(pointerIndex)),
+ *(motionEvent.getHistoricalRawPointerCoords(pointerIndex,
+ sampleIndex))});
}
mLatestSamples.pushBack(
- Sample{nanoseconds{motionEvent.getHistoricalEventTime(sampleIndex)}, pointers});
+ Sample{nanoseconds{motionEvent.getHistoricalEventTime(sampleIndex)}, pointerMap});
}
}
LegacyResampler::Sample LegacyResampler::messageToSample(const InputMessage& message) {
- std::vector<Pointer> pointers;
+ PointerMap pointerMap;
for (uint32_t i = 0; i < message.body.motion.pointerCount; ++i) {
- pointers.push_back(Pointer{message.body.motion.pointers[i].properties,
- message.body.motion.pointers[i].coords});
+ pointerMap.insert(Pointer{message.body.motion.pointers[i].properties,
+ message.body.motion.pointers[i].coords});
}
- return Sample{nanoseconds{message.body.motion.eventTime}, pointers};
+ return Sample{nanoseconds{message.body.motion.eventTime}, pointerMap};
}
bool LegacyResampler::pointerPropertiesResampleable(const Sample& target, const Sample& auxiliary) {
- if (target.pointers.size() > auxiliary.pointers.size()) {
- LOG_IF(INFO, debugResampling())
- << "Not resampled. Auxiliary sample has fewer pointers than target sample.";
- return false;
- }
- for (size_t i = 0; i < target.pointers.size(); ++i) {
- if (target.pointers[i].properties.id != auxiliary.pointers[i].properties.id) {
- LOG_IF(INFO, debugResampling()) << "Not resampled. Pointer ID mismatch.";
+ for (const Pointer& pointer : target.pointerMap) {
+ const std::optional<Pointer> auxiliaryPointer =
+ auxiliary.pointerMap.find(PointerMap::PointerId{pointer.properties.id});
+ if (!auxiliaryPointer.has_value()) {
+ LOG_IF(INFO, debugResampling())
+ << "Not resampled. Auxiliary sample does not contain all pointers from target.";
return false;
}
- if (target.pointers[i].properties.toolType != auxiliary.pointers[i].properties.toolType) {
+ if (pointer.properties.toolType != auxiliaryPointer->properties.toolType) {
LOG_IF(INFO, debugResampling()) << "Not resampled. Pointer ToolType mismatch.";
return false;
}
- if (!canResampleTool(target.pointers[i].properties.toolType)) {
+ if (!canResampleTool(pointer.properties.toolType)) {
LOG_IF(INFO, debugResampling())
<< "Not resampled. Cannot resample "
- << ftl::enum_string(target.pointers[i].properties.toolType) << " ToolType.";
+ << ftl::enum_string(pointer.properties.toolType) << " ToolType.";
return false;
}
}
@@ -166,35 +170,40 @@
const nanoseconds delta = futureSample.eventTime - pastSample.eventTime;
if (delta < RESAMPLE_MIN_DELTA) {
- LOG_IF(INFO, debugResampling()) << "Not resampled. Delta is too small: " << delta << "ns.";
+ LOG_IF(INFO, debugResampling())
+ << "Not resampled. Delta is too small: " << std::setprecision(3)
+ << std::chrono::duration<double, std::milli>{delta}.count() << "ms";
return false;
}
return true;
}
std::optional<LegacyResampler::Sample> LegacyResampler::attemptInterpolation(
- nanoseconds resampleTime, const InputMessage& futureSample) const {
- if (!canInterpolate(futureSample)) {
+ nanoseconds resampleTime, const InputMessage& futureMessage) const {
+ if (!canInterpolate(futureMessage)) {
return std::nullopt;
}
LOG_IF(FATAL, mLatestSamples.empty())
<< "Not resampled. mLatestSamples must not be empty to interpolate.";
const Sample& pastSample = *(mLatestSamples.end() - 1);
+ const Sample& futureSample = messageToSample(futureMessage);
- const nanoseconds delta =
- nanoseconds{futureSample.body.motion.eventTime} - pastSample.eventTime;
+ const nanoseconds delta = nanoseconds{futureSample.eventTime} - pastSample.eventTime;
const float alpha =
- std::chrono::duration<float, std::milli>(resampleTime - pastSample.eventTime) / delta;
+ std::chrono::duration<float, std::nano>(resampleTime - pastSample.eventTime) / delta;
- std::vector<Pointer> resampledPointers;
- for (size_t i = 0; i < pastSample.pointers.size(); ++i) {
- const PointerCoords& resampledCoords =
- calculateResampledCoords(pastSample.pointers[i].coords,
- futureSample.body.motion.pointers[i].coords, alpha);
- resampledPointers.push_back(Pointer{pastSample.pointers[i].properties, resampledCoords});
+ PointerMap resampledPointerMap;
+ for (const Pointer& pointer : pastSample.pointerMap) {
+ if (std::optional<Pointer> futureSamplePointer =
+ futureSample.pointerMap.find(PointerMap::PointerId{pointer.properties.id});
+ futureSamplePointer.has_value()) {
+ const PointerCoords& resampledCoords =
+ calculateResampledCoords(pointer.coords, futureSamplePointer->coords, alpha);
+ resampledPointerMap.insert(Pointer{pointer.properties, resampledCoords});
+ }
}
- return Sample{resampleTime, resampledPointers};
+ return Sample{resampleTime, resampledPointerMap};
}
bool LegacyResampler::canExtrapolate() const {
@@ -212,10 +221,14 @@
const nanoseconds delta = presentSample.eventTime - pastSample.eventTime;
if (delta < RESAMPLE_MIN_DELTA) {
- LOG_IF(INFO, debugResampling()) << "Not resampled. Delta is too small: " << delta << "ns.";
+ LOG_IF(INFO, debugResampling())
+ << "Not resampled. Delta is too small: " << std::setprecision(3)
+ << std::chrono::duration<double, std::milli>{delta}.count() << "ms";
return false;
} else if (delta > RESAMPLE_MAX_DELTA) {
- LOG_IF(INFO, debugResampling()) << "Not resampled. Delta is too large: " << delta << "ns.";
+ LOG_IF(INFO, debugResampling())
+ << "Not resampled. Delta is too large: " << std::setprecision(3)
+ << std::chrono::duration<double, std::milli>{delta}.count() << "ms";
return false;
}
return true;
@@ -241,20 +254,28 @@
(resampleTime > farthestPrediction) ? (farthestPrediction) : (resampleTime);
LOG_IF(INFO, debugResampling() && newResampleTime == farthestPrediction)
<< "Resample time is too far in the future. Adjusting prediction from "
- << (resampleTime - presentSample.eventTime) << " to "
- << (farthestPrediction - presentSample.eventTime) << "ns.";
+ << std::setprecision(3)
+ << std::chrono::duration<double, std::milli>{resampleTime - presentSample.eventTime}
+ .count()
+ << "ms to "
+ << std::chrono::duration<double, std::milli>{farthestPrediction -
+ presentSample.eventTime}
+ .count()
+ << "ms";
const float alpha =
- std::chrono::duration<float, std::milli>(newResampleTime - pastSample.eventTime) /
- delta;
+ std::chrono::duration<float, std::nano>(newResampleTime - pastSample.eventTime) / delta;
- std::vector<Pointer> resampledPointers;
- for (size_t i = 0; i < presentSample.pointers.size(); ++i) {
- const PointerCoords& resampledCoords =
- calculateResampledCoords(pastSample.pointers[i].coords,
- presentSample.pointers[i].coords, alpha);
- resampledPointers.push_back(Pointer{presentSample.pointers[i].properties, resampledCoords});
+ PointerMap resampledPointerMap;
+ for (const Pointer& pointer : presentSample.pointerMap) {
+ if (std::optional<Pointer> pastSamplePointer =
+ pastSample.pointerMap.find(PointerMap::PointerId{pointer.properties.id});
+ pastSamplePointer.has_value()) {
+ const PointerCoords& resampledCoords =
+ calculateResampledCoords(pastSamplePointer->coords, pointer.coords, alpha);
+ resampledPointerMap.insert(Pointer{pointer.properties, resampledCoords});
+ }
}
- return Sample{newResampleTime, resampledPointers};
+ return Sample{newResampleTime, resampledPointerMap};
}
inline void LegacyResampler::addSampleToMotionEvent(const Sample& sample,
@@ -267,6 +288,12 @@
return RESAMPLE_LATENCY;
}
+/**
+ * The resampler is unaware of ACTION_DOWN. Thus, it needs to constantly check for pointer IDs
+ * occurrences. This problem could be fixed if the resampler has access to the entire stream of
+ * MotionEvent actions. That way, both ACTION_DOWN and ACTION_UP will be visible; therefore,
+ * facilitating pointer tracking between samples.
+ */
void LegacyResampler::overwriteMotionEventSamples(MotionEvent& motionEvent) const {
const size_t numSamples = motionEvent.getHistorySize() + 1;
for (size_t sampleIndex = 0; sampleIndex < numSamples; ++sampleIndex) {
@@ -276,34 +303,59 @@
}
void LegacyResampler::overwriteStillPointers(MotionEvent& motionEvent, size_t sampleIndex) const {
+ if (!mLastRealSample.has_value() || !mPreviousPrediction.has_value()) {
+ LOG_IF(INFO, debugResampling()) << "Still pointers not overwritten. Not enough data.";
+ return;
+ }
for (size_t pointerIndex = 0; pointerIndex < motionEvent.getPointerCount(); ++pointerIndex) {
+ const std::optional<Pointer> lastRealPointer = mLastRealSample->pointerMap.find(
+ PointerMap::PointerId{motionEvent.getPointerId(pointerIndex)});
+ const std::optional<Pointer> previousPointer = mPreviousPrediction->pointerMap.find(
+ PointerMap::PointerId{motionEvent.getPointerId(pointerIndex)});
+ // This could happen because resampler only receives ACTION_MOVE events.
+ if (!lastRealPointer.has_value() || !previousPointer.has_value()) {
+ continue;
+ }
const PointerCoords& pointerCoords =
*(motionEvent.getHistoricalRawPointerCoords(pointerIndex, sampleIndex));
- if (equalXY(mLastRealSample->pointers[pointerIndex].coords, pointerCoords)) {
+ if (equalXY(pointerCoords, lastRealPointer->coords)) {
LOG_IF(INFO, debugResampling())
<< "Pointer ID: " << motionEvent.getPointerId(pointerIndex)
<< " did not move. Overwriting its coordinates from " << pointerCoords << " to "
- << mLastRealSample->pointers[pointerIndex].coords;
+ << previousPointer->coords;
setMotionEventPointerCoords(motionEvent, sampleIndex, pointerIndex,
- mPreviousPrediction->pointers[pointerIndex].coords);
+ previousPointer->coords);
}
}
}
void LegacyResampler::overwriteOldPointers(MotionEvent& motionEvent, size_t sampleIndex) const {
if (!mPreviousPrediction.has_value()) {
+ LOG_IF(INFO, debugResampling()) << "Old sample not overwritten. Not enough data.";
return;
}
if (nanoseconds{motionEvent.getHistoricalEventTime(sampleIndex)} <
mPreviousPrediction->eventTime) {
LOG_IF(INFO, debugResampling())
<< "Motion event sample older than predicted sample. Overwriting event time from "
- << motionEvent.getHistoricalEventTime(sampleIndex) << "ns to "
- << mPreviousPrediction->eventTime.count() << "ns.";
+ << std::setprecision(3)
+ << std::chrono::duration<double,
+ std::milli>{nanoseconds{motionEvent.getHistoricalEventTime(
+ sampleIndex)}}
+ .count()
+ << "ms to "
+ << std::chrono::duration<double, std::milli>{mPreviousPrediction->eventTime}.count()
+ << "ms";
for (size_t pointerIndex = 0; pointerIndex < motionEvent.getPointerCount();
++pointerIndex) {
+ const std::optional<Pointer> previousPointer = mPreviousPrediction->pointerMap.find(
+ PointerMap::PointerId{motionEvent.getPointerId(pointerIndex)});
+ // This could happen because resampler only receives ACTION_MOVE events.
+ if (!previousPointer.has_value()) {
+ continue;
+ }
setMotionEventPointerCoords(motionEvent, sampleIndex, pointerIndex,
- mPreviousPrediction->pointers[pointerIndex].coords);
+ previousPointer->coords);
}
}
}
@@ -333,7 +385,38 @@
mPreviousPrediction = sample;
}
}
+ LOG_IF(FATAL, mLatestSamples.empty()) << "mLatestSamples must contain at least one sample.";
mLastRealSample = *(mLatestSamples.end() - 1);
}
+// --- FilteredLegacyResampler ---
+
+FilteredLegacyResampler::FilteredLegacyResampler(float minCutoffFreq, float beta)
+ : mResampler{}, mMinCutoffFreq{minCutoffFreq}, mBeta{beta} {}
+
+void FilteredLegacyResampler::resampleMotionEvent(std::chrono::nanoseconds requestedFrameTime,
+ MotionEvent& motionEvent,
+ const InputMessage* futureSample) {
+ mResampler.resampleMotionEvent(requestedFrameTime, motionEvent, futureSample);
+ const size_t numSamples = motionEvent.getHistorySize() + 1;
+ for (size_t sampleIndex = 0; sampleIndex < numSamples; ++sampleIndex) {
+ for (size_t pointerIndex = 0; pointerIndex < motionEvent.getPointerCount();
+ ++pointerIndex) {
+ const int32_t pointerId = motionEvent.getPointerProperties(pointerIndex)->id;
+ const nanoseconds eventTime =
+ nanoseconds{motionEvent.getHistoricalEventTime(sampleIndex)};
+ // Refer to the static function `setMotionEventPointerCoords` for a justification of
+ // casting away const.
+ PointerCoords& pointerCoords = const_cast<PointerCoords&>(
+ *(motionEvent.getHistoricalRawPointerCoords(pointerIndex, sampleIndex)));
+ const auto& [iter, _] = mFilteredPointers.try_emplace(pointerId, mMinCutoffFreq, mBeta);
+ iter->second.filter(eventTime, pointerCoords);
+ }
+ }
+}
+
+std::chrono::nanoseconds FilteredLegacyResampler::getResampleLatency() const {
+ return mResampler.getResampleLatency();
+}
+
} // namespace android
diff --git a/libs/input/android/os/IInputConstants.aidl b/libs/input/android/os/IInputConstants.aidl
index 31592cd..4b87dab 100644
--- a/libs/input/android/os/IInputConstants.aidl
+++ b/libs/input/android/os/IInputConstants.aidl
@@ -43,8 +43,9 @@
const int INVALID_INPUT_DEVICE_ID = -2;
/**
- * The input event was injected from accessibility. Used in policyFlags for input event
- * injection.
+ * The input event was injected from some AccessibilityService, which may be either an
+ * Accessibility Tool OR a service using that API for purposes other than assisting users with
+ * disabilities. Used in policyFlags for input event injection.
*/
const int POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY = 0x20000;
@@ -55,18 +56,33 @@
const int POLICY_FLAG_KEY_GESTURE_TRIGGERED = 0x40000;
/**
+ * The input event was injected from an AccessibilityService with the
+ * AccessibilityServiceInfo#isAccessibilityTool property set to true. These services (known as
+ * "Accessibility Tools") are used to assist users with disabilities, so events from these
+ * services should be able to reach all Views including Views which set
+ * View#isAccessibilityDataSensitive to true. Used in policyFlags for input event injection.
+ */
+ const int POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY_TOOL = 0x80000;
+
+ /**
* Common input event flag used for both motion and key events for a gesture or pointer being
* canceled.
*/
const int INPUT_EVENT_FLAG_CANCELED = 0x20;
/**
- * Common input event flag used for both motion and key events, indicating that the event
- * was generated or modified by accessibility service.
+ * Input event flag used for both motion and key events.
+ * See POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY for more information.
*/
const int INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT = 0x800;
/**
+ * Input event flag used for motion events.
+ * See POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY_TOOL for more information.
+ */
+ const int INPUT_EVENT_FLAG_INJECTED_FROM_ACCESSIBILITY_TOOL = 0x1000;
+
+ /**
* Common input event flag used for both motion and key events, indicating that the system has
* detected this event may be inconsistent with the current event sequence or gesture, such as
* when a pointer move event is sent but the pointer is not down.
@@ -76,6 +92,9 @@
/* The default pointer acceleration value. */
const int DEFAULT_POINTER_ACCELERATION = 3;
+ /* The default mouse wheel acceleration value. */
+ const int DEFAULT_MOUSE_WHEEL_ACCELERATION = 4;
+
/**
* Use the default Velocity Tracker Strategy. Different axes may use different default
* strategies.
diff --git a/libs/input/android/os/InputConfig.aidl b/libs/input/android/os/InputConfig.aidl
index da62e03..e5f7b56 100644
--- a/libs/input/android/os/InputConfig.aidl
+++ b/libs/input/android/os/InputConfig.aidl
@@ -57,16 +57,9 @@
NOT_TOUCHABLE = 1 << 3,
/**
- * Indicates that this window will not accept a touch event that is split between
- * more than one window. When set:
- * - If this window receives a DOWN event with the first pointer, all successive
- * pointers that go down, regardless of their location on the screen, will be
- * directed to this window;
- * - If the DOWN event lands outside the touchable bounds of this window, no
- * successive pointers that go down, regardless of their location on the screen,
- * will be directed to this window.
+ * This flag is now deprecated and should not be used.
*/
- PREVENT_SPLITTING = 1 << 4,
+ DEPRECATED_PREVENT_SPLITTING = 1 << 4,
/**
* Indicates that this window shows the wallpaper behind it, so all touch events
diff --git a/libs/input/android/os/MotionEventFlag.aidl b/libs/input/android/os/MotionEventFlag.aidl
index 2093b06..6c9ccfb 100644
--- a/libs/input/android/os/MotionEventFlag.aidl
+++ b/libs/input/android/os/MotionEventFlag.aidl
@@ -118,13 +118,24 @@
PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION = 0x100,
/**
- * The input event was generated or modified by accessibility service.
- * Shared by both KeyEvent and MotionEvent flags, so this value should not overlap with either
- * set of flags, including in input/Input.h and in android/input.h.
+ * The input event was injected from some AccessibilityService, which may be either an
+ * Accessibility Tool OR a service using that API for purposes other than assisting users with
+ * disabilities. Shared by both KeyEvent and MotionEvent flags, so this value should not
+ * overlap with either set of flags, including in input/Input.h and in android/input.h.
*/
IS_ACCESSIBILITY_EVENT = IInputConstants.INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT,
/**
+ * The input event was injected from an AccessibilityService with the
+ * AccessibilityServiceInfo#isAccessibilityTool property set to true. These services (known as
+ * "Accessibility Tools") are used to assist users with disabilities, so events from these
+ * services should be able to reach all Views including Views which set
+ * View#isAccessibilityDataSensitive to true. Only used by MotionEvent flags.
+ */
+ INJECTED_FROM_ACCESSIBILITY_TOOL =
+ IInputConstants.INPUT_EVENT_FLAG_INJECTED_FROM_ACCESSIBILITY_TOOL,
+
+ /**
* Private flag that indicates when the system has detected that this motion event
* may be inconsistent with respect to the sequence of previously delivered motion events,
* such as when a pointer move event is sent but the pointer is not down.
diff --git a/libs/input/input_flags.aconfig b/libs/input/input_flags.aconfig
index 701fb43..9d387fe 100644
--- a/libs/input/input_flags.aconfig
+++ b/libs/input/input_flags.aconfig
@@ -16,6 +16,16 @@
}
flag {
+ name: "enable_button_state_verification"
+ namespace: "input"
+ description: "Set to true to enable crashing whenever bad inbound events are going into InputDispatcher"
+ bug: "392870542"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "remove_input_channel_from_windowstate"
namespace: "input"
description: "Do not store a copy of input channel inside WindowState."
@@ -37,9 +47,9 @@
}
flag {
- name: "split_all_touches"
+ name: "deprecate_split_touch_apis"
namespace: "input"
- description: "Set FLAG_SPLIT_TOUCHES to true for all windows, regardless of what they specify. This is essentially deprecating this flag by forcefully enabling the split functionality"
+ description: "Deprecate all public APIs related to split touch because now all windows behave as if split touch is permanently enabled and there's no way for a window to disable split touch."
bug: "239934827"
}
@@ -51,13 +61,6 @@
}
flag {
- name: "report_palms_to_gestures_library"
- namespace: "input"
- description: "Report touches marked as palm by firmware to gestures library"
- bug: "302505955"
-}
-
-flag {
name: "enable_touchpad_typing_palm_rejection"
namespace: "input"
description: "Enabling additional touchpad palm rejection will disable the tap to click while the user is typing on a physical keyboard"
@@ -79,13 +82,6 @@
}
flag {
- name: "enable_input_filter_rust_impl"
- namespace: "input"
- description: "Enable input filter rust implementation"
- bug: "294546335"
-}
-
-flag {
name: "override_key_behavior_permission_apis"
is_exported: true
namespace: "input"
@@ -94,13 +90,6 @@
}
flag {
- name: "enable_new_mouse_pointer_ballistics"
- namespace: "input"
- description: "Change the acceleration curves for mouse pointer movements to match the touchpad ones"
- bug: "315313622"
-}
-
-flag {
name: "rate_limit_user_activity_poke_in_dispatcher"
namespace: "input"
description: "Move user-activity poke rate-limiting from PowerManagerService to InputDispatcher."
@@ -116,13 +105,6 @@
}
flag {
- name: "enable_touchpad_fling_stop"
- namespace: "input"
- description: "Enable fling scrolling to be stopped by putting a finger on the touchpad again"
- bug: "281106755"
-}
-
-flag {
name: "enable_prediction_pruning_via_jerk_thresholding"
namespace: "input"
description: "Enable prediction pruning based on jerk thresholds."
@@ -202,6 +184,16 @@
}
flag {
+ name: "disable_touch_input_mapper_pointer_usage"
+ namespace: "input"
+ description: "Disable the PointerUsage concept in TouchInputMapper since the old touchpad stack is no longer used."
+ bug: "281840344"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "keyboard_repeat_keys"
namespace: "input"
description: "Allow user to enable key repeats or configure timeout before key repeat and key repeat delay rates."
@@ -214,3 +206,64 @@
description: "Enable telemetry for rotary input"
bug: "370353565"
}
+
+flag {
+ name: "set_input_device_kernel_wake"
+ namespace: "input"
+ description: "Set input device's power/wakeup sysfs node"
+ bug: "372812925"
+}
+
+flag {
+ name: "enable_alphabetic_keyboard_wake"
+ namespace: "input"
+ description: "Enable wake from alphabetic keyboards."
+ bug: "352856881"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "connected_displays_cursor"
+ namespace: "lse_desktop_experience"
+ description: "Allow cursor to transition across multiple connected displays"
+ bug: "362719483"
+}
+
+flag {
+ name: "connected_displays_associated_display_cursor_bugfix"
+ namespace: "lse_desktop_experience"
+ description: "Apply some rules to define associated display cursor behavior in connected displays"
+ bug: "396568321"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "use_cloned_screen_coordinates_as_raw"
+ namespace: "input"
+ description: "Use the cloned window's layer stack (screen) space as the raw coordinate space for input going to clones"
+ bug: "377846505"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "deprecate_uiautomation_input_injection"
+ namespace: "input"
+ description: "Deprecate UiAutomation#injectInputEvent and UiAutomation#injectInputEventToInputFilter test/hidden APIs"
+ bug: "277261245"
+}
+
+flag {
+ name: "prevent_merging_input_pointer_devices"
+ namespace: "desktop_input"
+ description: "Prevent merging input sub-devices that provide pointer input streams"
+ bug: "389689566"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/libs/input/rust/Android.bp b/libs/input/rust/Android.bp
index 63853f7..fae9074 100644
--- a/libs/input/rust/Android.bp
+++ b/libs/input/rust/Android.bp
@@ -18,12 +18,12 @@
srcs: ["lib.rs"],
host_supported: true,
rustlibs: [
+ "inputconstants-rust",
"libbitflags",
"libcxx",
"libinput_bindgen",
- "liblogger",
"liblog_rust",
- "inputconstants-rust",
+ "liblogger",
"libserde",
"libserde_json",
],
diff --git a/libs/input/rust/data_store.rs b/libs/input/rust/data_store.rs
index 6bdcefd..beb6e23 100644
--- a/libs/input/rust/data_store.rs
+++ b/libs/input/rust/data_store.rs
@@ -17,7 +17,7 @@
//! Contains the DataStore, used to store input related data in a persistent way.
use crate::input::KeyboardType;
-use log::{debug, error};
+use log::{debug, error, info};
use serde::{Deserialize, Serialize};
use std::fs::File;
use std::io::{Read, Write};
@@ -157,7 +157,7 @@
let path = Path::new(&self.filepath);
let mut fs_string = String::new();
match File::open(path) {
- Err(e) => error!("couldn't open {:?}: {}", path, e),
+ Err(e) => info!("couldn't open {:?}: {}", path, e),
Ok(mut file) => match file.read_to_string(&mut fs_string) {
Err(e) => error!("Couldn't read from {:?}: {}", path, e),
Ok(_) => debug!("Successfully read from file {:?}", path),
diff --git a/libs/input/rust/input.rs b/libs/input/rust/input.rs
index 90f509d..35ba04f 100644
--- a/libs/input/rust/input.rs
+++ b/libs/input/rust/input.rs
@@ -50,7 +50,7 @@
bitflags! {
/// Source of the input device or input events.
- #[derive(Debug, PartialEq)]
+ #[derive(Clone, Copy, Debug, PartialEq)]
pub struct Source: u32 {
// Constants from SourceClass, added here for compatibility reasons
/// SourceClass::Button
@@ -101,6 +101,7 @@
/// A rust enum representation of a MotionEvent action.
#[repr(u32)]
+#[derive(Clone, Copy, Eq, PartialEq)]
pub enum MotionAction {
/// ACTION_DOWN
Down = input_bindgen::AMOTION_EVENT_ACTION_DOWN,
@@ -131,9 +132,15 @@
/// ACTION_SCROLL
Scroll = input_bindgen::AMOTION_EVENT_ACTION_SCROLL,
/// ACTION_BUTTON_PRESS
- ButtonPress = input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS,
+ ButtonPress {
+ /// The button being pressed.
+ action_button: MotionButton,
+ } = input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS,
/// ACTION_BUTTON_RELEASE
- ButtonRelease = input_bindgen::AMOTION_EVENT_ACTION_BUTTON_RELEASE,
+ ButtonRelease {
+ /// The button being released.
+ action_button: MotionButton,
+ } = input_bindgen::AMOTION_EVENT_ACTION_BUTTON_RELEASE,
}
impl fmt::Display for MotionAction {
@@ -152,14 +159,20 @@
MotionAction::Scroll => write!(f, "SCROLL"),
MotionAction::HoverEnter => write!(f, "HOVER_ENTER"),
MotionAction::HoverExit => write!(f, "HOVER_EXIT"),
- MotionAction::ButtonPress => write!(f, "BUTTON_PRESS"),
- MotionAction::ButtonRelease => write!(f, "BUTTON_RELEASE"),
+ MotionAction::ButtonPress { action_button } => {
+ write!(f, "BUTTON_PRESS({action_button:?})")
+ }
+ MotionAction::ButtonRelease { action_button } => {
+ write!(f, "BUTTON_RELEASE({action_button:?})")
+ }
}
}
}
-impl From<u32> for MotionAction {
- fn from(action: u32) -> Self {
+impl MotionAction {
+ /// Creates a [`MotionAction`] from an `AMOTION_EVENT_ACTION_…` constant and an action button
+ /// (which should be empty for all actions except `BUTTON_PRESS` and `…_RELEASE`).
+ pub fn from_code(action: u32, action_button: MotionButton) -> Self {
let (action_masked, action_index) = MotionAction::breakdown_action(action);
match action_masked {
input_bindgen::AMOTION_EVENT_ACTION_DOWN => MotionAction::Down,
@@ -177,14 +190,16 @@
input_bindgen::AMOTION_EVENT_ACTION_HOVER_MOVE => MotionAction::HoverMove,
input_bindgen::AMOTION_EVENT_ACTION_HOVER_EXIT => MotionAction::HoverExit,
input_bindgen::AMOTION_EVENT_ACTION_SCROLL => MotionAction::Scroll,
- input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS => MotionAction::ButtonPress,
- input_bindgen::AMOTION_EVENT_ACTION_BUTTON_RELEASE => MotionAction::ButtonRelease,
+ input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS => {
+ MotionAction::ButtonPress { action_button }
+ }
+ input_bindgen::AMOTION_EVENT_ACTION_BUTTON_RELEASE => {
+ MotionAction::ButtonRelease { action_button }
+ }
_ => panic!("Unknown action: {}", action),
}
}
-}
-impl MotionAction {
fn breakdown_action(action: u32) -> (u32, usize) {
let action_masked = action & input_bindgen::AMOTION_EVENT_ACTION_MASK;
let index = (action & input_bindgen::AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
@@ -194,10 +209,31 @@
}
bitflags! {
+ /// MotionEvent buttons.
+ #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
+ pub struct MotionButton: u32 {
+ /// Primary button (e.g. the left mouse button)
+ const Primary = input_bindgen::AMOTION_EVENT_BUTTON_PRIMARY;
+ /// Secondary button (e.g. the right mouse button)
+ const Secondary = input_bindgen::AMOTION_EVENT_BUTTON_SECONDARY;
+ /// Tertiary button (e.g. the middle mouse button)
+ const Tertiary = input_bindgen::AMOTION_EVENT_BUTTON_TERTIARY;
+ /// Back button
+ const Back = input_bindgen::AMOTION_EVENT_BUTTON_BACK;
+ /// Forward button
+ const Forward = input_bindgen::AMOTION_EVENT_BUTTON_FORWARD;
+ /// Primary stylus button
+ const StylusPrimary = input_bindgen::AMOTION_EVENT_BUTTON_STYLUS_PRIMARY;
+ /// Secondary stylus button
+ const StylusSecondary = input_bindgen::AMOTION_EVENT_BUTTON_STYLUS_SECONDARY;
+ }
+}
+
+bitflags! {
/// MotionEvent flags.
/// The source of truth for the flag definitions are the MotionEventFlag AIDL enum.
/// The flag values are redefined here as a bitflags API.
- #[derive(Debug)]
+ #[derive(Clone, Copy, Debug)]
pub struct MotionFlags: u32 {
/// FLAG_WINDOW_IS_OBSCURED
const WINDOW_IS_OBSCURED = MotionEventFlag::WINDOW_IS_OBSCURED.0 as u32;
@@ -219,6 +255,9 @@
MotionEventFlag::PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION.0 as u32;
/// FLAG_IS_ACCESSIBILITY_EVENT
const IS_ACCESSIBILITY_EVENT = MotionEventFlag::IS_ACCESSIBILITY_EVENT.0 as u32;
+ /// FLAG_INJECTED_FROM_ACCESSIBILITY_TOOL
+ const INJECTED_FROM_ACCESSIBILITY_TOOL =
+ MotionEventFlag::INJECTED_FROM_ACCESSIBILITY_TOOL.0 as u32;
/// FLAG_TAINTED
const TAINTED = MotionEventFlag::TAINTED.0 as u32;
/// FLAG_TARGET_ACCESSIBILITY_FOCUS
diff --git a/libs/input/rust/input_verifier.rs b/libs/input/rust/input_verifier.rs
index b1d7760..f87dd41 100644
--- a/libs/input/rust/input_verifier.rs
+++ b/libs/input/rust/input_verifier.rs
@@ -17,21 +17,55 @@
//! Contains the InputVerifier, used to validate a stream of input events.
use crate::ffi::RustPointerProperties;
-use crate::input::{DeviceId, MotionAction, MotionFlags, Source, SourceClass};
+use crate::input::{DeviceId, MotionAction, MotionButton, MotionFlags, Source, SourceClass};
use log::info;
use std::collections::HashMap;
use std::collections::HashSet;
-fn verify_event(
- action: MotionAction,
- pointer_properties: &[RustPointerProperties],
- flags: &MotionFlags,
-) -> Result<(), String> {
- let pointer_count = pointer_properties.len();
+/// Represents a movement or state change event from a pointer device. The Rust equivalent of the
+/// C++ NotifyMotionArgs struct.
+#[derive(Clone, Copy)]
+pub struct NotifyMotionArgs<'a> {
+ /// The ID of the device that emitted the event.
+ pub device_id: DeviceId,
+
+ /// The type of device that emitted the event.
+ pub source: Source,
+
+ /// The type of event that took place.
+ pub action: MotionAction,
+
+ /// The properties of each of the pointers involved in the event.
+ pub pointer_properties: &'a [RustPointerProperties],
+
+ /// Flags applied to the event.
+ pub flags: MotionFlags,
+
+ /// The set of buttons that were pressed at the time of the event.
+ ///
+ /// We allow DOWN events to include buttons in their state for which BUTTON_PRESS events haven't
+ /// been sent yet. In that case, the DOWN should be immediately followed by BUTTON_PRESS events
+ /// for those buttons, building up to a button state matching that of the DOWN. For example, if
+ /// the user presses the primary and secondary buttons at exactly the same time, we'd expect
+ /// this sequence:
+ ///
+ /// | Action | Action button | Button state |
+ /// |----------------|---------------|------------------------|
+ /// | `HOVER_EXIT` | - | - |
+ /// | `DOWN` | - | `PRIMARY`, `SECONDARY` |
+ /// | `BUTTON_PRESS` | `PRIMARY` | `PRIMARY` |
+ /// | `BUTTON_PRESS` | `SECONDARY` | `PRIMARY`, `SECONDARY` |
+ /// | `MOVE` | - | `PRIMARY`, `SECONDARY` |
+ pub button_state: MotionButton,
+}
+
+/// Verifies the properties of an event that should always be true, regardless of the current state.
+fn verify_event(event: NotifyMotionArgs<'_>, verify_buttons: bool) -> Result<(), String> {
+ let pointer_count = event.pointer_properties.len();
if pointer_count < 1 {
- return Err(format!("Invalid {} event: no pointers", action));
+ return Err(format!("Invalid {} event: no pointers", event.action));
}
- match action {
+ match event.action {
MotionAction::Down
| MotionAction::HoverEnter
| MotionAction::HoverExit
@@ -40,23 +74,40 @@
if pointer_count != 1 {
return Err(format!(
"Invalid {} event: there are {} pointers in the event",
- action, pointer_count
+ event.action, pointer_count
));
}
}
MotionAction::Cancel => {
- if !flags.contains(MotionFlags::CANCELED) {
+ if !event.flags.contains(MotionFlags::CANCELED) {
return Err(format!(
"For ACTION_CANCEL, must set FLAG_CANCELED. Received flags: {:#?}",
- flags
+ event.flags
));
}
}
MotionAction::PointerDown { action_index } | MotionAction::PointerUp { action_index } => {
if action_index >= pointer_count {
- return Err(format!("Got {}, but event has {} pointer(s)", action, pointer_count));
+ return Err(format!(
+ "Got {}, but event has {} pointer(s)",
+ event.action, pointer_count
+ ));
+ }
+ }
+
+ MotionAction::ButtonPress { action_button }
+ | MotionAction::ButtonRelease { action_button } => {
+ if verify_buttons {
+ let button_count = action_button.iter().count();
+ if button_count != 1 {
+ return Err(format!(
+ "Invalid {} event: must specify a single action button, not {} action \
+ buttons",
+ event.action, button_count
+ ));
+ }
}
}
@@ -65,17 +116,94 @@
Ok(())
}
+/// Keeps track of the button state for a single device and verifies events against it.
+#[derive(Default)]
+struct ButtonVerifier {
+ /// The current button state of the device.
+ button_state: MotionButton,
+
+ /// The set of "pending buttons", which were seen in the last DOWN event's button state but
+ /// for which we haven't seen BUTTON_PRESS events yet (see [`NotifyMotionArgs::button_state`]).
+ pending_buttons: MotionButton,
+}
+
+impl ButtonVerifier {
+ pub fn process_event(&mut self, event: NotifyMotionArgs<'_>) -> Result<(), String> {
+ if !self.pending_buttons.is_empty() {
+ // We just saw a DOWN with some additional buttons in its state, so it should be
+ // immediately followed by ButtonPress events for those buttons.
+ match event.action {
+ MotionAction::ButtonPress { action_button }
+ if self.pending_buttons.contains(action_button) =>
+ {
+ self.pending_buttons -= action_button;
+ }
+ _ => {
+ return Err(format!(
+ "After DOWN event, expected BUTTON_PRESS event(s) for {:?}, but got {}",
+ self.pending_buttons, event.action
+ ));
+ }
+ }
+ }
+ let expected_state = match event.action {
+ MotionAction::Down => {
+ if self.button_state - event.button_state != MotionButton::empty() {
+ return Err(format!(
+ "DOWN event button state is missing {:?}",
+ self.button_state - event.button_state
+ ));
+ }
+ self.pending_buttons = event.button_state - self.button_state;
+ // We've already checked that the state isn't missing any already-down buttons, and
+ // extra buttons are valid on DOWN actions, so bypass the expected state check.
+ event.button_state
+ }
+ MotionAction::ButtonPress { action_button } => {
+ if self.button_state.contains(action_button) {
+ return Err(format!(
+ "Duplicate BUTTON_PRESS; button state already contains {action_button:?}"
+ ));
+ }
+ self.button_state | action_button
+ }
+ MotionAction::ButtonRelease { action_button } => {
+ if !self.button_state.contains(action_button) {
+ return Err(format!(
+ "Invalid BUTTON_RELEASE; button state doesn't contain {action_button:?}",
+ ));
+ }
+ self.button_state - action_button
+ }
+ _ => self.button_state,
+ };
+ if event.button_state != expected_state {
+ return Err(format!(
+ "Expected {} button state to be {:?}, but was {:?}",
+ event.action, expected_state, event.button_state
+ ));
+ }
+ // DOWN events can have pending buttons, so don't update the state for them.
+ if event.action != MotionAction::Down {
+ self.button_state = event.button_state;
+ }
+ Ok(())
+ }
+}
+
/// The InputVerifier is used to validate a stream of input events.
pub struct InputVerifier {
name: String,
should_log: bool,
+ verify_buttons: bool,
touching_pointer_ids_by_device: HashMap<DeviceId, HashSet<i32>>,
hovering_pointer_ids_by_device: HashMap<DeviceId, HashSet<i32>>,
+ button_verifier_by_device: HashMap<DeviceId, ButtonVerifier>,
}
impl InputVerifier {
/// Create a new InputVerifier.
- pub fn new(name: &str, should_log: bool) -> Self {
+ pub fn new(name: &str, should_log: bool, verify_buttons: bool) -> Self {
logger::init(
logger::Config::default()
.with_tag_on_device("InputVerifier")
@@ -84,68 +212,70 @@
Self {
name: name.to_owned(),
should_log,
+ verify_buttons,
touching_pointer_ids_by_device: HashMap::new(),
hovering_pointer_ids_by_device: HashMap::new(),
+ button_verifier_by_device: HashMap::new(),
}
}
/// Process a pointer movement event from an InputDevice.
/// If the event is not valid, we return an error string that describes the issue.
- pub fn process_movement(
- &mut self,
- device_id: DeviceId,
- source: Source,
- action: u32,
- pointer_properties: &[RustPointerProperties],
- flags: MotionFlags,
- ) -> Result<(), String> {
- if !source.is_from_class(SourceClass::Pointer) {
+ pub fn process_movement(&mut self, event: NotifyMotionArgs<'_>) -> Result<(), String> {
+ if !event.source.is_from_class(SourceClass::Pointer) {
// Skip non-pointer sources like MOUSE_RELATIVE for now
return Ok(());
}
if self.should_log {
info!(
"Processing {} for device {:?} ({} pointer{}) on {}",
- MotionAction::from(action).to_string(),
- device_id,
- pointer_properties.len(),
- if pointer_properties.len() == 1 { "" } else { "s" },
+ event.action,
+ event.device_id,
+ event.pointer_properties.len(),
+ if event.pointer_properties.len() == 1 { "" } else { "s" },
self.name
);
}
- verify_event(action.into(), pointer_properties, &flags)?;
+ verify_event(event, self.verify_buttons)?;
- match action.into() {
+ if self.verify_buttons {
+ self.button_verifier_by_device
+ .entry(event.device_id)
+ .or_default()
+ .process_event(event)?;
+ }
+
+ match event.action {
MotionAction::Down => {
- if self.touching_pointer_ids_by_device.contains_key(&device_id) {
+ if self.touching_pointer_ids_by_device.contains_key(&event.device_id) {
return Err(format!(
"{}: Invalid DOWN event - pointers already down for device {:?}: {:?}",
- self.name, device_id, self.touching_pointer_ids_by_device
+ self.name, event.device_id, self.touching_pointer_ids_by_device
));
}
- let it = self.touching_pointer_ids_by_device.entry(device_id).or_default();
- it.insert(pointer_properties[0].id);
+ let it = self.touching_pointer_ids_by_device.entry(event.device_id).or_default();
+ it.insert(event.pointer_properties[0].id);
}
MotionAction::PointerDown { action_index } => {
- if !self.touching_pointer_ids_by_device.contains_key(&device_id) {
+ if !self.touching_pointer_ids_by_device.contains_key(&event.device_id) {
return Err(format!(
"{}: Received POINTER_DOWN but no pointers are currently down \
for device {:?}",
- self.name, device_id
+ self.name, event.device_id
));
}
- let it = self.touching_pointer_ids_by_device.get_mut(&device_id).unwrap();
- if it.len() != pointer_properties.len() - 1 {
+ let it = self.touching_pointer_ids_by_device.get_mut(&event.device_id).unwrap();
+ if it.len() != event.pointer_properties.len() - 1 {
return Err(format!(
"{}: There are currently {} touching pointers, but the incoming \
POINTER_DOWN event has {}",
self.name,
it.len(),
- pointer_properties.len()
+ event.pointer_properties.len()
));
}
- let pointer_id = pointer_properties[action_index].id;
+ let pointer_id = event.pointer_properties[action_index].id;
if it.contains(&pointer_id) {
return Err(format!(
"{}: Pointer with id={} already present found in the properties",
@@ -155,7 +285,7 @@
it.insert(pointer_id);
}
MotionAction::Move => {
- if !self.ensure_touching_pointers_match(device_id, pointer_properties) {
+ if !self.ensure_touching_pointers_match(event.device_id, event.pointer_properties) {
return Err(format!(
"{}: ACTION_MOVE touching pointers don't match",
self.name
@@ -163,49 +293,49 @@
}
}
MotionAction::PointerUp { action_index } => {
- if !self.ensure_touching_pointers_match(device_id, pointer_properties) {
+ if !self.ensure_touching_pointers_match(event.device_id, event.pointer_properties) {
return Err(format!(
"{}: ACTION_POINTER_UP touching pointers don't match",
self.name
));
}
- let it = self.touching_pointer_ids_by_device.get_mut(&device_id).unwrap();
- let pointer_id = pointer_properties[action_index].id;
+ let it = self.touching_pointer_ids_by_device.get_mut(&event.device_id).unwrap();
+ let pointer_id = event.pointer_properties[action_index].id;
it.remove(&pointer_id);
}
MotionAction::Up => {
- if !self.touching_pointer_ids_by_device.contains_key(&device_id) {
+ if !self.touching_pointer_ids_by_device.contains_key(&event.device_id) {
return Err(format!(
"{} Received ACTION_UP but no pointers are currently down for device {:?}",
- self.name, device_id
+ self.name, event.device_id
));
}
- let it = self.touching_pointer_ids_by_device.get_mut(&device_id).unwrap();
+ let it = self.touching_pointer_ids_by_device.get_mut(&event.device_id).unwrap();
if it.len() != 1 {
return Err(format!(
"{}: Got ACTION_UP, but we have pointers: {:?} for device {:?}",
- self.name, it, device_id
+ self.name, it, event.device_id
));
}
- let pointer_id = pointer_properties[0].id;
+ let pointer_id = event.pointer_properties[0].id;
if !it.contains(&pointer_id) {
return Err(format!(
"{}: Got ACTION_UP, but pointerId {} is not touching. Touching pointers:\
{:?} for device {:?}",
- self.name, pointer_id, it, device_id
+ self.name, pointer_id, it, event.device_id
));
}
- self.touching_pointer_ids_by_device.remove(&device_id);
+ self.touching_pointer_ids_by_device.remove(&event.device_id);
}
MotionAction::Cancel => {
- if !self.ensure_touching_pointers_match(device_id, pointer_properties) {
+ if !self.ensure_touching_pointers_match(event.device_id, event.pointer_properties) {
return Err(format!(
"{}: Got ACTION_CANCEL, but the pointers don't match. \
Existing pointers: {:?}",
self.name, self.touching_pointer_ids_by_device
));
}
- self.touching_pointer_ids_by_device.remove(&device_id);
+ self.touching_pointer_ids_by_device.remove(&event.device_id);
}
/*
* The hovering protocol currently supports a single pointer only, because we do not
@@ -214,41 +344,41 @@
* eventually supported.
*/
MotionAction::HoverEnter => {
- if self.hovering_pointer_ids_by_device.contains_key(&device_id) {
+ if self.hovering_pointer_ids_by_device.contains_key(&event.device_id) {
return Err(format!(
"{}: Invalid HOVER_ENTER event - pointers already hovering for device {:?}:\
{:?}",
- self.name, device_id, self.hovering_pointer_ids_by_device
+ self.name, event.device_id, self.hovering_pointer_ids_by_device
));
}
- let it = self.hovering_pointer_ids_by_device.entry(device_id).or_default();
- it.insert(pointer_properties[0].id);
+ let it = self.hovering_pointer_ids_by_device.entry(event.device_id).or_default();
+ it.insert(event.pointer_properties[0].id);
}
MotionAction::HoverMove => {
// For compatibility reasons, we allow HOVER_MOVE without a prior HOVER_ENTER.
// If there was no prior HOVER_ENTER, just start a new hovering pointer.
- let it = self.hovering_pointer_ids_by_device.entry(device_id).or_default();
- it.insert(pointer_properties[0].id);
+ let it = self.hovering_pointer_ids_by_device.entry(event.device_id).or_default();
+ it.insert(event.pointer_properties[0].id);
}
MotionAction::HoverExit => {
- if !self.hovering_pointer_ids_by_device.contains_key(&device_id) {
+ if !self.hovering_pointer_ids_by_device.contains_key(&event.device_id) {
return Err(format!(
"{}: Invalid HOVER_EXIT event - no pointers are hovering for device {:?}",
- self.name, device_id
+ self.name, event.device_id
));
}
- let pointer_id = pointer_properties[0].id;
- let it = self.hovering_pointer_ids_by_device.get_mut(&device_id).unwrap();
+ let pointer_id = event.pointer_properties[0].id;
+ let it = self.hovering_pointer_ids_by_device.get_mut(&event.device_id).unwrap();
it.remove(&pointer_id);
if !it.is_empty() {
return Err(format!(
"{}: Removed hovering pointer {}, but pointers are still\
hovering for device {:?}: {:?}",
- self.name, pointer_id, device_id, it
+ self.name, pointer_id, event.device_id, it
));
}
- self.hovering_pointer_ids_by_device.remove(&device_id);
+ self.hovering_pointer_ids_by_device.remove(&event.device_id);
}
_ => return Ok(()),
}
@@ -288,295 +418,227 @@
#[cfg(test)]
mod tests {
+ use crate::input::MotionButton;
use crate::input_verifier::InputVerifier;
+ use crate::input_verifier::NotifyMotionArgs;
use crate::DeviceId;
+ use crate::MotionAction;
use crate::MotionFlags;
use crate::RustPointerProperties;
use crate::Source;
+ const BASE_POINTER_PROPERTIES: [RustPointerProperties; 1] = [RustPointerProperties { id: 0 }];
+ const BASE_EVENT: NotifyMotionArgs = NotifyMotionArgs {
+ device_id: DeviceId(1),
+ source: Source::Touchscreen,
+ action: MotionAction::Down,
+ pointer_properties: &BASE_POINTER_PROPERTIES,
+ flags: MotionFlags::empty(),
+ button_state: MotionButton::empty(),
+ };
+ const BASE_MOUSE_EVENT: NotifyMotionArgs =
+ NotifyMotionArgs { source: Source::Mouse, ..BASE_EVENT };
+
#[test]
/**
* Send a DOWN event with 2 pointers and ensure that it's marked as invalid.
*/
fn bad_down_event() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ true);
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ true, /*verify_buttons*/ true);
let pointer_properties =
Vec::from([RustPointerProperties { id: 0 }, RustPointerProperties { id: 1 }]);
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::Down,
+ pointer_properties: &pointer_properties,
+ ..BASE_EVENT
+ })
.is_err());
}
#[test]
fn single_pointer_stream() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::Down,
+ pointer_properties: &pointer_properties,
+ ..BASE_EVENT
+ })
.is_ok());
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_MOVE,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::Move,
+ pointer_properties: &pointer_properties,
+ ..BASE_EVENT
+ })
.is_ok());
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_UP,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::Up,
+ pointer_properties: &pointer_properties,
+ ..BASE_EVENT
+ })
.is_ok());
}
#[test]
fn two_pointer_stream() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::Down,
+ pointer_properties: &pointer_properties,
+ ..BASE_EVENT
+ })
.is_ok());
// POINTER 1 DOWN
let two_pointer_properties =
Vec::from([RustPointerProperties { id: 0 }, RustPointerProperties { id: 1 }]);
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_POINTER_DOWN
- | (1 << input_bindgen::AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- &two_pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::PointerDown { action_index: 1 },
+ pointer_properties: &two_pointer_properties,
+ ..BASE_EVENT
+ })
.is_ok());
// POINTER 0 UP
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_POINTER_UP
- | (0 << input_bindgen::AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- &two_pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::PointerUp { action_index: 0 },
+ pointer_properties: &two_pointer_properties,
+ ..BASE_EVENT
+ })
.is_ok());
// ACTION_UP for pointer id=1
let pointer_1_properties = Vec::from([RustPointerProperties { id: 1 }]);
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_UP,
- &pointer_1_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::Up,
+ pointer_properties: &pointer_1_properties,
+ ..BASE_EVENT
+ })
.is_ok());
}
#[test]
fn multi_device_stream() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs {
+ device_id: DeviceId(1),
+ action: MotionAction::Down,
+ ..BASE_EVENT
+ })
.is_ok());
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_MOVE,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs {
+ device_id: DeviceId(1),
+ action: MotionAction::Move,
+ ..BASE_EVENT
+ })
.is_ok());
assert!(verifier
- .process_movement(
- DeviceId(2),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs {
+ device_id: DeviceId(2),
+ action: MotionAction::Down,
+ ..BASE_EVENT
+ })
.is_ok());
assert!(verifier
- .process_movement(
- DeviceId(2),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_MOVE,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs {
+ device_id: DeviceId(2),
+ action: MotionAction::Move,
+ ..BASE_EVENT
+ })
.is_ok());
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_UP,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs {
+ device_id: DeviceId(1),
+ action: MotionAction::Up,
+ ..BASE_EVENT
+ })
.is_ok());
}
#[test]
fn action_cancel() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::Down,
+ flags: MotionFlags::empty(),
+ ..BASE_EVENT
+ })
.is_ok());
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_CANCEL,
- &pointer_properties,
- MotionFlags::CANCELED,
- )
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::Cancel,
+ flags: MotionFlags::CANCELED,
+ ..BASE_EVENT
+ })
.is_ok());
}
#[test]
fn invalid_action_cancel() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs { action: MotionAction::Down, ..BASE_EVENT })
.is_ok());
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_CANCEL,
- &pointer_properties,
- MotionFlags::empty(), // forgot to set FLAG_CANCELED
- )
+ .process_movement(NotifyMotionArgs { action: MotionAction::Cancel, ..BASE_EVENT })
.is_err());
}
#[test]
fn invalid_up() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_UP,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs { action: MotionAction::Up, ..BASE_EVENT })
.is_err());
}
#[test]
fn correct_hover_sequence() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs { action: MotionAction::HoverEnter, ..BASE_EVENT })
.is_ok());
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_HOVER_MOVE,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs { action: MotionAction::HoverMove, ..BASE_EVENT })
.is_ok());
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_HOVER_EXIT,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs { action: MotionAction::HoverExit, ..BASE_EVENT })
.is_ok());
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs { action: MotionAction::HoverEnter, ..BASE_EVENT })
.is_ok());
}
#[test]
fn double_hover_enter() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs { action: MotionAction::HoverEnter, ..BASE_EVENT })
.is_ok());
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs { action: MotionAction::HoverEnter, ..BASE_EVENT })
.is_err());
}
@@ -584,55 +646,356 @@
// MOUSE_RELATIVE, which is used during pointer capture. The verifier should allow such event.
#[test]
fn relative_mouse_move() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
assert!(verifier
- .process_movement(
- DeviceId(2),
- Source::MouseRelative,
- input_bindgen::AMOTION_EVENT_ACTION_MOVE,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs {
+ device_id: DeviceId(2),
+ source: Source::MouseRelative,
+ action: MotionAction::Move,
+ ..BASE_EVENT
+ })
.is_ok());
}
// Send a MOVE event with incorrect number of pointers (one of the pointers is missing).
#[test]
fn move_with_wrong_number_of_pointers() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::Down,
+ pointer_properties: &pointer_properties,
+ ..BASE_EVENT
+ })
.is_ok());
// POINTER 1 DOWN
let two_pointer_properties =
Vec::from([RustPointerProperties { id: 0 }, RustPointerProperties { id: 1 }]);
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_POINTER_DOWN
- | (1 << input_bindgen::AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- &two_pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::PointerDown { action_index: 1 },
+ pointer_properties: &two_pointer_properties,
+ ..BASE_EVENT
+ })
.is_ok());
// MOVE event with 1 pointer missing (the pointer with id = 1). It should be rejected
assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Touchscreen,
- input_bindgen::AMOTION_EVENT_ACTION_MOVE,
- &pointer_properties,
- MotionFlags::empty(),
- )
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::Move,
+ pointer_properties: &pointer_properties,
+ ..BASE_EVENT
+ })
+ .is_err());
+ }
+
+ #[test]
+ fn correct_button_press() {
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::ButtonPress { action_button: MotionButton::Primary },
+ button_state: MotionButton::Primary,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_ok());
+ }
+
+ #[test]
+ fn button_press_without_action_button() {
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::ButtonPress { action_button: MotionButton::empty() },
+ button_state: MotionButton::empty(),
+ ..BASE_MOUSE_EVENT
+ })
+ .is_err());
+ }
+
+ #[test]
+ fn button_press_with_multiple_action_buttons() {
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::ButtonPress {
+ action_button: MotionButton::Back | MotionButton::Forward
+ },
+ button_state: MotionButton::Back | MotionButton::Forward,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_err());
+ }
+
+ #[test]
+ fn button_press_without_action_button_in_state() {
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::ButtonPress { action_button: MotionButton::Primary },
+ button_state: MotionButton::empty(),
+ ..BASE_MOUSE_EVENT
+ })
+ .is_err());
+ }
+
+ #[test]
+ fn button_release_with_action_button_in_state() {
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::ButtonPress { action_button: MotionButton::Primary },
+ button_state: MotionButton::Primary,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_ok());
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::ButtonRelease { action_button: MotionButton::Primary },
+ button_state: MotionButton::Primary,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_err());
+ }
+
+ #[test]
+ fn nonbutton_action_with_button_state_change() {
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::HoverEnter,
+ button_state: MotionButton::empty(),
+ ..BASE_MOUSE_EVENT
+ })
+ .is_ok());
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::HoverMove,
+ button_state: MotionButton::Back,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_err());
+ }
+
+ #[test]
+ fn nonbutton_action_missing_button_state() {
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::HoverEnter,
+ button_state: MotionButton::empty(),
+ ..BASE_MOUSE_EVENT
+ })
+ .is_ok());
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::ButtonPress { action_button: MotionButton::Back },
+ button_state: MotionButton::Back,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_ok());
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::HoverMove,
+ button_state: MotionButton::empty(),
+ ..BASE_MOUSE_EVENT
+ })
+ .is_err());
+ }
+
+ #[test]
+ fn up_without_button_release() {
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::Down,
+ button_state: MotionButton::Primary,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_ok());
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::ButtonPress { action_button: MotionButton::Primary },
+ button_state: MotionButton::Primary,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_ok());
+ // This UP event shouldn't change the button state; a BUTTON_RELEASE before it should.
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::Up,
+ button_state: MotionButton::empty(),
+ ..BASE_MOUSE_EVENT
+ })
+ .is_err());
+ }
+
+ #[test]
+ fn button_press_for_already_pressed_button() {
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::ButtonPress { action_button: MotionButton::Back },
+ button_state: MotionButton::Back,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_ok());
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::ButtonPress { action_button: MotionButton::Back },
+ button_state: MotionButton::Back,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_err());
+ }
+
+ #[test]
+ fn button_release_for_unpressed_button() {
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::ButtonRelease { action_button: MotionButton::Back },
+ button_state: MotionButton::empty(),
+ ..BASE_MOUSE_EVENT
+ })
+ .is_err());
+ }
+
+ #[test]
+ fn correct_multiple_button_presses_without_down() {
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::ButtonPress { action_button: MotionButton::Back },
+ button_state: MotionButton::Back,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_ok());
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::ButtonPress { action_button: MotionButton::Forward },
+ button_state: MotionButton::Back | MotionButton::Forward,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_ok());
+ }
+
+ #[test]
+ fn correct_down_with_button_press() {
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::Down,
+ button_state: MotionButton::Primary | MotionButton::Secondary,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_ok());
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::ButtonPress { action_button: MotionButton::Primary },
+ button_state: MotionButton::Primary,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_ok());
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::ButtonPress { action_button: MotionButton::Secondary },
+ button_state: MotionButton::Primary | MotionButton::Secondary,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_ok());
+ // Also check that the MOVE afterwards is OK, as that's where errors would be raised if not
+ // enough BUTTON_PRESSes were sent.
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::Move,
+ button_state: MotionButton::Primary | MotionButton::Secondary,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_ok());
+ }
+
+ #[test]
+ fn down_with_button_state_change_not_followed_by_button_press() {
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::Down,
+ button_state: MotionButton::Primary,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_ok());
+ // The DOWN event itself is OK, but it needs to be immediately followed by a BUTTON_PRESS.
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::Move,
+ button_state: MotionButton::Primary,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_err());
+ }
+
+ #[test]
+ fn down_with_button_state_change_not_followed_by_enough_button_presses() {
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::Down,
+ button_state: MotionButton::Primary | MotionButton::Secondary,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_ok());
+ // The DOWN event itself is OK, but it needs to be immediately followed by two
+ // BUTTON_PRESSes, one for each button.
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::ButtonPress { action_button: MotionButton::Primary },
+ button_state: MotionButton::Primary,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_ok());
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::Move,
+ button_state: MotionButton::Primary,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_err());
+ }
+
+ #[test]
+ fn down_missing_already_pressed_button() {
+ let mut verifier =
+ InputVerifier::new("Test", /*should_log*/ false, /*verify_buttons*/ true);
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::ButtonPress { action_button: MotionButton::Back },
+ button_state: MotionButton::Back,
+ ..BASE_MOUSE_EVENT
+ })
+ .is_ok());
+ assert!(verifier
+ .process_movement(NotifyMotionArgs {
+ action: MotionAction::Down,
+ button_state: MotionButton::empty(),
+ ..BASE_MOUSE_EVENT
+ })
.is_err());
}
}
diff --git a/libs/input/rust/keyboard_classification_config.rs b/libs/input/rust/keyboard_classification_config.rs
index ab74efb..26a8d8f 100644
--- a/libs/input/rust/keyboard_classification_config.rs
+++ b/libs/input/rust/keyboard_classification_config.rs
@@ -20,6 +20,15 @@
// key events at all. (Requires setup allowing InputDevice to dynamically add/remove
// KeyboardInputMapper based on blocklist and KeyEvents in case a KeyboardType::None device ends
// up producing a key event)
+
+/// This list pre-classifies a device into Alphabetic/Non-Alphabetic keyboard and tells us whether
+/// further re-classification should be allowed or not (using is_finalized value).
+/// This list DOES NOT change the source of the device or change the input mappers associated with
+/// the device. It only changes the "KeyboardType" classification. This list should be primarily
+/// used to pre-classify devices that are NOT keyboards(like mice, game pads, etc.) but generate
+/// evdev nodes that say that they are alphabetic keyboards.
+///
+/// NOTE: Pls keep the list sorted by vendor id and product id for easy searching.
pub static CLASSIFIED_DEVICES: &[(
/* vendorId */ u16,
/* productId */ u16,
@@ -96,6 +105,8 @@
(0x056e, 0x0159, KeyboardType::NonAlphabetic, true),
// Zebra LS2208 barcode scanner
(0x05e0, 0x1200, KeyboardType::NonAlphabetic, true),
+ // Glorious O2 Wireless
+ (0x093a, 0x822d, KeyboardType::NonAlphabetic, true),
// RDing FootSwitch1F1
(0x0c45, 0x7403, KeyboardType::NonAlphabetic, true),
// SteelSeries Sensei RAW Frost Blue
@@ -108,6 +119,8 @@
(0x1050, 0x0010, KeyboardType::NonAlphabetic, true),
// Yubico.com Yubikey 4 OTP+U2F+CCID
(0x1050, 0x0407, KeyboardType::NonAlphabetic, true),
+ // Razer DeathAdder Essential
+ (0x1532, 0x0098, KeyboardType::NonAlphabetic, true),
// Lenovo USB-C Wired Compact Mouse
(0x17ef, 0x6123, KeyboardType::NonAlphabetic, true),
// Corsair Katar Pro Wireless (USB dongle)
diff --git a/libs/input/rust/keyboard_classifier.rs b/libs/input/rust/keyboard_classifier.rs
index 3c789b4..1b89a5c 100644
--- a/libs/input/rust/keyboard_classifier.rs
+++ b/libs/input/rust/keyboard_classifier.rs
@@ -66,11 +66,11 @@
/// Get keyboard type for a tracked keyboard in KeyboardClassifier
pub fn get_keyboard_type(&self, device_id: DeviceId) -> KeyboardType {
- return if let Some(keyboard) = self.device_map.get(&device_id) {
+ if let Some(keyboard) = self.device_map.get(&device_id) {
keyboard.keyboard_type
} else {
KeyboardType::None
- };
+ }
}
/// Tells if keyboard type classification is finalized. Once finalized the classification can't
@@ -79,11 +79,11 @@
/// Finalized devices are either "alphabetic" keyboards or keyboards in blocklist or
/// allowlist that are explicitly categorized and won't change with future key events
pub fn is_finalized(&self, device_id: DeviceId) -> bool {
- return if let Some(keyboard) = self.device_map.get(&device_id) {
+ if let Some(keyboard) = self.device_map.get(&device_id) {
keyboard.is_finalized
} else {
false
- };
+ }
}
/// Process a key event and change keyboard type if required.
diff --git a/libs/input/rust/lib.rs b/libs/input/rust/lib.rs
index 4f4ea85..ee999f7 100644
--- a/libs/input/rust/lib.rs
+++ b/libs/input/rust/lib.rs
@@ -24,10 +24,10 @@
pub use data_store::{DataStore, DefaultFileReaderWriter};
pub use input::{
- DeviceClass, DeviceId, InputDevice, KeyboardType, ModifierState, MotionAction, MotionFlags,
- Source,
+ DeviceClass, DeviceId, InputDevice, KeyboardType, ModifierState, MotionAction, MotionButton,
+ MotionFlags, Source,
};
-pub use input_verifier::InputVerifier;
+pub use input_verifier::{InputVerifier, NotifyMotionArgs};
pub use keyboard_classifier::KeyboardClassifier;
#[cxx::bridge(namespace = "android::input")]
@@ -57,14 +57,17 @@
/// ```
type InputVerifier;
#[cxx_name = create]
- fn create_input_verifier(name: String) -> Box<InputVerifier>;
+ fn create_input_verifier(name: String, verify_buttons: bool) -> Box<InputVerifier>;
+ #[allow(clippy::too_many_arguments)]
fn process_movement(
verifier: &mut InputVerifier,
device_id: i32,
source: u32,
action: u32,
+ action_button: u32,
pointer_properties: &[RustPointerProperties],
flags: u32,
+ button_state: u32,
) -> String;
fn reset_device(verifier: &mut InputVerifier, device_id: i32);
}
@@ -115,33 +118,67 @@
use crate::ffi::{RustInputDeviceIdentifier, RustPointerProperties};
-fn create_input_verifier(name: String) -> Box<InputVerifier> {
- Box::new(InputVerifier::new(&name, ffi::shouldLog("InputVerifierLogEvents")))
+fn create_input_verifier(name: String, verify_buttons: bool) -> Box<InputVerifier> {
+ Box::new(InputVerifier::new(&name, ffi::shouldLog("InputVerifierLogEvents"), verify_buttons))
}
+#[allow(clippy::too_many_arguments)]
fn process_movement(
verifier: &mut InputVerifier,
device_id: i32,
source: u32,
action: u32,
+ action_button: u32,
pointer_properties: &[RustPointerProperties],
flags: u32,
+ button_state: u32,
) -> String {
- let motion_flags = MotionFlags::from_bits(flags);
- if motion_flags.is_none() {
+ let Some(converted_source) = Source::from_bits(source) else {
+ panic!(
+ "The conversion of source 0x{source:08x} failed, please check if some sources have not \
+ been added to Source."
+ );
+ };
+ let Some(motion_flags) = MotionFlags::from_bits(flags) else {
panic!(
"The conversion of flags 0x{:08x} failed, please check if some flags have not been \
added to MotionFlags.",
flags
);
+ };
+ let Some(motion_action_button) = MotionButton::from_bits(action_button) else {
+ panic!(
+ "The conversion of action button 0x{action_button:08x} failed, please check if some \
+ buttons need to be added to MotionButton."
+ );
+ };
+ let Some(motion_button_state) = MotionButton::from_bits(button_state) else {
+ panic!(
+ "The conversion of button state 0x{button_state:08x} failed, please check if some \
+ buttons need to be added to MotionButton."
+ );
+ };
+ let motion_action = MotionAction::from_code(action, motion_action_button);
+ if motion_action_button != MotionButton::empty() {
+ match motion_action {
+ MotionAction::ButtonPress { action_button: _ }
+ | MotionAction::ButtonRelease { action_button: _ } => {}
+ _ => {
+ return format!(
+ "Invalid {motion_action} event: has action button {motion_action_button:?} but \
+ is not a button action"
+ );
+ }
+ }
}
- let result = verifier.process_movement(
- DeviceId(device_id),
- Source::from_bits(source).unwrap(),
- action,
+ let result = verifier.process_movement(NotifyMotionArgs {
+ device_id: DeviceId(device_id),
+ source: converted_source,
+ action: motion_action,
pointer_properties,
- motion_flags.unwrap(),
- );
+ flags: motion_flags,
+ button_state: motion_button_state,
+ });
match result {
Ok(()) => "".to_string(),
Err(e) => e,
@@ -208,3 +245,44 @@
}
classifier.process_key(DeviceId(device_id), evdev_code, modifier_state.unwrap());
}
+
+#[cfg(test)]
+mod tests {
+ use crate::create_input_verifier;
+ use crate::process_movement;
+ use crate::RustPointerProperties;
+
+ const BASE_POINTER_PROPERTIES: [RustPointerProperties; 1] = [RustPointerProperties { id: 0 }];
+
+ #[test]
+ fn verify_nonbutton_action_with_action_button() {
+ let mut verifier = create_input_verifier("Test".to_string(), /*verify_buttons*/ true);
+ assert!(process_movement(
+ &mut verifier,
+ 1,
+ input_bindgen::AINPUT_SOURCE_MOUSE,
+ input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
+ input_bindgen::AMOTION_EVENT_BUTTON_PRIMARY,
+ &BASE_POINTER_PROPERTIES,
+ 0,
+ 0,
+ )
+ .contains("button action"));
+ }
+
+ #[test]
+ fn verify_nonbutton_action_with_action_button_and_button_state() {
+ let mut verifier = create_input_verifier("Test".to_string(), /*verify_buttons*/ true);
+ assert!(process_movement(
+ &mut verifier,
+ 1,
+ input_bindgen::AINPUT_SOURCE_MOUSE,
+ input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
+ input_bindgen::AMOTION_EVENT_BUTTON_PRIMARY,
+ &BASE_POINTER_PROPERTIES,
+ 0,
+ input_bindgen::AMOTION_EVENT_BUTTON_PRIMARY,
+ )
+ .contains("button action"));
+ }
+}
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index 661c9f7..968fa5f 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -16,15 +16,17 @@
"BlockingQueue_test.cpp",
"IdGenerator_test.cpp",
"InputChannel_test.cpp",
- "InputConsumer_test.cpp",
+ "InputConsumerFilteredResampling_test.cpp",
"InputConsumerResampling_test.cpp",
+ "InputConsumer_test.cpp",
"InputDevice_test.cpp",
"InputEvent_test.cpp",
- "InputPublisherAndConsumer_test.cpp",
"InputPublisherAndConsumerNoResampling_test.cpp",
+ "InputPublisherAndConsumer_test.cpp",
"InputVerifier_test.cpp",
- "MotionPredictor_test.cpp",
"MotionPredictorMetricsManager_test.cpp",
+ "MotionPredictor_test.cpp",
+ "OneEuroFilter_test.cpp",
"Resampler_test.cpp",
"RingBuffer_test.cpp",
"TestInputChannel.cpp",
@@ -51,32 +53,41 @@
],
cflags: [
"-Wall",
- "-Wextra",
"-Werror",
+ "-Wextra",
"-Wno-unused-parameter",
],
sanitize: {
+ address: true,
hwaddress: true,
undefined: true,
all_undefined: true,
diag: {
+ cfi: true,
+ integer_overflow: true,
+ memtag_heap: true,
undefined: true,
+ misc_undefined: [
+ "all",
+ "bounds",
+ ],
},
},
shared_libs: [
+ "libPlatformProperties",
+ "libaconfig_storage_read_api_cc",
"libbase",
"libbinder",
"libcutils",
"liblog",
- "libPlatformProperties",
"libstatslog",
"libtinyxml2",
"libutils",
"server_configurable_flags",
],
data: [
- "data/*",
":motion_predictor_model",
+ "data/*",
],
test_options: {
unit_test: true,
@@ -89,11 +100,6 @@
"libstatssocket_lazy",
],
},
- host: {
- sanitize: {
- address: true,
- },
- },
},
native_coverage: false,
}
@@ -111,10 +117,10 @@
"-Wextra",
],
shared_libs: [
- "libinput",
- "libcutils",
- "libutils",
- "libbinder",
"libbase",
+ "libbinder",
+ "libcutils",
+ "libinput",
+ "libutils",
],
}
diff --git a/libs/input/tests/InputConsumerFilteredResampling_test.cpp b/libs/input/tests/InputConsumerFilteredResampling_test.cpp
new file mode 100644
index 0000000..757cd18
--- /dev/null
+++ b/libs/input/tests/InputConsumerFilteredResampling_test.cpp
@@ -0,0 +1,218 @@
+/**
+ * Copyright 2024 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 <input/InputConsumerNoResampling.h>
+
+#include <chrono>
+#include <iostream>
+#include <memory>
+#include <queue>
+
+#include <TestEventMatchers.h>
+#include <TestInputChannel.h>
+#include <android-base/logging.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <input/Input.h>
+#include <input/InputEventBuilders.h>
+#include <input/Resampler.h>
+#include <utils/Looper.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace {
+
+using std::chrono::nanoseconds;
+
+using ::testing::AllOf;
+using ::testing::Matcher;
+
+const int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
+const int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
+
+struct Pointer {
+ int32_t id{0};
+ ToolType toolType{ToolType::FINGER};
+ float x{0.0f};
+ float y{0.0f};
+ bool isResampled{false};
+
+ PointerBuilder asPointerBuilder() const {
+ return PointerBuilder{id, toolType}.x(x).y(y).isResampled(isResampled);
+ }
+};
+
+} // namespace
+
+class InputConsumerFilteredResamplingTest : public ::testing::Test, public InputConsumerCallbacks {
+protected:
+ InputConsumerFilteredResamplingTest()
+ : mClientTestChannel{std::make_shared<TestInputChannel>("TestChannel")},
+ mLooper{sp<Looper>::make(/*allowNonCallbacks=*/false)} {
+ Looper::setForThread(mLooper);
+ mConsumer = std::make_unique<
+ InputConsumerNoResampling>(mClientTestChannel, mLooper, *this, []() {
+ return std::make_unique<FilteredLegacyResampler>(/*minCutoffFreq=*/4.7, /*beta=*/0.01);
+ });
+ }
+
+ void invokeLooperCallback() const {
+ sp<LooperCallback> callback;
+ ASSERT_TRUE(mLooper->getFdStateDebug(mClientTestChannel->getFd(), /*ident=*/nullptr,
+ /*events=*/nullptr, &callback, /*data=*/nullptr));
+ ASSERT_NE(callback, nullptr);
+ callback->handleEvent(mClientTestChannel->getFd(), ALOOPER_EVENT_INPUT, /*data=*/nullptr);
+ }
+
+ void assertOnBatchedInputEventPendingWasCalled() {
+ ASSERT_GT(mOnBatchedInputEventPendingInvocationCount, 0UL)
+ << "onBatchedInputEventPending was not called";
+ --mOnBatchedInputEventPendingInvocationCount;
+ }
+
+ void assertReceivedMotionEvent(const Matcher<MotionEvent>& matcher) {
+ ASSERT_TRUE(!mMotionEvents.empty()) << "No motion events were received";
+ std::unique_ptr<MotionEvent> motionEvent = std::move(mMotionEvents.front());
+ mMotionEvents.pop();
+ ASSERT_NE(motionEvent, nullptr) << "The consumed motion event must not be nullptr";
+ EXPECT_THAT(*motionEvent, matcher);
+ }
+
+ InputMessage nextPointerMessage(nanoseconds eventTime, int32_t action, const Pointer& pointer);
+
+ std::shared_ptr<TestInputChannel> mClientTestChannel;
+ sp<Looper> mLooper;
+ std::unique_ptr<InputConsumerNoResampling> mConsumer;
+
+ // Batched input events
+ std::queue<std::unique_ptr<KeyEvent>> mKeyEvents;
+ std::queue<std::unique_ptr<MotionEvent>> mMotionEvents;
+ std::queue<std::unique_ptr<FocusEvent>> mFocusEvents;
+ std::queue<std::unique_ptr<CaptureEvent>> mCaptureEvents;
+ std::queue<std::unique_ptr<DragEvent>> mDragEvents;
+ std::queue<std::unique_ptr<TouchModeEvent>> mTouchModeEvents;
+
+private:
+ // InputConsumer callbacks
+ void onKeyEvent(std::unique_ptr<KeyEvent> event, uint32_t seq) override {
+ mKeyEvents.push(std::move(event));
+ mConsumer->finishInputEvent(seq, /*handled=*/true);
+ }
+
+ void onMotionEvent(std::unique_ptr<MotionEvent> event, uint32_t seq) override {
+ mMotionEvents.push(std::move(event));
+ mConsumer->finishInputEvent(seq, /*handled=*/true);
+ }
+
+ void onBatchedInputEventPending(int32_t pendingBatchSource) override {
+ if (!mConsumer->probablyHasInput()) {
+ ADD_FAILURE() << "Should deterministically have input because there is a batch";
+ }
+ ++mOnBatchedInputEventPendingInvocationCount;
+ }
+
+ void onFocusEvent(std::unique_ptr<FocusEvent> event, uint32_t seq) override {
+ mFocusEvents.push(std::move(event));
+ mConsumer->finishInputEvent(seq, /*handled=*/true);
+ }
+
+ void onCaptureEvent(std::unique_ptr<CaptureEvent> event, uint32_t seq) override {
+ mCaptureEvents.push(std::move(event));
+ mConsumer->finishInputEvent(seq, /*handled=*/true);
+ }
+
+ void onDragEvent(std::unique_ptr<DragEvent> event, uint32_t seq) override {
+ mDragEvents.push(std::move(event));
+ mConsumer->finishInputEvent(seq, /*handled=*/true);
+ }
+
+ void onTouchModeEvent(std::unique_ptr<TouchModeEvent> event, uint32_t seq) override {
+ mTouchModeEvents.push(std::move(event));
+ mConsumer->finishInputEvent(seq, /*handled=*/true);
+ }
+
+ uint32_t mLastSeq{0};
+ size_t mOnBatchedInputEventPendingInvocationCount{0};
+};
+
+InputMessage InputConsumerFilteredResamplingTest::nextPointerMessage(nanoseconds eventTime,
+ int32_t action,
+ const Pointer& pointer) {
+ ++mLastSeq;
+ return InputMessageBuilder{InputMessage::Type::MOTION, mLastSeq}
+ .eventTime(eventTime.count())
+ .source(AINPUT_SOURCE_TOUCHSCREEN)
+ .action(action)
+ .pointer(pointer.asPointerBuilder())
+ .build();
+}
+
+TEST_F(InputConsumerFilteredResamplingTest, NeighboringTimestampsDoNotResultInZeroDivision) {
+ mClientTestChannel->enqueueMessage(
+ nextPointerMessage(0ms, ACTION_DOWN, Pointer{.x = 0.0f, .y = 0.0f}));
+
+ invokeLooperCallback();
+
+ assertReceivedMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithSampleCount(1)));
+
+ const std::chrono::nanoseconds initialTime{56'821'700'000'000};
+
+ mClientTestChannel->enqueueMessage(nextPointerMessage(initialTime + 4'929'000ns, ACTION_MOVE,
+ Pointer{.x = 1.0f, .y = 1.0f}));
+ mClientTestChannel->enqueueMessage(nextPointerMessage(initialTime + 9'352'000ns, ACTION_MOVE,
+ Pointer{.x = 2.0f, .y = 2.0f}));
+ mClientTestChannel->enqueueMessage(nextPointerMessage(initialTime + 14'531'000ns, ACTION_MOVE,
+ Pointer{.x = 3.0f, .y = 3.0f}));
+
+ invokeLooperCallback();
+ mConsumer->consumeBatchedInputEvents(initialTime.count() + 18'849'395 /*ns*/);
+
+ assertOnBatchedInputEventPendingWasCalled();
+ // Three samples are expected. The first two of the batch, and the resampled one. The
+ // coordinates of the resampled sample are hardcoded because the matcher requires them. However,
+ // the primary intention here is to check that the last sample is resampled.
+ assertReceivedMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithSampleCount(3),
+ WithSample(/*sampleIndex=*/2,
+ Sample{initialTime + 13'849'395ns,
+ {PointerArgs{.x = 1.3286f,
+ .y = 1.3286f,
+ .isResampled = true}}})));
+
+ mClientTestChannel->enqueueMessage(nextPointerMessage(initialTime + 20'363'000ns, ACTION_MOVE,
+ Pointer{.x = 4.0f, .y = 4.0f}));
+ mClientTestChannel->enqueueMessage(nextPointerMessage(initialTime + 25'745'000ns, ACTION_MOVE,
+ Pointer{.x = 5.0f, .y = 5.0f}));
+ // This sample is part of the stream of messages, but should not be consumed because its
+ // timestamp is greater than the ajusted frame time.
+ mClientTestChannel->enqueueMessage(nextPointerMessage(initialTime + 31'337'000ns, ACTION_MOVE,
+ Pointer{.x = 6.0f, .y = 6.0f}));
+
+ invokeLooperCallback();
+ mConsumer->consumeBatchedInputEvents(initialTime.count() + 35'516'062 /*ns*/);
+
+ assertOnBatchedInputEventPendingWasCalled();
+ // Four samples are expected because the last sample of the previous batch was not consumed.
+ assertReceivedMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithSampleCount(4)));
+
+ mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true);
+ mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true);
+ mClientTestChannel->assertFinishMessage(/*seq=*/3, /*handled=*/true);
+ mClientTestChannel->assertFinishMessage(/*seq=*/4, /*handled=*/true);
+ mClientTestChannel->assertFinishMessage(/*seq=*/5, /*handled=*/true);
+ mClientTestChannel->assertFinishMessage(/*seq=*/6, /*handled=*/true);
+}
+
+} // namespace android
diff --git a/libs/input/tests/InputConsumerResampling_test.cpp b/libs/input/tests/InputConsumerResampling_test.cpp
index 883ca82..97688a8 100644
--- a/libs/input/tests/InputConsumerResampling_test.cpp
+++ b/libs/input/tests/InputConsumerResampling_test.cpp
@@ -38,6 +38,8 @@
using std::chrono::nanoseconds;
using namespace std::chrono_literals;
+const std::chrono::milliseconds RESAMPLE_LATENCY{5};
+
struct Pointer {
int32_t id{0};
float x{0.0f};
@@ -440,7 +442,7 @@
{20ms, {Pointer{.id = 0, .x = 30.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE}));
invokeLooperCallback();
- mConsumer->consumeBatchedInputEvents(nanoseconds{20ms + 5ms /*RESAMPLE_LATENCY*/}.count());
+ mConsumer->consumeBatchedInputEvents(nanoseconds{20ms + RESAMPLE_LATENCY}.count());
// MotionEvent should not resampled because the resample time falls exactly on the existing
// event time.
@@ -496,14 +498,15 @@
{40ms, {Pointer{.id = 0, .x = 30.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE}));
invokeLooperCallback();
- mConsumer->consumeBatchedInputEvents(nanoseconds{45ms + 5ms /*RESAMPLE_LATENCY*/}.count());
+ mConsumer->consumeBatchedInputEvents(nanoseconds{45ms + RESAMPLE_LATENCY}.count());
+ // Original and resampled event should be both overwritten.
assertReceivedMotionEvent(
{InputEventEntry{40ms,
{Pointer{.id = 0, .x = 35.0f, .y = 30.0f, .isResampled = true}},
- AMOTION_EVENT_ACTION_MOVE}, // original event, rewritten
+ AMOTION_EVENT_ACTION_MOVE},
InputEventEntry{45ms,
{Pointer{.id = 0, .x = 35.0f, .y = 30.0f, .isResampled = true}},
- AMOTION_EVENT_ACTION_MOVE}}); // resampled event, rewritten
+ AMOTION_EVENT_ACTION_MOVE}});
mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true);
mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true);
@@ -552,13 +555,14 @@
invokeLooperCallback();
mConsumer->consumeBatchedInputEvents(nanoseconds{50ms}.count());
+ // Original and resampled event should be both overwritten.
assertReceivedMotionEvent(
{InputEventEntry{24ms,
{Pointer{.id = 0, .x = 35.0f, .y = 30.0f, .isResampled = true}},
- AMOTION_EVENT_ACTION_MOVE}, // original event, rewritten
+ AMOTION_EVENT_ACTION_MOVE},
InputEventEntry{26ms,
{Pointer{.id = 0, .x = 45.0f, .y = 30.0f, .isResampled = true}},
- AMOTION_EVENT_ACTION_MOVE}}); // resampled event, rewritten
+ AMOTION_EVENT_ACTION_MOVE}});
mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true);
mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true);
@@ -566,4 +570,175 @@
mClientTestChannel->assertFinishMessage(/*seq=*/4, /*handled=*/true);
}
+TEST_F(InputConsumerResamplingTest, DoNotResampleWhenFrameTimeIsNotAvailable) {
+ mClientTestChannel->enqueueMessage(nextPointerMessage(
+ {0ms, {Pointer{.id = 0, .x = 10.0f, .y = 20.0f}}, AMOTION_EVENT_ACTION_DOWN}));
+
+ invokeLooperCallback();
+ assertReceivedMotionEvent({InputEventEntry{0ms,
+ {Pointer{.id = 0, .x = 10.0f, .y = 20.0f}},
+ AMOTION_EVENT_ACTION_DOWN}});
+
+ mClientTestChannel->enqueueMessage(nextPointerMessage(
+ {10ms, {Pointer{.id = 0, .x = 20.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE}));
+ mClientTestChannel->enqueueMessage(nextPointerMessage(
+ {20ms, {Pointer{.id = 0, .x = 30.0f, .y = 30.0f}}, AMOTION_EVENT_ACTION_MOVE}));
+
+ invokeLooperCallback();
+ mConsumer->consumeBatchedInputEvents(std::nullopt);
+ assertReceivedMotionEvent({InputEventEntry{10ms,
+ {Pointer{.id = 0, .x = 20.0f, .y = 30.0f}},
+ AMOTION_EVENT_ACTION_MOVE},
+ InputEventEntry{20ms,
+ {Pointer{.id = 0, .x = 30.0f, .y = 30.0f}},
+ AMOTION_EVENT_ACTION_MOVE}});
+
+ mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true);
+ mClientTestChannel->assertFinishMessage(/*seq=*/2, /*handled=*/true);
+ mClientTestChannel->assertFinishMessage(/*seq=*/3, /*handled=*/true);
+}
+
+TEST_F(InputConsumerResamplingTest, TwoPointersAreResampledIndependently) {
+ // Full action for when a pointer with index=1 appears (some other pointer must already be
+ // present)
+ const int32_t actionPointer1Down =
+ AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+
+ // Full action for when a pointer with index=0 disappears (some other pointer must still remain)
+ const int32_t actionPointer0Up =
+ AMOTION_EVENT_ACTION_POINTER_UP + (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+
+ mClientTestChannel->enqueueMessage(nextPointerMessage(
+ {0ms, {Pointer{.id = 0, .x = 100.0f, .y = 100.0f}}, AMOTION_EVENT_ACTION_DOWN}));
+
+ mClientTestChannel->assertNoSentMessages();
+
+ invokeLooperCallback();
+ assertReceivedMotionEvent({InputEventEntry{0ms,
+ {Pointer{.id = 0, .x = 100.0f, .y = 100.0f}},
+ AMOTION_EVENT_ACTION_DOWN}});
+
+ mClientTestChannel->enqueueMessage(nextPointerMessage(
+ {10ms, {Pointer{.id = 0, .x = 100.0f, .y = 100.0f}}, AMOTION_EVENT_ACTION_MOVE}));
+
+ invokeLooperCallback();
+ mConsumer->consumeBatchedInputEvents(nanoseconds{10ms + RESAMPLE_LATENCY}.count());
+ // Not resampled value because requestedFrameTime - RESAMPLE_LATENCY == eventTime
+ assertReceivedMotionEvent({InputEventEntry{10ms,
+ {Pointer{.id = 0, .x = 100.0f, .y = 100.0f}},
+ AMOTION_EVENT_ACTION_MOVE}});
+
+ // Second pointer id=1 appears
+ mClientTestChannel->enqueueMessage(
+ nextPointerMessage({15ms,
+ {Pointer{.id = 0, .x = 100.0f, .y = 100.0f},
+ Pointer{.id = 1, .x = 500.0f, .y = 500.0f}},
+ actionPointer1Down}));
+
+ invokeLooperCallback();
+ mConsumer->consumeBatchedInputEvents(nanoseconds{20ms + RESAMPLE_LATENCY}.count());
+ // Not resampled value because requestedFrameTime - RESAMPLE_LATENCY == eventTime.
+ assertReceivedMotionEvent({InputEventEntry{15ms,
+ {Pointer{.id = 0, .x = 100.0f, .y = 100.0f},
+ Pointer{.id = 1, .x = 500.0f, .y = 500.0f}},
+ actionPointer1Down}});
+
+ // Both pointers move
+ mClientTestChannel->enqueueMessage(
+ nextPointerMessage({30ms,
+ {Pointer{.id = 0, .x = 100.0f, .y = 100.0f},
+ Pointer{.id = 1, .x = 500.0f, .y = 500.0f}},
+ AMOTION_EVENT_ACTION_MOVE}));
+ mClientTestChannel->enqueueMessage(
+ nextPointerMessage({40ms,
+ {Pointer{.id = 0, .x = 120.0f, .y = 120.0f},
+ Pointer{.id = 1, .x = 600.0f, .y = 600.0f}},
+ AMOTION_EVENT_ACTION_MOVE}));
+
+ invokeLooperCallback();
+ mConsumer->consumeBatchedInputEvents(nanoseconds{45ms + RESAMPLE_LATENCY}.count());
+ assertReceivedMotionEvent(
+ {InputEventEntry{30ms,
+ {Pointer{.id = 0, .x = 100.0f, .y = 100.0f},
+ Pointer{.id = 1, .x = 500.0f, .y = 500.0f}},
+ AMOTION_EVENT_ACTION_MOVE},
+ InputEventEntry{40ms,
+ {Pointer{.id = 0, .x = 120.0f, .y = 120.0f},
+ Pointer{.id = 1, .x = 600.0f, .y = 600.0f}},
+ AMOTION_EVENT_ACTION_MOVE},
+ InputEventEntry{45ms,
+ {Pointer{.id = 0, .x = 130.0f, .y = 130.0f, .isResampled = true},
+ Pointer{.id = 1, .x = 650.0f, .y = 650.0f, .isResampled = true}},
+ AMOTION_EVENT_ACTION_MOVE}});
+
+ // Both pointers move again
+ mClientTestChannel->enqueueMessage(
+ nextPointerMessage({60ms,
+ {Pointer{.id = 0, .x = 120.0f, .y = 120.0f},
+ Pointer{.id = 1, .x = 600.0f, .y = 600.0f}},
+ AMOTION_EVENT_ACTION_MOVE}));
+ mClientTestChannel->enqueueMessage(
+ nextPointerMessage({70ms,
+ {Pointer{.id = 0, .x = 130.0f, .y = 130.0f},
+ Pointer{.id = 1, .x = 700.0f, .y = 700.0f}},
+ AMOTION_EVENT_ACTION_MOVE}));
+
+ invokeLooperCallback();
+ mConsumer->consumeBatchedInputEvents(nanoseconds{75ms + RESAMPLE_LATENCY}.count());
+
+ /*
+ * The pointer id 0 at t = 60 should not be equal to 120 because the value was received twice,
+ * and resampled to 130. Therefore, if we reported 130, then we should continue to report it as
+ * such. Likewise, with pointer id 1.
+ */
+
+ // Not 120 because it matches a previous real event.
+ assertReceivedMotionEvent(
+ {InputEventEntry{60ms,
+ {Pointer{.id = 0, .x = 130.0f, .y = 130.0f, .isResampled = true},
+ Pointer{.id = 1, .x = 650.0f, .y = 650.0f, .isResampled = true}},
+ AMOTION_EVENT_ACTION_MOVE},
+ InputEventEntry{70ms,
+ {Pointer{.id = 0, .x = 130.0f, .y = 130.0f},
+ Pointer{.id = 1, .x = 700.0f, .y = 700.0f}},
+ AMOTION_EVENT_ACTION_MOVE},
+ InputEventEntry{75ms,
+ {Pointer{.id = 0, .x = 135.0f, .y = 135.0f, .isResampled = true},
+ Pointer{.id = 1, .x = 750.0f, .y = 750.0f, .isResampled = true}},
+ AMOTION_EVENT_ACTION_MOVE}});
+
+ // First pointer id=0 leaves the screen
+ mClientTestChannel->enqueueMessage(
+ nextPointerMessage({80ms,
+ {Pointer{.id = 0, .x = 120.0f, .y = 120.0f},
+ Pointer{.id = 1, .x = 600.0f, .y = 600.0f}},
+ actionPointer0Up}));
+
+ invokeLooperCallback();
+ // Not resampled event for ACTION_POINTER_UP
+ assertReceivedMotionEvent({InputEventEntry{80ms,
+ {Pointer{.id = 0, .x = 120.0f, .y = 120.0f},
+ Pointer{.id = 1, .x = 600.0f, .y = 600.0f}},
+ actionPointer0Up}});
+
+ // Remaining pointer id=1 is still present, but doesn't move
+ mClientTestChannel->enqueueMessage(nextPointerMessage(
+ {90ms, {Pointer{.id = 1, .x = 600.0f, .y = 600.0f}}, AMOTION_EVENT_ACTION_MOVE}));
+
+ invokeLooperCallback();
+ mConsumer->consumeBatchedInputEvents(nanoseconds{100ms}.count());
+
+ /*
+ * The latest event with ACTION_MOVE was at t = 70 with value = 700. Thus, the resampled value
+ * is 700 + ((95 - 70)/(90 - 70))*(600 - 700) = 575.
+ */
+ assertReceivedMotionEvent(
+ {InputEventEntry{90ms,
+ {Pointer{.id = 1, .x = 600.0f, .y = 600.0f}},
+ AMOTION_EVENT_ACTION_MOVE},
+ InputEventEntry{95ms,
+ {Pointer{.id = 1, .x = 575.0f, .y = 575.0f, .isResampled = true}},
+ AMOTION_EVENT_ACTION_MOVE}});
+}
+
} // namespace android
diff --git a/libs/input/tests/InputConsumer_test.cpp b/libs/input/tests/InputConsumer_test.cpp
index 6a3bbe5..226b892 100644
--- a/libs/input/tests/InputConsumer_test.cpp
+++ b/libs/input/tests/InputConsumer_test.cpp
@@ -70,11 +70,20 @@
[]() { return std::make_unique<LegacyResampler>(); });
}
- void invokeLooperCallback() const {
+ bool invokeLooperCallback() const {
sp<LooperCallback> callback;
- ASSERT_TRUE(mLooper->getFdStateDebug(mClientTestChannel->getFd(), /*ident=*/nullptr,
- /*events=*/nullptr, &callback, /*data=*/nullptr));
+ const bool found =
+ mLooper->getFdStateDebug(mClientTestChannel->getFd(), /*ident=*/nullptr,
+ /*events=*/nullptr, &callback, /*data=*/nullptr);
+ if (!found) {
+ return false;
+ }
+ if (callback == nullptr) {
+ LOG(FATAL) << "Looper has the fd of interest, but the callback is null!";
+ return false;
+ }
callback->handleEvent(mClientTestChannel->getFd(), ALOOPER_EVENT_INPUT, /*data=*/nullptr);
+ return true;
}
void assertOnBatchedInputEventPendingWasCalled() {
@@ -194,7 +203,7 @@
std::unique_ptr<MotionEvent> moveMotionEvent =
assertReceivedMotionEvent(WithMotionAction(ACTION_MOVE));
ASSERT_NE(moveMotionEvent, nullptr);
- EXPECT_EQ(moveMotionEvent->getHistorySize() + 1, 3UL);
+ EXPECT_EQ(moveMotionEvent->getHistorySize() + 1, 2UL);
mClientTestChannel->assertFinishMessage(/*seq=*/0, /*handled=*/true);
mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/true);
@@ -271,6 +280,27 @@
}
/**
+ * Check what happens when looper invokes callback after consumer has been destroyed.
+ * This reproduces a crash where the LooperEventCallback was added back to the Looper during
+ * destructor, thus allowing the looper callback to be invoked onto a null consumer object.
+ */
+TEST_F(InputConsumerTest, LooperCallbackInvokedAfterConsumerDestroyed) {
+ mClientTestChannel->enqueueMessage(
+ InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/0}.action(ACTION_DOWN).build());
+ mClientTestChannel->enqueueMessage(
+ InputMessageBuilder{InputMessage::Type::MOTION, /*seq=*/1}.action(ACTION_MOVE).build());
+ ASSERT_TRUE(invokeLooperCallback());
+ assertOnBatchedInputEventPendingWasCalled();
+ assertReceivedMotionEvent(WithMotionAction(ACTION_DOWN));
+ mClientTestChannel->assertFinishMessage(/*seq=*/0, /*handled=*/true);
+
+ // Now, destroy the consumer and invoke the looper callback again after it's been destroyed.
+ mConsumer.reset();
+ mClientTestChannel->assertFinishMessage(/*seq=*/1, /*handled=*/false);
+ ASSERT_FALSE(invokeLooperCallback());
+}
+
+/**
* Send an event to the InputConsumer, but do not invoke "consumeBatchedInputEvents", thus leaving
* the input event unconsumed by the callbacks. Ensure that no crash occurs when the consumer is
* destroyed.
@@ -443,4 +473,5 @@
mClientTestChannel->assertFinishMessage(/*seq=*/8, /*handled=*/true);
mClientTestChannel->assertFinishMessage(/*seq=*/10, /*handled=*/true);
}
+
} // namespace android
diff --git a/libs/input/tests/InputPublisherAndConsumerNoResampling_test.cpp b/libs/input/tests/InputPublisherAndConsumerNoResampling_test.cpp
index 1210f71..1dadae9 100644
--- a/libs/input/tests/InputPublisherAndConsumerNoResampling_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumerNoResampling_test.cpp
@@ -14,15 +14,18 @@
* limitations under the License.
*/
+#include <TestEventMatchers.h>
#include <android-base/logging.h>
#include <attestation/HmacKeyManager.h>
#include <ftl/enum.h>
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <input/BlockingQueue.h>
#include <input/InputConsumerNoResampling.h>
#include <input/InputTransport.h>
using android::base::Result;
+using ::testing::Matcher;
namespace android {
@@ -278,7 +281,7 @@
void SetUp() override {
std::unique_ptr<InputChannel> serverChannel;
status_t result =
- InputChannel::openInputChannelPair("channel name", serverChannel, mClientChannel);
+ InputChannel::openInputChannelPair("test channel", serverChannel, mClientChannel);
ASSERT_EQ(OK, result);
mPublisher = std::make_unique<InputPublisher>(std::move(serverChannel));
@@ -316,6 +319,8 @@
protected:
// Interaction with the looper thread
+ void blockLooper();
+ void unblockLooper();
enum class LooperMessage : int {
CALL_PROBABLY_HAS_INPUT,
CREATE_CONSUMER,
@@ -336,6 +341,8 @@
// accessed on the test thread.
BlockingQueue<bool> mProbablyHasInputResponses;
+ std::unique_ptr<MotionEvent> assertReceivedMotionEvent(const Matcher<MotionEvent>& matcher);
+
private:
sp<MessageHandler> mMessageHandler;
void handleMessage(const Message& message);
@@ -384,11 +391,45 @@
};
};
+void InputPublisherAndConsumerNoResamplingTest::blockLooper() {
+ {
+ std::scoped_lock l(mLock);
+ mLooperMayProceed = false;
+ }
+ sendMessage(LooperMessage::BLOCK_LOOPER);
+ {
+ std::unique_lock l(mLock);
+ mNotifyLooperWaiting.wait(l, [this] { return mLooperIsBlocked; });
+ }
+}
+
+void InputPublisherAndConsumerNoResamplingTest::unblockLooper() {
+ {
+ std::scoped_lock l(mLock);
+ mLooperMayProceed = true;
+ }
+ mNotifyLooperMayProceed.notify_all();
+}
+
void InputPublisherAndConsumerNoResamplingTest::sendMessage(LooperMessage message) {
Message msg{ftl::to_underlying(message)};
mLooper->sendMessage(mMessageHandler, msg);
}
+std::unique_ptr<MotionEvent> InputPublisherAndConsumerNoResamplingTest::assertReceivedMotionEvent(
+ const Matcher<MotionEvent>& matcher) {
+ std::optional<std::unique_ptr<MotionEvent>> event = mMotionEvents.popWithTimeout(TIMEOUT);
+ if (!event) {
+ ADD_FAILURE() << "No event was received, but expected motion " << matcher;
+ return nullptr;
+ }
+ if (*event == nullptr) {
+ LOG(FATAL) << "Event was received, but it was null";
+ }
+ EXPECT_THAT(**event, matcher);
+ return std::move(*event);
+}
+
void InputPublisherAndConsumerNoResamplingTest::handleMessage(const Message& message) {
switch (static_cast<LooperMessage>(message.what)) {
case LooperMessage::CALL_PROBABLY_HAS_INPUT: {
@@ -572,8 +613,7 @@
const nsecs_t publishTimeOfDown = systemTime(SYSTEM_TIME_MONOTONIC);
publishMotionEvent(*mPublisher, argsDown);
- // Consume the DOWN event.
- ASSERT_TRUE(mMotionEvents.popWithTimeout(TIMEOUT).has_value());
+ assertReceivedMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
verifyFinishedSignal(*mPublisher, mSeq, publishTimeOfDown);
@@ -582,15 +622,7 @@
std::queue<uint32_t> publishedSequenceNumbers;
// Block Looper to increase the chance of batching events
- {
- std::scoped_lock l(mLock);
- mLooperMayProceed = false;
- }
- sendMessage(LooperMessage::BLOCK_LOOPER);
- {
- std::unique_lock l(mLock);
- mNotifyLooperWaiting.wait(l, [this] { return mLooperIsBlocked; });
- }
+ blockLooper();
uint32_t firstSampleId;
for (size_t i = 0; i < nSamples; ++i) {
@@ -611,21 +643,16 @@
std::vector<MotionEvent> singleSampledMotionEvents;
- // Unblock Looper
- {
- std::scoped_lock l(mLock);
- mLooperMayProceed = true;
- }
- mNotifyLooperMayProceed.notify_all();
+ unblockLooper();
// We have no control over the socket behavior, so the consumer can receive
// the motion as a batched event, or as a sequence of multiple single-sample MotionEvents (or a
// mix of those)
while (singleSampledMotionEvents.size() != nSamples) {
- const std::optional<std::unique_ptr<MotionEvent>> batchedMotionEvent =
- mMotionEvents.popWithTimeout(TIMEOUT);
+ const std::unique_ptr<MotionEvent> batchedMotionEvent =
+ assertReceivedMotionEvent(WithMotionAction(ACTION_MOVE));
// The events received by these calls are never null
- std::vector<MotionEvent> splitMotionEvents = splitBatchedMotionEvent(**batchedMotionEvent);
+ std::vector<MotionEvent> splitMotionEvents = splitBatchedMotionEvent(*batchedMotionEvent);
singleSampledMotionEvents.insert(singleSampledMotionEvents.end(), splitMotionEvents.begin(),
splitMotionEvents.end());
}
@@ -681,10 +708,7 @@
}
mNotifyLooperMayProceed.notify_all();
- std::optional<std::unique_ptr<MotionEvent>> optMotion = mMotionEvents.popWithTimeout(TIMEOUT);
- ASSERT_TRUE(optMotion.has_value());
- std::unique_ptr<MotionEvent> motion = std::move(*optMotion);
- ASSERT_EQ(ACTION_MOVE, motion->getAction());
+ assertReceivedMotionEvent(WithMotionAction(ACTION_MOVE));
verifyFinishedSignal(*mPublisher, seq, publishTime);
}
@@ -696,9 +720,7 @@
nsecs_t publishTime = systemTime(SYSTEM_TIME_MONOTONIC);
publishMotionEvent(*mPublisher, args);
- std::optional<std::unique_ptr<MotionEvent>> optMotion = mMotionEvents.popWithTimeout(TIMEOUT);
- ASSERT_TRUE(optMotion.has_value());
- std::unique_ptr<MotionEvent> event = std::move(*optMotion);
+ std::unique_ptr<MotionEvent> event = assertReceivedMotionEvent(WithMotionAction(action));
verifyArgsEqualToEvent(args, *event);
@@ -796,6 +818,15 @@
verifyFinishedSignal(*mPublisher, seq, publishTime);
}
+/**
+ * If the publisher has died, consumer should not crash when trying to send an outgoing message.
+ */
+TEST_F(InputPublisherAndConsumerNoResamplingTest, ConsumerWritesAfterPublisherDies) {
+ mPublisher.reset(); // The publisher has died
+ mReportTimelineArgs.emplace(/*inputEventId=*/10, /*gpuCompletedTime=*/20, /*presentTime=*/30);
+ sendMessage(LooperMessage::CALL_REPORT_TIMELINE);
+}
+
TEST_F(InputPublisherAndConsumerNoResamplingTest, SendTimeline) {
const int32_t inputEventId = 20;
const nsecs_t gpuCompletedTime = 30;
diff --git a/libs/input/tests/InputVerifier_test.cpp b/libs/input/tests/InputVerifier_test.cpp
index e2eb080..8e0d906 100644
--- a/libs/input/tests/InputVerifier_test.cpp
+++ b/libs/input/tests/InputVerifier_test.cpp
@@ -14,9 +14,13 @@
* limitations under the License.
*/
+#include <android/input.h>
+#include <android-base/result.h>
#include <gtest/gtest.h>
+#include <input/Input.h>
#include <input/InputVerifier.h>
#include <string>
+#include <vector>
namespace android {
@@ -45,10 +49,10 @@
const Result<void> result =
verifier.processMovement(/*deviceId=*/0, AINPUT_SOURCE_CLASS_POINTER,
- AMOTION_EVENT_ACTION_DOWN,
+ AMOTION_EVENT_ACTION_DOWN, /*actionButton=*/0,
/*pointerCount=*/properties.size(), properties.data(),
- coords.data(), /*flags=*/0);
- ASSERT_TRUE(result.ok());
+ coords.data(), /*flags=*/0, /*buttonState=*/0);
+ ASSERT_RESULT_OK(result);
}
} // namespace android
diff --git a/libs/input/tests/OneEuroFilter_test.cpp b/libs/input/tests/OneEuroFilter_test.cpp
new file mode 100644
index 0000000..8645508
--- /dev/null
+++ b/libs/input/tests/OneEuroFilter_test.cpp
@@ -0,0 +1,137 @@
+/**
+ * Copyright 2024 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 <input/OneEuroFilter.h>
+
+#include <algorithm>
+#include <chrono>
+#include <cmath>
+#include <numeric>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include <input/Input.h>
+
+namespace android {
+namespace {
+
+using namespace std::literals::chrono_literals;
+using std::chrono::duration;
+
+struct Sample {
+ duration<double> timestamp{};
+ double value{};
+
+ friend bool operator<(const Sample& lhs, const Sample& rhs) { return lhs.value < rhs.value; }
+};
+
+/**
+ * Generates a sinusoidal signal with the passed frequency and amplitude.
+ */
+std::vector<Sample> generateSinusoidalSignal(duration<double> signalDuration,
+ double samplingFrequency, double signalFrequency,
+ double amplitude) {
+ std::vector<Sample> signal;
+ const duration<double> samplingPeriod{1.0 / samplingFrequency};
+ for (duration<double> timestamp{0.0}; timestamp < signalDuration; timestamp += samplingPeriod) {
+ signal.push_back(
+ Sample{timestamp,
+ amplitude * std::sin(2.0 * M_PI * signalFrequency * timestamp.count())});
+ }
+ return signal;
+}
+
+double meanAbsoluteError(const std::vector<Sample>& filteredSignal,
+ const std::vector<Sample>& signal) {
+ if (filteredSignal.size() != signal.size()) {
+ ADD_FAILURE() << "filteredSignal and signal do not have equal number of samples";
+ return std::numeric_limits<double>::max();
+ }
+ std::vector<double> absoluteError;
+ for (size_t sampleIndex = 0; sampleIndex < signal.size(); ++sampleIndex) {
+ absoluteError.push_back(
+ std::abs(filteredSignal[sampleIndex].value - signal[sampleIndex].value));
+ }
+ if (absoluteError.empty()) {
+ ADD_FAILURE() << "Zero division. absoluteError is empty";
+ return std::numeric_limits<double>::max();
+ }
+ return std::accumulate(absoluteError.begin(), absoluteError.end(), 0.0) / absoluteError.size();
+}
+
+double maxAbsoluteAmplitude(const std::vector<Sample>& signal) {
+ if (signal.empty()) {
+ ADD_FAILURE() << "Max absolute value amplitude does not exist. Signal is empty";
+ return std::numeric_limits<double>::max();
+ }
+ std::vector<Sample> absoluteSignal;
+ for (const Sample& sample : signal) {
+ absoluteSignal.push_back(Sample{sample.timestamp, std::abs(sample.value)});
+ }
+ return std::max_element(absoluteSignal.begin(), absoluteSignal.end())->value;
+}
+
+} // namespace
+
+class OneEuroFilterTest : public ::testing::Test {
+protected:
+ // The constructor's parameters are the ones that Chromium's using. The tuning was based on a 60
+ // Hz sampling frequency. Refer to their one_euro_filter.h header for additional information
+ // about these parameters.
+ OneEuroFilterTest() : mFilter{/*minCutoffFreq=*/4.7, /*beta=*/0.01} {}
+
+ std::vector<Sample> filterSignal(const std::vector<Sample>& signal) {
+ std::vector<Sample> filteredSignal;
+ for (const Sample& sample : signal) {
+ filteredSignal.push_back(
+ Sample{sample.timestamp,
+ mFilter.filter(std::chrono::duration_cast<std::chrono::nanoseconds>(
+ sample.timestamp),
+ sample.value)});
+ }
+ return filteredSignal;
+ }
+
+ OneEuroFilter mFilter;
+};
+
+TEST_F(OneEuroFilterTest, PassLowFrequencySignal) {
+ const std::vector<Sample> signal =
+ generateSinusoidalSignal(1s, /*samplingFrequency=*/60, /*signalFrequency=*/1,
+ /*amplitude=*/1);
+
+ const std::vector<Sample> filteredSignal = filterSignal(signal);
+
+ // The reason behind using the mean absolute error as a metric is that, ideally, a low frequency
+ // filtered signal is expected to be almost identical to the raw one. Therefore, the error
+ // between them should be minimal. The constant is heuristically chosen.
+ EXPECT_LT(meanAbsoluteError(filteredSignal, signal), 0.25);
+}
+
+TEST_F(OneEuroFilterTest, RejectHighFrequencySignal) {
+ const std::vector<Sample> signal =
+ generateSinusoidalSignal(1s, /*samplingFrequency=*/60, /*signalFrequency=*/22.5,
+ /*amplitude=*/1);
+
+ const std::vector<Sample> filteredSignal = filterSignal(signal);
+
+ // The filtered signal should consist of values that are much closer to zero. The comparison
+ // constant is heuristically chosen.
+ EXPECT_LT(maxAbsoluteAmplitude(filteredSignal), 0.25);
+}
+
+} // namespace android
diff --git a/libs/input/tests/Resampler_test.cpp b/libs/input/tests/Resampler_test.cpp
index fae8518..3162b77 100644
--- a/libs/input/tests/Resampler_test.cpp
+++ b/libs/input/tests/Resampler_test.cpp
@@ -648,7 +648,15 @@
mResampler->resampleMotionEvent(16ms, motionEvent, &futureSample);
- assertMotionEventIsNotResampled(originalMotionEvent, motionEvent);
+ assertMotionEventIsResampledAndCoordsNear(originalMotionEvent, motionEvent,
+ {Pointer{.id = 0,
+ .x = 1.4f,
+ .y = 1.4f,
+ .isResampled = true},
+ Pointer{.id = 1,
+ .x = 2.4f,
+ .y = 2.4f,
+ .isResampled = true}});
}
TEST_F(ResamplerTest, MultiplePointerDifferentIdOrderExtrapolation) {
@@ -670,7 +678,15 @@
mResampler->resampleMotionEvent(16ms, secondMotionEvent, /*futureSample=*/nullptr);
- assertMotionEventIsNotResampled(secondOriginalMotionEvent, secondMotionEvent);
+ assertMotionEventIsResampledAndCoordsNear(secondOriginalMotionEvent, secondMotionEvent,
+ {Pointer{.id = 1,
+ .x = 4.4f,
+ .y = 4.4f,
+ .isResampled = true},
+ Pointer{.id = 0,
+ .x = 3.4f,
+ .y = 3.4f,
+ .isResampled = true}});
}
TEST_F(ResamplerTest, MultiplePointerDifferentIdsInterpolation) {
diff --git a/libs/input/tests/TestEventMatchers.h b/libs/input/tests/TestEventMatchers.h
index 3589de5..8dbdcb3 100644
--- a/libs/input/tests/TestEventMatchers.h
+++ b/libs/input/tests/TestEventMatchers.h
@@ -17,6 +17,7 @@
#pragma once
#include <chrono>
+#include <cmath>
#include <ostream>
#include <vector>
@@ -26,12 +27,8 @@
namespace android {
-namespace {
-
using ::testing::Matcher;
-} // namespace
-
/**
* This file contains a copy of Matchers from .../inputflinger/tests/TestEventMatchers.h. Ideally,
* implementations must not be duplicated.
@@ -75,12 +72,18 @@
using is_gtest_matcher = void;
explicit WithMotionActionMatcher(int32_t action) : mAction(action) {}
- bool MatchAndExplain(const MotionEvent& event, std::ostream*) const {
- bool matches = mAction == event.getAction();
- if (event.getAction() == AMOTION_EVENT_ACTION_CANCEL) {
- matches &= (event.getFlags() & AMOTION_EVENT_FLAG_CANCELED) != 0;
+ bool MatchAndExplain(const MotionEvent& event, testing::MatchResultListener* listener) const {
+ if (mAction != event.getAction()) {
+ *listener << "expected " << MotionEvent::actionToString(mAction) << ", but got "
+ << MotionEvent::actionToString(event.getAction());
+ return false;
}
- return matches;
+ if (event.getAction() == AMOTION_EVENT_ACTION_CANCEL &&
+ (event.getFlags() & AMOTION_EVENT_FLAG_CANCELED) == 0) {
+ *listener << "event with CANCEL action is missing FLAG_CANCELED";
+ return false;
+ }
+ return true;
}
void DescribeTo(std::ostream* os) const {
@@ -150,14 +153,18 @@
++pointerIndex) {
const PointerCoords& pointerCoords =
*(motionEvent.getHistoricalRawPointerCoords(pointerIndex, mSampleIndex));
- if ((pointerCoords.getX() != mSample.pointers[pointerIndex].x) ||
- (pointerCoords.getY() != mSample.pointers[pointerIndex].y)) {
+
+ if ((std::abs(pointerCoords.getX() - mSample.pointers[pointerIndex].x) >
+ MotionEvent::ROUNDING_PRECISION) ||
+ (std::abs(pointerCoords.getY() - mSample.pointers[pointerIndex].y) >
+ MotionEvent::ROUNDING_PRECISION)) {
*os << "sample coordinates mismatch at pointer index " << pointerIndex
<< ". sample: (" << pointerCoords.getX() << ", " << pointerCoords.getY()
<< ") expected: (" << mSample.pointers[pointerIndex].x << ", "
<< mSample.pointers[pointerIndex].y << ")";
return false;
}
+
if (motionEvent.isResampled(pointerIndex, mSampleIndex) !=
mSample.pointers[pointerIndex].isResampled) {
*os << "resampling flag mismatch. sample: "
diff --git a/libs/input/tests/TfLiteMotionPredictor_test.cpp b/libs/input/tests/TfLiteMotionPredictor_test.cpp
index c3ac0b7..0c19ebe 100644
--- a/libs/input/tests/TfLiteMotionPredictor_test.cpp
+++ b/libs/input/tests/TfLiteMotionPredictor_test.cpp
@@ -89,23 +89,23 @@
buffers.pushSample(/*timestamp=*/1,
{.position = {.x = 10, .y = 10},
.pressure = 0,
- .orientation = 0,
- .tilt = 0.2});
+ .tilt = 0.2,
+ .orientation = 0});
buffers.pushSample(/*timestamp=*/2,
{.position = {.x = 10, .y = 50},
.pressure = 0.4,
- .orientation = M_PI / 4,
- .tilt = 0.3});
+ .tilt = 0.3,
+ .orientation = M_PI / 4});
buffers.pushSample(/*timestamp=*/3,
{.position = {.x = 30, .y = 50},
.pressure = 0.5,
- .orientation = -M_PI / 4,
- .tilt = 0.4});
+ .tilt = 0.4,
+ .orientation = -M_PI / 4});
buffers.pushSample(/*timestamp=*/3,
{.position = {.x = 30, .y = 60},
.pressure = 0,
- .orientation = 0,
- .tilt = 0.5});
+ .tilt = 0.5,
+ .orientation = 0});
buffers.copyTo(*model);
const int zeroPadding = model->inputLength() - 3;
diff --git a/libs/input/tests/TouchResampling_test.cpp b/libs/input/tests/TouchResampling_test.cpp
index 8d8b530..9841c03 100644
--- a/libs/input/tests/TouchResampling_test.cpp
+++ b/libs/input/tests/TouchResampling_test.cpp
@@ -571,11 +571,12 @@
std::chrono::nanoseconds frameTime;
std::vector<InputEventEntry> entries, expectedEntries;
- // full action for when a pointer with id=1 appears (some other pointer must already be present)
+ // full action for when a pointer with index=1 appears (some other pointer must already be
+ // present)
constexpr int32_t actionPointer1Down =
AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
- // full action for when a pointer with id=0 disappears (some other pointer must still remain)
+ // full action for when a pointer with index=0 disappears (some other pointer must still remain)
constexpr int32_t actionPointer0Up =
AMOTION_EVENT_ACTION_POINTER_UP + (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
diff --git a/libs/math/OWNERS b/libs/math/OWNERS
index 82ae422..08f0c5f 100644
--- a/libs/math/OWNERS
+++ b/libs/math/OWNERS
@@ -1,5 +1,4 @@
mathias@google.com
-randolphs@google.com
romainguy@google.com
sumir@google.com
jreck@google.com
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index bed31e2..89a97de 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -142,7 +142,7 @@
}
AChoreographer* AChoreographer_getInstance() {
- return Choreographer_to_AChoreographer(Choreographer::getForThread());
+ return Choreographer_to_AChoreographer(Choreographer::getForThread().get());
}
void AChoreographer_postFrameCallback(AChoreographer* choreographer,
@@ -238,13 +238,17 @@
}
AChoreographer* AChoreographer_create() {
- Choreographer* choreographer = new Choreographer(nullptr);
+ // Increments default strongRef count on construction, will be decremented on
+ // function exit.
+ auto choreographer = sp<Choreographer>::make(nullptr);
status_t result = choreographer->initialize();
if (result != OK) {
ALOGW("Failed to initialize");
return nullptr;
}
- return Choreographer_to_AChoreographer(choreographer);
+ // Will be decremented and destroyed by AChoreographer_destroy
+ choreographer->incStrong((void*)AChoreographer_create);
+ return Choreographer_to_AChoreographer(choreographer.get());
}
void AChoreographer_destroy(AChoreographer* choreographer) {
@@ -252,7 +256,7 @@
return;
}
- delete AChoreographer_to_Choreographer(choreographer);
+ AChoreographer_to_Choreographer(choreographer)->decStrong((void*)AChoreographer_create);
}
int AChoreographer_getFd(const AChoreographer* choreographer) {
diff --git a/libs/nativedisplay/include/surfacetexture/EGLConsumer.h b/libs/nativedisplay/include/surfacetexture/EGLConsumer.h
index 444722b..226a8a6 100644
--- a/libs/nativedisplay/include/surfacetexture/EGLConsumer.h
+++ b/libs/nativedisplay/include/surfacetexture/EGLConsumer.h
@@ -113,18 +113,11 @@
protected:
struct PendingRelease {
- PendingRelease()
- : isPending(false),
- currentTexture(-1),
- graphicBuffer(),
- display(nullptr),
- fence(nullptr) {}
+ PendingRelease() : isPending(false), currentTexture(-1), graphicBuffer() {}
bool isPending;
int currentTexture;
sp<GraphicBuffer> graphicBuffer;
- EGLDisplay display;
- EGLSyncKHR fence;
};
/**
@@ -250,13 +243,16 @@
* EGLConsumer maintains about a BufferQueue buffer slot.
*/
struct EglSlot {
- EglSlot() : mEglFence(EGL_NO_SYNC_KHR) {}
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ EglSlot() : mEglFence(EGL_NO_SYNC_KHR) {}
+#endif
/**
* mEglImage is the EGLImage created from mGraphicBuffer.
*/
sp<EglImage> mEglImage;
+#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
/**
* mFence is the EGL sync object that must signal before the buffer
* associated with this buffer slot may be dequeued. It is initialized
@@ -264,6 +260,7 @@
* on a compile-time option) set to a new sync object in updateTexImage.
*/
EGLSyncKHR mEglFence;
+#endif
};
/**
diff --git a/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h b/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
index f1453bd..253aa18 100644
--- a/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
+++ b/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
@@ -343,8 +343,13 @@
* releaseBufferLocked overrides the ConsumerBase method to update the
* mEglSlots array in addition to the ConsumerBase.
*/
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ virtual status_t releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer) override;
+#else
virtual status_t releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer,
- EGLDisplay display, EGLSyncKHR eglFence) override;
+ EGLDisplay display = EGL_NO_DISPLAY,
+ EGLSyncKHR eglFence = EGL_NO_SYNC_KHR) override;
+#endif
/**
* freeBufferLocked frees up the given buffer slot. If the slot has been
diff --git a/libs/nativedisplay/surfacetexture/EGLConsumer.cpp b/libs/nativedisplay/surfacetexture/EGLConsumer.cpp
index 275b7a4..fad0f6c 100644
--- a/libs/nativedisplay/surfacetexture/EGLConsumer.cpp
+++ b/libs/nativedisplay/surfacetexture/EGLConsumer.cpp
@@ -150,8 +150,7 @@
}
}
- err = st.releaseBufferLocked(buf, st.mSlots[buf].mGraphicBuffer, mEglDisplay,
- EGL_NO_SYNC_KHR);
+ err = st.releaseBufferLocked(buf, st.mSlots[buf].mGraphicBuffer);
if (err < NO_ERROR) {
EGC_LOGE("releaseTexImage: failed to release buffer: %s (%d)", strerror(-err), err);
return err;
@@ -222,7 +221,11 @@
}
void EGLConsumer::onReleaseBufferLocked(int buf) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ (void)buf;
+#else
mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
+#endif
}
status_t EGLConsumer::updateAndReleaseLocked(const BufferItem& item, PendingRelease* pendingRelease,
@@ -234,14 +237,14 @@
if (st.mOpMode != SurfaceTexture::OpMode::attachedToGL) {
EGC_LOGE("updateAndRelease: EGLConsumer is not attached to an OpenGL "
"ES context");
- st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR);
+ st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer);
return INVALID_OPERATION;
}
// Confirm state.
err = checkAndUpdateEglStateLocked(st);
if (err != NO_ERROR) {
- st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR);
+ st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer);
return err;
}
@@ -254,7 +257,7 @@
if (err != NO_ERROR) {
EGC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d", mEglDisplay,
slot);
- st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR);
+ st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer);
return UNKNOWN_ERROR;
}
@@ -266,8 +269,7 @@
// release the old buffer, so instead we just drop the new frame.
// As we are still under lock since acquireBuffer, it is safe to
// release by slot.
- st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, mEglDisplay,
- EGL_NO_SYNC_KHR);
+ st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer);
return err;
}
}
@@ -285,10 +287,15 @@
// release old buffer
if (st.mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
if (pendingRelease == nullptr) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ status_t status = st.releaseBufferLocked(st.mCurrentTexture,
+ mCurrentTextureImage->graphicBuffer());
+#else
status_t status =
st.releaseBufferLocked(st.mCurrentTexture,
mCurrentTextureImage->graphicBuffer(), mEglDisplay,
mEglSlots[st.mCurrentTexture].mEglFence);
+#endif
if (status < NO_ERROR) {
EGC_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status),
status);
@@ -298,8 +305,6 @@
} else {
pendingRelease->currentTexture = st.mCurrentTexture;
pendingRelease->graphicBuffer = mCurrentTextureImage->graphicBuffer();
- pendingRelease->display = mEglDisplay;
- pendingRelease->fence = mEglSlots[st.mCurrentTexture].mEglFence;
pendingRelease->isPending = true;
}
}
@@ -504,6 +509,11 @@
return err;
}
} else if (st.mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ // Basically all clients are using native fence syncs. If they aren't, we lose nothing
+ // by waiting here, because the alternative can cause deadlocks (b/339705065).
+ glFinish();
+#else
EGLSyncKHR fence = mEglSlots[st.mCurrentTexture].mEglFence;
if (fence != EGL_NO_SYNC_KHR) {
// There is already a fence for the current slot. We need to
@@ -533,6 +543,7 @@
}
glFlush();
mEglSlots[st.mCurrentTexture].mEglFence = fence;
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
}
}
diff --git a/libs/nativedisplay/surfacetexture/ImageConsumer.cpp b/libs/nativedisplay/surfacetexture/ImageConsumer.cpp
index 32b229d..1ffd382 100644
--- a/libs/nativedisplay/surfacetexture/ImageConsumer.cpp
+++ b/libs/nativedisplay/surfacetexture/ImageConsumer.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+#define EGL_EGLEXT_PROTOTYPES
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
#include <gui/BufferQueue.h>
#include <surfacetexture/ImageConsumer.h>
#include <surfacetexture/SurfaceTexture.h>
@@ -64,8 +68,7 @@
// Wait on the producer fence for the buffer to be ready.
err = fenceWait(item.mFence->get(), fencePassThroughHandle);
if (err != OK) {
- st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY,
- EGL_NO_SYNC_KHR);
+ st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer);
return nullptr;
}
}
@@ -79,8 +82,7 @@
err = createFence(st.mUseFenceSync, &mImageSlots[slot].eglFence(), &display,
&releaseFenceId, fencePassThroughHandle);
if (OK != err) {
- st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY,
- EGL_NO_SYNC_KHR);
+ st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer);
return nullptr;
}
@@ -91,17 +93,40 @@
releaseFence);
if (err != OK) {
IMG_LOGE("dequeueImage: error adding release fence: %s (%d)", strerror(-err), err);
- st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY,
- EGL_NO_SYNC_KHR);
+ st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer);
return nullptr;
}
}
// Finally release the old buffer.
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ EGLSyncKHR previousFence = mImageSlots[st.mCurrentTexture].eglFence();
+ if (previousFence != EGL_NO_SYNC_KHR) {
+ // Most platforms will be using native fences, so it's unlikely that we'll ever have to
+ // process an eglFence. Ideally we can remove this code eventually. In the mean time, do
+ // our best to wait for it so the buffer stays valid, otherwise return an error to the
+ // caller.
+ //
+ // EGL_SYNC_FLUSH_COMMANDS_BIT_KHR so that we don't wait forever on a fence that hasn't
+ // shown up on the GPU yet.
+ EGLint result = eglClientWaitSyncKHR(display, previousFence,
+ EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 1000000000);
+ if (result == EGL_FALSE) {
+ IMG_LOGE("dequeueBuffer: error %#x waiting for fence", eglGetError());
+ } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+ IMG_LOGE("dequeueBuffer: timeout waiting for fence");
+ }
+ eglDestroySyncKHR(display, previousFence);
+ }
+
+ status_t status = st.releaseBufferLocked(st.mCurrentTexture,
+ st.mSlots[st.mCurrentTexture].mGraphicBuffer);
+#else
status_t status =
st.releaseBufferLocked(st.mCurrentTexture,
st.mSlots[st.mCurrentTexture].mGraphicBuffer, display,
mImageSlots[st.mCurrentTexture].eglFence());
+#endif
if (status < NO_ERROR) {
IMG_LOGE("dequeueImage: failed to release buffer: %s (%d)", strerror(-status), status);
err = status;
diff --git a/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp b/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
index ce232cc..c0a1cc5 100644
--- a/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
+++ b/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
@@ -178,13 +178,21 @@
return NO_ERROR;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+status_t SurfaceTexture::releaseBufferLocked(int buf, sp<GraphicBuffer> graphicBuffer) {
+#else
status_t SurfaceTexture::releaseBufferLocked(int buf, sp<GraphicBuffer> graphicBuffer,
EGLDisplay display, EGLSyncKHR eglFence) {
+#endif
// release the buffer if it hasn't already been discarded by the
// BufferQueue. This can happen, for example, when the producer of this
// buffer has reallocated the original buffer slot after this buffer
// was acquired.
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BQ_GL_FENCE_CLEANUP)
+ status_t err = ConsumerBase::releaseBufferLocked(buf, graphicBuffer);
+#else
status_t err = ConsumerBase::releaseBufferLocked(buf, graphicBuffer, display, eglFence);
+#endif
// We could be releasing an EGL/Vulkan buffer, even if not currently
// attached to a GL context.
mImageConsumer.onReleaseBufferLocked(buf);
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index ca41346..3205c32 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -112,6 +112,10 @@
static_cast<int>(aidl::android::hardware::graphics::common::PixelFormat::RGBA_10101010) ==
AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM,
"HAL and AHardwareBuffer pixel format don't match");
+static_assert(
+ static_cast<int>(aidl::android::hardware::graphics::common::PixelFormat::YCBCR_P210) ==
+ AHARDWAREBUFFER_FORMAT_YCbCr_P210,
+ "HAL and AHardwareBuffer pixel format don't match");
static enum AHardwareBufferStatus filterStatus(status_t status) {
switch (status) {
@@ -300,8 +304,10 @@
if (result == 0) {
outPlanes->planeCount = 3;
outPlanes->planes[0].data = yuvData.y;
- // P010 is word-aligned 10-bit semiplaner, and YCbCr_422_I is a single interleaved plane
+ // P010 & P210 are word-aligned 10-bit semiplaner, and YCbCr_422_I is a single interleaved
+ // plane
if (format == AHARDWAREBUFFER_FORMAT_YCbCr_P010 ||
+ format == AHARDWAREBUFFER_FORMAT_YCbCr_P210 ||
format == AHARDWAREBUFFER_FORMAT_YCbCr_422_I) {
outPlanes->planes[0].pixelStride = 2;
} else {
@@ -724,6 +730,7 @@
case AHARDWAREBUFFER_FORMAT_YCrCb_420_SP:
case AHARDWAREBUFFER_FORMAT_YCbCr_422_I:
case AHARDWAREBUFFER_FORMAT_YCbCr_P010:
+ case AHARDWAREBUFFER_FORMAT_YCbCr_P210:
return true;
default:
return false;
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index f97eed5..f5a1db5 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -222,6 +222,8 @@
static_cast<int>(HAL_DATASPACE_BT2020_ITU_HLG));
static_assert(static_cast<int>(ADATASPACE_DEPTH) == static_cast<int>(HAL_DATASPACE_DEPTH));
static_assert(static_cast<int>(ADATASPACE_DYNAMIC_DEPTH) == static_cast<int>(HAL_DATASPACE_DYNAMIC_DEPTH));
+ static_assert(static_cast<int>(ADATASPACE_DISPLAY_BT2020) ==
+ static_cast<int>(HAL_DATASPACE_DISPLAY_BT2020));
if (!window || !query(window, NATIVE_WINDOW_IS_VALID)) {
return -EINVAL;
diff --git a/libs/nativewindow/include/android/data_space.h b/libs/nativewindow/include/android/data_space.h
index 8056d9a..295a307 100644
--- a/libs/nativewindow/include/android/data_space.h
+++ b/libs/nativewindow/include/android/data_space.h
@@ -578,6 +578,13 @@
*/
ADATASPACE_BT2020_ITU_HLG = 302383104, // ADATASPACE_STANDARD_BT2020 | ADATASPACE_TRANSFER_HLG |
// ADATASPACE_RANGE_LIMITED
+ /**
+ * sRGB-encoded BT. 2020
+ *
+ * Uses full range, sRGB transfer and BT2020 standard.
+ */
+ ADATASPACE_DISPLAY_BT2020 = 142999552, // ADATASPACE_STANDARD_BT2020 | ADATASPACE_TRANSFER_SRGB
+ // | ADATASPACE_RANGE_FULL
/**
* Depth
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index d05ff34..5a78a5c 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -175,6 +175,14 @@
AHARDWAREBUFFER_FORMAT_YCbCr_P010 = 0x36,
/**
+ * YUV P210 format.
+ * Must have an even width and height. Can be accessed in OpenGL
+ * shaders through an external sampler. Does not support mip-maps
+ * cube-maps or multi-layered textures.
+ */
+ AHARDWAREBUFFER_FORMAT_YCbCr_P210 = 0x3c,
+
+ /**
* Corresponding formats:
* Vulkan: VK_FORMAT_R8_UNORM
* OpenGL ES: GR_GL_R8
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index be6623e..10abb7c 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -243,8 +243,7 @@
* There are no inherent restrictions on the frame rate of this window. When
* the system selects a frame rate other than what the app requested, the
* app will be able to run at the system frame rate without requiring pull
- * down. This value should be used when displaying game content, UIs, and
- * anything that isn't video.
+ * down. This value should be used when displaying game content.
*/
ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT = 0,
/**
@@ -256,7 +255,14 @@
* stuttering) than it would be if the system had chosen the app's requested
* frame rate. This value should be used for video content.
*/
- ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE = 1
+ ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE = 1,
+
+ /**
+ * The window requests a frame rate that is at least the specified frame rate.
+ * This value should be used for UIs, animations, scrolling, and anything that is not a game
+ * or video.
+ */
+ ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_AT_LEAST = 2
};
/**
@@ -366,14 +372,13 @@
*
* See ANativeWindow_setFrameRateWithChangeStrategy().
*
- * Available since API level 34.
+ * Available since API level 31.
*
* \param window pointer to an ANativeWindow object.
*
* \return 0 for success, -EINVAL if the window value is invalid.
*/
-inline int32_t ANativeWindow_clearFrameRate(ANativeWindow* window)
- __INTRODUCED_IN(__ANDROID_API_U__) {
+inline int32_t ANativeWindow_clearFrameRate(ANativeWindow* window) __INTRODUCED_IN(31) {
return ANativeWindow_setFrameRateWithChangeStrategy(window, 0,
ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT,
ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 33c303a..f669f77 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -1060,12 +1060,7 @@
/**
* This surface will vote for the minimum refresh rate.
*/
- ANATIVEWINDOW_FRAME_RATE_MIN,
-
- /**
- * The surface requests a frame rate that is greater than or equal to `frameRate`.
- */
- ANATIVEWINDOW_FRAME_RATE_GTE
+ ANATIVEWINDOW_FRAME_RATE_MIN
};
/*
diff --git a/libs/nativewindow/rust/Android.bp b/libs/nativewindow/rust/Android.bp
index c572ee7..faab48b 100644
--- a/libs/nativewindow/rust/Android.bp
+++ b/libs/nativewindow/rust/Android.bp
@@ -110,6 +110,7 @@
name: "libnativewindow_defaults",
srcs: ["src/lib.rs"],
rustlibs: [
+ "android.hardware.common-V2-rust",
"libbinder_rs",
"libbitflags",
"libnativewindow_bindgen",
diff --git a/libs/nativewindow/rust/src/handle.rs b/libs/nativewindow/rust/src/handle.rs
index c41ab8d..2b08c1b 100644
--- a/libs/nativewindow/rust/src/handle.rs
+++ b/libs/nativewindow/rust/src/handle.rs
@@ -12,6 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+use android_hardware_common::{
+ aidl::android::hardware::common::NativeHandle::NativeHandle as AidlNativeHandle,
+ binder::ParcelFileDescriptor,
+};
use std::{
ffi::c_int,
mem::forget,
@@ -81,6 +85,12 @@
/// Destroys the `NativeHandle`, taking ownership of the file descriptors it contained.
pub fn into_fds(self) -> Vec<OwnedFd> {
+ // Unset FDSan tag since this `native_handle_t` is no longer the owner of the file
+ // descriptors after this function.
+ // SAFETY: Our wrapped `native_handle_t` pointer is always valid.
+ unsafe {
+ ffi::native_handle_unset_fdsan_tag(self.as_ref());
+ }
let fds = self.data()[..self.fd_count()]
.iter()
.map(|fd| {
@@ -190,6 +200,21 @@
}
}
+impl From<AidlNativeHandle> for NativeHandle {
+ fn from(aidl_native_handle: AidlNativeHandle) -> Self {
+ let fds = aidl_native_handle.fds.into_iter().map(OwnedFd::from).collect();
+ Self::new(fds, &aidl_native_handle.ints).unwrap()
+ }
+}
+
+impl From<NativeHandle> for AidlNativeHandle {
+ fn from(native_handle: NativeHandle) -> Self {
+ let ints = native_handle.ints().to_owned();
+ let fds = native_handle.into_fds().into_iter().map(ParcelFileDescriptor::new).collect();
+ Self { ints, fds }
+ }
+}
+
// SAFETY: `NativeHandle` owns the `native_handle_t`, which just contains some integers and file
// descriptors, which aren't tied to any particular thread.
unsafe impl Send for NativeHandle {}
@@ -240,4 +265,43 @@
drop(cloned);
}
+
+ #[test]
+ fn to_fds() {
+ let file = File::open("/dev/null").unwrap();
+ let original = NativeHandle::new(vec![file.into()], &[42]).unwrap();
+ assert_eq!(original.ints(), &[42]);
+ assert_eq!(original.fds().len(), 1);
+
+ let fds = original.into_fds();
+ assert_eq!(fds.len(), 1);
+ }
+
+ #[test]
+ fn to_aidl() {
+ let file = File::open("/dev/null").unwrap();
+ let original = NativeHandle::new(vec![file.into()], &[42]).unwrap();
+ assert_eq!(original.ints(), &[42]);
+ assert_eq!(original.fds().len(), 1);
+
+ let aidl = AidlNativeHandle::from(original);
+ assert_eq!(&aidl.ints, &[42]);
+ assert_eq!(aidl.fds.len(), 1);
+ }
+
+ #[test]
+ fn to_from_aidl() {
+ let file = File::open("/dev/null").unwrap();
+ let original = NativeHandle::new(vec![file.into()], &[42]).unwrap();
+ assert_eq!(original.ints(), &[42]);
+ assert_eq!(original.fds().len(), 1);
+
+ let aidl = AidlNativeHandle::from(original);
+ assert_eq!(&aidl.ints, &[42]);
+ assert_eq!(aidl.fds.len(), 1);
+
+ let converted_back = NativeHandle::from(aidl);
+ assert_eq!(converted_back.ints(), &[42]);
+ assert_eq!(converted_back.fds().len(), 1);
+ }
}
diff --git a/libs/nativewindow/rust/src/lib.rs b/libs/nativewindow/rust/src/lib.rs
index f19b908..aeb2603 100644
--- a/libs/nativewindow/rust/src/lib.rs
+++ b/libs/nativewindow/rust/src/lib.rs
@@ -30,12 +30,14 @@
StatusCode,
};
use ffi::{
- AHardwareBuffer, AHardwareBuffer_Desc, AHardwareBuffer_readFromParcel,
- AHardwareBuffer_writeToParcel,
+ AHardwareBuffer, AHardwareBuffer_Desc, AHardwareBuffer_Plane, AHardwareBuffer_Planes,
+ AHardwareBuffer_readFromParcel, AHardwareBuffer_writeToParcel, ARect,
};
+use std::ffi::c_void;
use std::fmt::{self, Debug, Formatter};
-use std::mem::ManuallyDrop;
-use std::ptr::{self, null_mut, NonNull};
+use std::mem::{forget, ManuallyDrop};
+use std::os::fd::{AsRawFd, BorrowedFd, FromRawFd, OwnedFd};
+use std::ptr::{self, null, null_mut, NonNull};
/// Wrapper around a C `AHardwareBuffer_Desc`.
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -203,8 +205,8 @@
Self(buffer_ptr)
}
- /// Creates a new Rust HardwareBuffer to wrap the given AHardwareBuffer without taking ownership
- /// of it.
+ /// Creates a new Rust HardwareBuffer to wrap the given `AHardwareBuffer` without taking
+ /// ownership of it.
///
/// Unlike [`from_raw`](Self::from_raw) this method will increment the refcount on the buffer.
/// This means that the caller can continue to use the raw buffer it passed in, and must call
@@ -220,8 +222,20 @@
Self(buffer)
}
- /// Get the internal |AHardwareBuffer| pointer without decrementing the refcount. This can
- /// be used to provide a pointer to the AHB for a C/C++ API over the FFI.
+ /// Returns the internal `AHardwareBuffer` pointer.
+ ///
+ /// This is only valid as long as this `HardwareBuffer` exists, so shouldn't be stored. It can
+ /// be used to provide a pointer for a C/C++ API over FFI.
+ pub fn as_raw(&self) -> NonNull<AHardwareBuffer> {
+ self.0
+ }
+
+ /// Gets the internal `AHardwareBuffer` pointer without decrementing the refcount. This can
+ /// be used for a C/C++ API which takes ownership of the pointer.
+ ///
+ /// The caller is responsible for releasing the `AHardwareBuffer` pointer by calling
+ /// `AHardwareBuffer_release` when it is finished with it, or may convert it back to a Rust
+ /// `HardwareBuffer` by calling [`HardwareBuffer::from_raw`].
pub fn into_raw(self) -> NonNull<AHardwareBuffer> {
let buffer = ManuallyDrop::new(self);
buffer.0
@@ -255,10 +269,192 @@
rfu0: 0,
rfu1: 0,
};
- // SAFETY: neither the buffer nor AHardwareBuffer_Desc pointers will be null.
+ // SAFETY: The `AHardwareBuffer` pointer we wrap is always valid, and the
+ // AHardwareBuffer_Desc pointer is valid because it comes from a reference.
unsafe { ffi::AHardwareBuffer_describe(self.0.as_ref(), &mut buffer_desc) };
HardwareBufferDescription(buffer_desc)
}
+
+ /// Locks the hardware buffer for direct CPU access.
+ ///
+ /// # Safety
+ ///
+ /// - If `fence` is `None`, the caller must ensure that all writes to the buffer have completed
+ /// before calling this function.
+ /// - If the buffer has `AHARDWAREBUFFER_FORMAT_BLOB`, multiple threads or process may lock the
+ /// buffer simultaneously, but the caller must ensure that they don't access it simultaneously
+ /// and break Rust's aliasing rules, like any other shared memory.
+ /// - Otherwise if `usage` includes `AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY` or
+ /// `AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN`, the caller must ensure that no other threads or
+ /// processes lock the buffer simultaneously for any usage.
+ /// - Otherwise, the caller must ensure that no other threads lock the buffer for writing
+ /// simultaneously.
+ /// - If `rect` is not `None`, the caller must not modify the buffer outside of that rectangle.
+ pub unsafe fn lock<'a>(
+ &'a self,
+ usage: AHardwareBuffer_UsageFlags,
+ fence: Option<BorrowedFd>,
+ rect: Option<&ARect>,
+ ) -> Result<HardwareBufferGuard<'a>, StatusCode> {
+ let fence = if let Some(fence) = fence { fence.as_raw_fd() } else { -1 };
+ let rect = rect.map(ptr::from_ref).unwrap_or(null());
+ let mut address = null_mut();
+ // SAFETY: The `AHardwareBuffer` pointer we wrap is always valid, and the buffer address out
+ // pointer is valid because it comes from a reference. Our caller promises that writes have
+ // completed and there will be no simultaneous read/write locks.
+ let status = unsafe {
+ ffi::AHardwareBuffer_lock(self.0.as_ptr(), usage.0, fence, rect, &mut address)
+ };
+ status_result(status)?;
+ Ok(HardwareBufferGuard {
+ buffer: self,
+ address: NonNull::new(address)
+ .expect("AHardwareBuffer_lock set a null outVirtualAddress"),
+ })
+ }
+
+ /// Lock a potentially multi-planar hardware buffer for direct CPU access.
+ ///
+ /// # Safety
+ ///
+ /// - If `fence` is `None`, the caller must ensure that all writes to the buffer have completed
+ /// before calling this function.
+ /// - If the buffer has `AHARDWAREBUFFER_FORMAT_BLOB`, multiple threads or process may lock the
+ /// buffer simultaneously, but the caller must ensure that they don't access it simultaneously
+ /// and break Rust's aliasing rules, like any other shared memory.
+ /// - Otherwise if `usage` includes `AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY` or
+ /// `AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN`, the caller must ensure that no other threads or
+ /// processes lock the buffer simultaneously for any usage.
+ /// - Otherwise, the caller must ensure that no other threads lock the buffer for writing
+ /// simultaneously.
+ /// - If `rect` is not `None`, the caller must not modify the buffer outside of that rectangle.
+ pub unsafe fn lock_planes<'a>(
+ &'a self,
+ usage: AHardwareBuffer_UsageFlags,
+ fence: Option<BorrowedFd>,
+ rect: Option<&ARect>,
+ ) -> Result<Vec<PlaneGuard<'a>>, StatusCode> {
+ let fence = if let Some(fence) = fence { fence.as_raw_fd() } else { -1 };
+ let rect = rect.map(ptr::from_ref).unwrap_or(null());
+ let mut planes = AHardwareBuffer_Planes {
+ planeCount: 0,
+ planes: [const { AHardwareBuffer_Plane { data: null_mut(), pixelStride: 0, rowStride: 0 } };
+ 4],
+ };
+
+ // SAFETY: The `AHardwareBuffer` pointer we wrap is always valid, and the various out
+ // pointers are valid because they come from references. Our caller promises that writes have
+ // completed and there will be no simultaneous read/write locks.
+ let status = unsafe {
+ ffi::AHardwareBuffer_lockPlanes(self.0.as_ptr(), usage.0, fence, rect, &mut planes)
+ };
+ status_result(status)?;
+ let plane_count = planes.planeCount.try_into().unwrap();
+ Ok(planes.planes[..plane_count]
+ .iter()
+ .map(|plane| PlaneGuard {
+ guard: HardwareBufferGuard {
+ buffer: self,
+ address: NonNull::new(plane.data)
+ .expect("AHardwareBuffer_lockAndGetInfo set a null outVirtualAddress"),
+ },
+ pixel_stride: plane.pixelStride,
+ row_stride: plane.rowStride,
+ })
+ .collect())
+ }
+
+ /// Locks the hardware buffer for direct CPU access, returning information about the bytes per
+ /// pixel and stride as well.
+ ///
+ /// # Safety
+ ///
+ /// - If `fence` is `None`, the caller must ensure that all writes to the buffer have completed
+ /// before calling this function.
+ /// - If the buffer has `AHARDWAREBUFFER_FORMAT_BLOB`, multiple threads or process may lock the
+ /// buffer simultaneously, but the caller must ensure that they don't access it simultaneously
+ /// and break Rust's aliasing rules, like any other shared memory.
+ /// - Otherwise if `usage` includes `AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY` or
+ /// `AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN`, the caller must ensure that no other threads or
+ /// processes lock the buffer simultaneously for any usage.
+ /// - Otherwise, the caller must ensure that no other threads lock the buffer for writing
+ /// simultaneously.
+ pub unsafe fn lock_and_get_info<'a>(
+ &'a self,
+ usage: AHardwareBuffer_UsageFlags,
+ fence: Option<BorrowedFd>,
+ rect: Option<&ARect>,
+ ) -> Result<LockedBufferInfo<'a>, StatusCode> {
+ let fence = if let Some(fence) = fence { fence.as_raw_fd() } else { -1 };
+ let rect = rect.map(ptr::from_ref).unwrap_or(null());
+ let mut address = null_mut();
+ let mut bytes_per_pixel = 0;
+ let mut stride = 0;
+ // SAFETY: The `AHardwareBuffer` pointer we wrap is always valid, and the various out
+ // pointers are valid because they come from references. Our caller promises that writes have
+ // completed and there will be no simultaneous read/write locks.
+ let status = unsafe {
+ ffi::AHardwareBuffer_lockAndGetInfo(
+ self.0.as_ptr(),
+ usage.0,
+ fence,
+ rect,
+ &mut address,
+ &mut bytes_per_pixel,
+ &mut stride,
+ )
+ };
+ status_result(status)?;
+ Ok(LockedBufferInfo {
+ guard: HardwareBufferGuard {
+ buffer: self,
+ address: NonNull::new(address)
+ .expect("AHardwareBuffer_lockAndGetInfo set a null outVirtualAddress"),
+ },
+ bytes_per_pixel: bytes_per_pixel as u32,
+ stride: stride as u32,
+ })
+ }
+
+ /// Unlocks the hardware buffer from direct CPU access.
+ ///
+ /// Must be called after all changes to the buffer are completed by the caller. This will block
+ /// until the unlocking is complete and the buffer contents are updated.
+ fn unlock(&self) -> Result<(), StatusCode> {
+ // SAFETY: The `AHardwareBuffer` pointer we wrap is always valid.
+ let status = unsafe { ffi::AHardwareBuffer_unlock(self.0.as_ptr(), null_mut()) };
+ status_result(status)?;
+ Ok(())
+ }
+
+ /// Unlocks the hardware buffer from direct CPU access.
+ ///
+ /// Must be called after all changes to the buffer are completed by the caller.
+ ///
+ /// This may not block until all work is completed, but rather will return a file descriptor
+ /// which will be signalled once the unlocking is complete and the buffer contents is updated.
+ /// If `Ok(None)` is returned then unlocking has already completed and no further waiting is
+ /// necessary. The file descriptor may be passed to a subsequent call to [`Self::lock`].
+ pub fn unlock_with_fence(
+ &self,
+ guard: HardwareBufferGuard,
+ ) -> Result<Option<OwnedFd>, StatusCode> {
+ // Forget the guard so that its `Drop` implementation doesn't try to unlock the
+ // HardwareBuffer again.
+ forget(guard);
+
+ let mut fence = -2;
+ // SAFETY: The `AHardwareBuffer` pointer we wrap is always valid.
+ let status = unsafe { ffi::AHardwareBuffer_unlock(self.0.as_ptr(), &mut fence) };
+ let fence = if fence < 0 {
+ None
+ } else {
+ // SAFETY: `AHardwareBuffer_unlock` gives us ownership of the fence file descriptor.
+ Some(unsafe { OwnedFd::from_raw_fd(fence) })
+ };
+ status_result(status)?;
+ Ok(fence)
+ }
}
impl Drop for HardwareBuffer {
@@ -334,6 +530,49 @@
// according to the docs on the underlying gralloc calls)
unsafe impl Sync for HardwareBuffer {}
+/// A guard for when a `HardwareBuffer` is locked.
+///
+/// The `HardwareBuffer` will be unlocked when this is dropped, or may be unlocked via
+/// [`HardwareBuffer::unlock_with_fence`].
+#[derive(Debug)]
+pub struct HardwareBufferGuard<'a> {
+ buffer: &'a HardwareBuffer,
+ /// The address of the buffer in memory.
+ pub address: NonNull<c_void>,
+}
+
+impl Drop for HardwareBufferGuard<'_> {
+ fn drop(&mut self) {
+ self.buffer
+ .unlock()
+ .expect("Failed to unlock HardwareBuffer when dropping HardwareBufferGuard");
+ }
+}
+
+/// A guard for when a `HardwareBuffer` is locked, with additional information about the number of
+/// bytes per pixel and stride.
+#[derive(Debug)]
+pub struct LockedBufferInfo<'a> {
+ /// The locked buffer guard.
+ pub guard: HardwareBufferGuard<'a>,
+ /// The number of bytes used for each pixel in the buffer.
+ pub bytes_per_pixel: u32,
+ /// The stride in bytes between rows in the buffer.
+ pub stride: u32,
+}
+
+/// A guard for a single plane of a locked `HardwareBuffer`, with additional information about the
+/// stride.
+#[derive(Debug)]
+pub struct PlaneGuard<'a> {
+ /// The locked buffer guard.
+ pub guard: HardwareBufferGuard<'a>,
+ /// The stride in bytes between the color channel for one pixel to the next pixel.
+ pub pixel_stride: u32,
+ /// The stride in bytes between rows in the buffer.
+ pub row_stride: u32,
+}
+
#[cfg(test)]
mod test {
use super::*;
@@ -487,4 +726,108 @@
assert_eq!(buffer.description(), buffer_description);
assert_eq!(buffer2.description(), buffer_description);
}
+
+ #[test]
+ fn lock() {
+ let buffer = HardwareBuffer::new(&HardwareBufferDescription::new(
+ 1024,
+ 512,
+ 1,
+ AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
+ AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN,
+ 0,
+ ))
+ .expect("Failed to create buffer");
+
+ // SAFETY: No other threads or processes have access to the buffer.
+ let guard = unsafe {
+ buffer.lock(
+ AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN,
+ None,
+ None,
+ )
+ }
+ .unwrap();
+
+ drop(guard);
+ }
+
+ #[test]
+ fn lock_with_rect() {
+ let buffer = HardwareBuffer::new(&HardwareBufferDescription::new(
+ 1024,
+ 512,
+ 1,
+ AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
+ AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN,
+ 0,
+ ))
+ .expect("Failed to create buffer");
+ let rect = ARect { left: 10, right: 20, top: 35, bottom: 45 };
+
+ // SAFETY: No other threads or processes have access to the buffer.
+ let guard = unsafe {
+ buffer.lock(
+ AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN,
+ None,
+ Some(&rect),
+ )
+ }
+ .unwrap();
+
+ drop(guard);
+ }
+
+ #[test]
+ fn unlock_with_fence() {
+ let buffer = HardwareBuffer::new(&HardwareBufferDescription::new(
+ 1024,
+ 512,
+ 1,
+ AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
+ AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN,
+ 0,
+ ))
+ .expect("Failed to create buffer");
+
+ // SAFETY: No other threads or processes have access to the buffer.
+ let guard = unsafe {
+ buffer.lock(
+ AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN,
+ None,
+ None,
+ )
+ }
+ .unwrap();
+
+ buffer.unlock_with_fence(guard).unwrap();
+ }
+
+ #[test]
+ fn lock_with_info() {
+ const WIDTH: u32 = 1024;
+ let buffer = HardwareBuffer::new(&HardwareBufferDescription::new(
+ WIDTH,
+ 512,
+ 1,
+ AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
+ AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN,
+ 0,
+ ))
+ .expect("Failed to create buffer");
+
+ // SAFETY: No other threads or processes have access to the buffer.
+ let info = unsafe {
+ buffer.lock_and_get_info(
+ AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN,
+ None,
+ None,
+ )
+ }
+ .unwrap();
+
+ assert_eq!(info.bytes_per_pixel, 4);
+ assert_eq!(info.stride, WIDTH * 4);
+ drop(info);
+ }
}
diff --git a/libs/nativewindow/tests/ANativeWindowTest.cpp b/libs/nativewindow/tests/ANativeWindowTest.cpp
index 937ff02..51d0c81 100644
--- a/libs/nativewindow/tests/ANativeWindowTest.cpp
+++ b/libs/nativewindow/tests/ANativeWindowTest.cpp
@@ -50,14 +50,9 @@
const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
ALOGV("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
-#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
- mItemConsumer = new BufferItemConsumer(GRALLOC_USAGE_SW_READ_OFTEN);
- mWindow = new TestableSurface(mItemConsumer->getSurface()->getIGraphicBufferProducer());
-#else
- BufferQueue::createBufferQueue(&mProducer, &mConsumer);
- mItemConsumer = new BufferItemConsumer(mConsumer, GRALLOC_USAGE_SW_READ_OFTEN);
- mWindow = new TestableSurface(mProducer);
-#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+ sp<Surface> surface;
+ std::tie(mItemConsumer, surface) = BufferItemConsumer::create(GRALLOC_USAGE_SW_READ_OFTEN);
+ mWindow = new TestableSurface(surface->getIGraphicBufferProducer());
const int success = native_window_api_connect(mWindow.get(), NATIVE_WINDOW_API_CPU);
EXPECT_EQ(0, success);
}
diff --git a/libs/permission/Android.bp b/libs/permission/Android.bp
index 0eeca54..929f067 100644
--- a/libs/permission/Android.bp
+++ b/libs/permission/Android.bp
@@ -16,6 +16,7 @@
double_loadable: true,
srcs: [
"aidl/android/content/AttributionSourceState.aidl",
+ "aidl/com/android/internal/app/IAppOpsCallback.aidl",
"aidl/android/permission/IPermissionChecker.aidl",
],
}
@@ -36,7 +37,6 @@
],
srcs: [
"AppOpsManager.cpp",
- "IAppOpsCallback.cpp",
"IAppOpsService.cpp",
"android/permission/PermissionChecker.cpp",
],
diff --git a/libs/permission/IAppOpsCallback.cpp b/libs/permission/IAppOpsCallback.cpp
deleted file mode 100644
index 2b3f462..0000000
--- a/libs/permission/IAppOpsCallback.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.
- */
-
-#define LOG_TAG "AppOpsCallback"
-
-#include <binder/IAppOpsCallback.h>
-
-#include <utils/Log.h>
-#include <binder/Parcel.h>
-#include <utils/String8.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------
-
-class BpAppOpsCallback : public BpInterface<IAppOpsCallback>
-{
-public:
- explicit BpAppOpsCallback(const sp<IBinder>& impl)
- : BpInterface<IAppOpsCallback>(impl)
- {
- }
-
- virtual void opChanged(int32_t op, const String16& packageName) {
- Parcel data, reply;
- data.writeInterfaceToken(IAppOpsCallback::getInterfaceDescriptor());
- data.writeInt32(op);
- data.writeString16(packageName);
- remote()->transact(OP_CHANGED_TRANSACTION, data, &reply, IBinder::FLAG_ONEWAY);
- }
-};
-
-IMPLEMENT_META_INTERFACE(AppOpsCallback, "com.android.internal.app.IAppOpsCallback")
-
-// ----------------------------------------------------------------------
-
-// NOLINTNEXTLINE(google-default-arguments)
-status_t BnAppOpsCallback::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch(code) {
- case OP_CHANGED_TRANSACTION: {
- CHECK_INTERFACE(IAppOpsCallback, data, reply);
- int32_t op = data.readInt32();
- String16 packageName;
- (void)data.readString16(&packageName);
- opChanged(op, packageName);
- return NO_ERROR;
- } break;
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-} // namespace android
diff --git a/libs/binder/trusty/ndk/include/android/llndk-versioning.h b/libs/permission/aidl/com/android/internal/app/IAppOpsCallback.aidl
similarity index 72%
copy from libs/binder/trusty/ndk/include/android/llndk-versioning.h
copy to libs/permission/aidl/com/android/internal/app/IAppOpsCallback.aidl
index e955a34..36b19df 100644
--- a/libs/binder/trusty/ndk/include/android/llndk-versioning.h
+++ b/libs/permission/aidl/com/android/internal/app/IAppOpsCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2024 The Android Open Source Project
+ * Copyright (C) 2025 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.
@@ -13,7 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#pragma once
-// TODO(b/349936395): set to true for Trusty
-#define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) (false)
+package com.android.internal.app;
+
+oneway interface IAppOpsCallback {
+ void opChanged(int op, int uid, String packageName, String persistentDeviceId);
+}
diff --git a/libs/permission/include/binder/AppOpsManager.h b/libs/permission/include/binder/AppOpsManager.h
index 243532b..a22c975 100644
--- a/libs/permission/include/binder/AppOpsManager.h
+++ b/libs/permission/include/binder/AppOpsManager.h
@@ -148,7 +148,10 @@
OP_BLUETOOTH_ADVERTISE = 114,
OP_RECORD_INCOMING_PHONE_AUDIO = 115,
OP_NEARBY_WIFI_DEVICES = 116,
- _NUM_OP = 117
+ // 116 - 154 omitted due to lack of use in native
+ OP_CONTROL_AUDIO = 154,
+ OP_CONTROL_AUDIO_PARTIAL = 155,
+ _NUM_OP = 156,
};
enum {
@@ -177,10 +180,10 @@
void finishOp(int32_t op, int32_t uid, const String16& callingPackage,
const std::optional<String16>& attributionTag);
void startWatchingMode(int32_t op, const String16& packageName,
- const sp<IAppOpsCallback>& callback);
+ const sp<com::android::internal::app::IAppOpsCallback>& callback);
void startWatchingMode(int32_t op, const String16& packageName, int32_t flags,
- const sp<IAppOpsCallback>& callback);
- void stopWatchingMode(const sp<IAppOpsCallback>& callback);
+ const sp<com::android::internal::app::IAppOpsCallback>& callback);
+ void stopWatchingMode(const sp<com::android::internal::app::IAppOpsCallback>& callback);
int32_t permissionToOpCode(const String16& permission);
void setCameraAudioRestriction(int32_t mode);
diff --git a/libs/permission/include/binder/IAppOpsCallback.h b/libs/permission/include/binder/IAppOpsCallback.h
deleted file mode 100644
index eb76f57..0000000
--- a/libs/permission/include/binder/IAppOpsCallback.h
+++ /dev/null
@@ -1,57 +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.
- */
-
-#pragma once
-
-#ifndef __ANDROID_VNDK__
-
-#include <binder/IInterface.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------
-
-class IAppOpsCallback : public IInterface
-{
-public:
- DECLARE_META_INTERFACE(AppOpsCallback)
-
- virtual void opChanged(int32_t op, const String16& packageName) = 0;
-
- enum {
- OP_CHANGED_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION
- };
-};
-
-// ----------------------------------------------------------------------
-
-class BnAppOpsCallback : public BnInterface<IAppOpsCallback>
-{
-public:
- // NOLINTNEXTLINE(google-default-arguments)
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------
-
-} // namespace android
-
-#else // __ANDROID_VNDK__
-#error "This header is not visible to vendors"
-#endif // __ANDROID_VNDK__
diff --git a/libs/permission/include/binder/IAppOpsService.h b/libs/permission/include/binder/IAppOpsService.h
index 918fcdb..1468fd9 100644
--- a/libs/permission/include/binder/IAppOpsService.h
+++ b/libs/permission/include/binder/IAppOpsService.h
@@ -16,7 +16,8 @@
#pragma once
-#include <binder/IAppOpsCallback.h>
+#include <com/android/internal/app/IAppOpsCallback.h>
+#include <com/android/internal/app/BnAppOpsCallback.h>
#include <binder/IInterface.h>
#include <optional>
@@ -27,6 +28,8 @@
namespace android {
+using IAppOpsCallback = ::com::android::internal::app::IAppOpsCallback;
+
// ----------------------------------------------------------------------
class IAppOpsService : public IInterface
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index d248ea0..7f207f0 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -105,6 +105,7 @@
"skia/filters/KawaseBlurDualFilter.cpp",
"skia/filters/KawaseBlurFilter.cpp",
"skia/filters/LinearEffect.cpp",
+ "skia/filters/LutShader.cpp",
"skia/filters/MouriMap.cpp",
"skia/filters/StretchShaderFactory.cpp",
"skia/filters/EdgeExtensionShaderFactory.cpp",
diff --git a/libs/renderengine/OWNERS b/libs/renderengine/OWNERS
index 17ab29f..e296283 100644
--- a/libs/renderengine/OWNERS
+++ b/libs/renderengine/OWNERS
@@ -7,4 +7,3 @@
lpy@google.com
nscobie@google.com
sallyqi@google.com
-scroggo@google.com
diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp
index 907590a..873fc67 100644
--- a/libs/renderengine/RenderEngine.cpp
+++ b/libs/renderengine/RenderEngine.cpp
@@ -107,16 +107,15 @@
return resultFuture;
}
-ftl::Future<FenceResult> RenderEngine::drawGainmap(
- const std::shared_ptr<ExternalTexture>& sdr, base::borrowed_fd&& sdrFence,
+ftl::Future<FenceResult> RenderEngine::tonemapAndDrawGainmap(
const std::shared_ptr<ExternalTexture>& hdr, base::borrowed_fd&& hdrFence,
- float hdrSdrRatio, ui::Dataspace dataspace,
+ float hdrSdrRatio, ui::Dataspace dataspace, const std::shared_ptr<ExternalTexture>& sdr,
const std::shared_ptr<ExternalTexture>& gainmap) {
const auto resultPromise = std::make_shared<std::promise<FenceResult>>();
std::future<FenceResult> resultFuture = resultPromise->get_future();
updateProtectedContext({}, {sdr.get(), hdr.get(), gainmap.get()});
- drawGainmapInternal(std::move(resultPromise), sdr, std::move(sdrFence), hdr,
- std::move(hdrFence), hdrSdrRatio, dataspace, gainmap);
+ tonemapAndDrawGainmapInternal(std::move(resultPromise), hdr, std::move(hdrFence), hdrSdrRatio,
+ dataspace, sdr, gainmap);
return resultFuture;
}
diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h
index 859ae8b..ecb16b2 100644
--- a/libs/renderengine/include/renderengine/LayerSettings.h
+++ b/libs/renderengine/include/renderengine/LayerSettings.h
@@ -16,6 +16,7 @@
#pragma once
+#include <gui/DisplayLuts.h>
#include <math/mat4.h>
#include <math/vec3.h>
#include <renderengine/ExternalTexture.h>
@@ -145,6 +146,8 @@
// If white point nits are unknown, then this layer is assumed to have the
// same luminance as the brightest layer in the scene.
float whitePointNits = -1.f;
+
+ std::shared_ptr<gui::DisplayLuts> luts;
};
// Keep in sync with custom comparison function in
@@ -187,7 +190,7 @@
lhs.blurRegionTransform == rhs.blurRegionTransform &&
lhs.stretchEffect == rhs.stretchEffect &&
lhs.edgeExtensionEffect == rhs.edgeExtensionEffect &&
- lhs.whitePointNits == rhs.whitePointNits;
+ lhs.whitePointNits == rhs.whitePointNits && lhs.luts == rhs.luts;
}
static inline void PrintTo(const Buffer& settings, ::std::ostream* os) {
@@ -298,6 +301,10 @@
*os << "\n .edgeExtensionEffect = " << settings.edgeExtensionEffect;
}
*os << "\n .whitePointNits = " << settings.whitePointNits;
+ if (settings.luts) {
+ *os << "\n .luts = ";
+ PrintTo(settings.luts, os);
+ }
*os << "\n}";
}
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index 0fd982e..c2dd4ae 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -38,6 +38,14 @@
#define PROPERTY_DEBUG_RENDERENGINE_BACKEND "debug.renderengine.backend"
/**
+ * Allows opting particular devices into an initial preview rollout of RenderEngine on Graphite.
+ *
+ * Only applicable within SurfaceFlinger, and if relevant aconfig flags are enabled.
+ */
+#define PROPERTY_DEBUG_RENDERENGINE_GRAPHITE_PREVIEW_OPTIN \
+ "debug.renderengine.graphite_preview_optin"
+
+/**
* Turns on recording of skia commands in SkiaGL version of the RE. This property
* defines number of milliseconds for the recording to take place. A non zero value
* turns on the recording.
@@ -209,12 +217,17 @@
const std::shared_ptr<ExternalTexture>& buffer,
base::unique_fd&& bufferFence);
- virtual ftl::Future<FenceResult> drawGainmap(const std::shared_ptr<ExternalTexture>& sdr,
- base::borrowed_fd&& sdrFence,
- const std::shared_ptr<ExternalTexture>& hdr,
- base::borrowed_fd&& hdrFence, float hdrSdrRatio,
- ui::Dataspace dataspace,
- const std::shared_ptr<ExternalTexture>& gainmap);
+ // Tonemaps an HDR input image and draws an SDR rendition, plus a gainmap
+ // describing how to recover the HDR image.
+ //
+ // The HDR input image is ALWAYS encoded with an sRGB transfer function and
+ // is a floating point format. Accordingly, the hdrSdrRatio describes the
+ // max luminance in the HDR input image above SDR, and the dataspace
+ // describes the input primaries.
+ virtual ftl::Future<FenceResult> tonemapAndDrawGainmap(
+ const std::shared_ptr<ExternalTexture>& hdr, base::borrowed_fd&& hdrFence,
+ float hdrSdrRatio, ui::Dataspace dataspace, const std::shared_ptr<ExternalTexture>& sdr,
+ const std::shared_ptr<ExternalTexture>& gainmap);
// Clean-up method that should be called on the main thread after the
// drawFence returned by drawLayers fires. This method will free up
@@ -302,11 +315,10 @@
const DisplaySettings& display, const std::vector<LayerSettings>& layers,
const std::shared_ptr<ExternalTexture>& buffer, base::unique_fd&& bufferFence) = 0;
- virtual void drawGainmapInternal(
+ virtual void tonemapAndDrawGainmapInternal(
const std::shared_ptr<std::promise<FenceResult>>&& resultPromise,
- const std::shared_ptr<ExternalTexture>& sdr, base::borrowed_fd&& sdrFence,
const std::shared_ptr<ExternalTexture>& hdr, base::borrowed_fd&& hdrFence,
- float hdrSdrRatio, ui::Dataspace dataspace,
+ float hdrSdrRatio, ui::Dataspace dataspace, const std::shared_ptr<ExternalTexture>& sdr,
const std::shared_ptr<ExternalTexture>& gainmap) = 0;
};
diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h
index fb8331d..c42e403 100644
--- a/libs/renderengine/include/renderengine/mock/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h
@@ -46,17 +46,16 @@
ftl::Future<FenceResult>(const DisplaySettings&, const std::vector<LayerSettings>&,
const std::shared_ptr<ExternalTexture>&,
base::unique_fd&&));
- MOCK_METHOD7(drawGainmap,
+ MOCK_METHOD6(tonemapAndDrawGainmap,
ftl::Future<FenceResult>(const std::shared_ptr<ExternalTexture>&,
- base::borrowed_fd&&,
- const std::shared_ptr<ExternalTexture>&,
base::borrowed_fd&&, float, ui::Dataspace,
+ const std::shared_ptr<ExternalTexture>&,
const std::shared_ptr<ExternalTexture>&));
- MOCK_METHOD8(drawGainmapInternal,
+ MOCK_METHOD7(tonemapAndDrawGainmapInternal,
void(const std::shared_ptr<std::promise<FenceResult>>&&,
- const std::shared_ptr<ExternalTexture>&, base::borrowed_fd&&,
const std::shared_ptr<ExternalTexture>&, base::borrowed_fd&&, float,
- ui::Dataspace, const std::shared_ptr<ExternalTexture>&));
+ ui::Dataspace, const std::shared_ptr<ExternalTexture>&,
+ const std::shared_ptr<ExternalTexture>&));
MOCK_METHOD5(drawLayersInternal,
void(const std::shared_ptr<std::promise<FenceResult>>&&, const DisplaySettings&,
const std::vector<LayerSettings>&, const std::shared_ptr<ExternalTexture>&,
diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp
index 57041ee..9f64d2c 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -14,6 +14,9 @@
* limitations under the License.
*/
#include "Cache.h"
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
#include "AutoBackendTexture.h"
#include "SkiaRenderEngine.h"
#include "android-base/unique_fd.h"
@@ -28,6 +31,7 @@
#include "utils/Timers.h"
#include <com_android_graphics_libgui_flags.h>
+#include <common/trace.h>
namespace android::renderengine::skia {
@@ -337,17 +341,17 @@
LayerSettings layer{
.geometry =
Geometry{
+ .boundaries = rect,
// The position transform doesn't matter when the reduced shader mode
// in in effect. A matrix transform stage is always included.
.positionTransform = mat4(),
- .boundaries = rect,
- .roundedCornersCrop = rect,
.roundedCornersRadius = {0.f, 0.f},
+ .roundedCornersCrop = rect,
},
.source = PixelSource{.buffer = Buffer{.buffer = srcTexture,
- .maxLuminanceNits = 1000.f,
.usePremultipliedAlpha = true,
- .isOpaque = true}},
+ .isOpaque = true,
+ .maxLuminanceNits = 1000.f}},
.alpha = 1.f,
.sourceDataspace = kDestDataSpace,
};
@@ -370,16 +374,16 @@
LayerSettings layer{
.geometry =
Geometry{
- .positionTransform = mat4(),
.boundaries = rect,
+ .positionTransform = mat4(),
.roundedCornersCrop = rect,
},
.source = PixelSource{.buffer =
Buffer{
.buffer = srcTexture,
- .maxLuminanceNits = 1000.f,
.usePremultipliedAlpha = true,
.isOpaque = false,
+ .maxLuminanceNits = 1000.f,
}},
.sourceDataspace = kDestDataSpace,
};
@@ -421,17 +425,17 @@
LayerSettings layer{
.geometry =
Geometry{
- .positionTransform = mat4(),
.boundaries = boundary,
- .roundedCornersCrop = rect,
+ .positionTransform = mat4(),
.roundedCornersRadius = {27.f, 27.f},
+ .roundedCornersCrop = rect,
},
.source = PixelSource{.buffer =
Buffer{
.buffer = srcTexture,
- .maxLuminanceNits = 1000.f,
.usePremultipliedAlpha = true,
.isOpaque = false,
+ .maxLuminanceNits = 1000.f,
}},
.alpha = 1.f,
.sourceDataspace = kDestDataSpace,
@@ -489,17 +493,17 @@
LayerSettings layer{
.geometry =
Geometry{
+ .boundaries = rect,
// The position transform doesn't matter when the reduced shader mode
// in in effect. A matrix transform stage is always included.
.positionTransform = mat4(),
- .boundaries = rect,
- .roundedCornersCrop = rect,
.roundedCornersRadius = {0.f, 0.f},
+ .roundedCornersCrop = rect,
},
.source = PixelSource{.buffer = Buffer{.buffer = srcTexture,
- .maxLuminanceNits = 1000.f,
.usePremultipliedAlpha = true,
- .isOpaque = true}},
+ .isOpaque = true,
+ .maxLuminanceNits = 1000.f}},
.alpha = 1.f,
.sourceDataspace = kBT2020DataSpace,
};
@@ -527,17 +531,17 @@
LayerSettings layer{
.geometry =
Geometry{
- .positionTransform = kScaleAsymmetric,
.boundaries = boundary,
- .roundedCornersCrop = rect,
+ .positionTransform = kScaleAsymmetric,
.roundedCornersRadius = {64.1f, 64.1f},
+ .roundedCornersCrop = rect,
},
.source = PixelSource{.buffer =
Buffer{
.buffer = srcTexture,
- .maxLuminanceNits = 1000.f,
.usePremultipliedAlpha = true,
.isOpaque = true,
+ .maxLuminanceNits = 1000.f,
}},
.alpha = 0.5f,
.sourceDataspace = kBT2020DataSpace,
@@ -556,17 +560,17 @@
LayerSettings layer{
.geometry =
Geometry{
+ .boundaries = rect,
// The position transform doesn't matter when the reduced shader mode
// in in effect. A matrix transform stage is always included.
.positionTransform = mat4(),
- .boundaries = rect,
- .roundedCornersCrop = rect,
.roundedCornersRadius = {50.f, 50.f},
+ .roundedCornersCrop = rect,
},
.source = PixelSource{.buffer = Buffer{.buffer = srcTexture,
- .maxLuminanceNits = 1000.f,
.usePremultipliedAlpha = true,
- .isOpaque = true}},
+ .isOpaque = true,
+ .maxLuminanceNits = 1000.f}},
.alpha = 0.5f,
.sourceDataspace = kExtendedHdrDataSpce,
};
@@ -594,17 +598,17 @@
LayerSettings layer{
.geometry =
Geometry{
+ .boundaries = rect,
// The position transform doesn't matter when the reduced shader mode
// in in effect. A matrix transform stage is always included.
.positionTransform = mat4(),
- .boundaries = rect,
- .roundedCornersCrop = rect,
.roundedCornersRadius = {50.f, 50.f},
+ .roundedCornersCrop = rect,
},
.source = PixelSource{.buffer = Buffer{.buffer = srcTexture,
- .maxLuminanceNits = 1000.f,
.usePremultipliedAlpha = true,
- .isOpaque = false}},
+ .isOpaque = false,
+ .maxLuminanceNits = 1000.f}},
.alpha = 0.5f,
.sourceDataspace = kOtherDataSpace,
};
@@ -659,6 +663,7 @@
// in external/skia/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
// gPrintSKSL = true
void Cache::primeShaderCache(SkiaRenderEngine* renderengine, PrimeCacheConfig config) {
+ SFTRACE_CALL();
const int previousCount = renderengine->reportShadersCompiled();
if (previousCount) {
ALOGD("%d Shaders already compiled before Cache::primeShaderCache ran\n", previousCount);
@@ -724,24 +729,29 @@
impl::ExternalTexture::Usage::WRITEABLE);
if (config.cacheHolePunchLayer) {
+ SFTRACE_NAME("cacheHolePunchLayer");
drawHolePunchLayer(renderengine, display, dstTexture);
}
if (config.cacheSolidLayers) {
+ SFTRACE_NAME("cacheSolidLayers");
drawSolidLayers(renderengine, display, dstTexture);
drawSolidLayers(renderengine, p3Display, dstTexture);
}
if (config.cacheSolidDimmedLayers) {
+ SFTRACE_NAME("cacheSolidDimmedLayers");
drawSolidDimmedLayers(renderengine, display, dstTexture);
}
if (config.cacheShadowLayers) {
+ SFTRACE_NAME("cacheShadowLayers");
drawShadowLayers(renderengine, display, srcTexture);
drawShadowLayers(renderengine, p3Display, srcTexture);
}
if (renderengine->supportsBackgroundBlur()) {
+ SFTRACE_NAME("supportsBackgroundBlur");
drawBlurLayers(renderengine, display, dstTexture);
}
@@ -776,32 +786,38 @@
for (auto texture : textures) {
if (config.cacheImageLayers) {
+ SFTRACE_NAME("cacheImageLayers");
drawImageLayers(renderengine, display, dstTexture, texture);
}
if (config.cacheImageDimmedLayers) {
+ SFTRACE_NAME("cacheImageDimmedLayers");
drawImageDimmedLayers(renderengine, display, dstTexture, texture);
drawImageDimmedLayers(renderengine, p3Display, dstTexture, texture);
drawImageDimmedLayers(renderengine, bt2020Display, dstTexture, texture);
}
if (config.cacheClippedLayers) {
+ SFTRACE_NAME("cacheClippedLayers");
// Draw layers for b/185569240.
drawClippedLayers(renderengine, display, dstTexture, texture);
}
if (com::android::graphics::libgui::flags::edge_extension_shader() &&
config.cacheEdgeExtension) {
+ SFTRACE_NAME("cacheEdgeExtension");
drawEdgeExtensionLayers(renderengine, display, dstTexture, texture);
drawEdgeExtensionLayers(renderengine, p3Display, dstTexture, texture);
}
}
if (config.cachePIPImageLayers) {
+ SFTRACE_NAME("cachePIPImageLayers");
drawPIPImageLayer(renderengine, display, dstTexture, externalTexture);
}
if (config.cacheTransparentImageDimmedLayers) {
+ SFTRACE_NAME("cacheTransparentImageDimmedLayers");
drawTransparentImageDimmedLayers(renderengine, bt2020Display, dstTexture,
externalTexture);
drawTransparentImageDimmedLayers(renderengine, display, dstTexture, externalTexture);
@@ -811,10 +827,12 @@
}
if (config.cacheClippedDimmedImageLayers) {
+ SFTRACE_NAME("cacheClippedDimmedImageLayers");
drawClippedDimmedImageLayers(renderengine, bt2020Display, dstTexture, externalTexture);
}
if (config.cacheUltraHDR) {
+ SFTRACE_NAME("cacheUltraHDR");
drawBT2020ClippedImageLayers(renderengine, bt2020Display, dstTexture, externalTexture);
drawBT2020ImageLayers(renderengine, bt2020Display, dstTexture, externalTexture);
@@ -833,7 +851,10 @@
};
auto layers = std::vector<LayerSettings>{layer};
// call get() to make it synchronous
- renderengine->drawLayers(display, layers, dstTexture, base::unique_fd()).get();
+ {
+ SFTRACE_NAME("finalLayer");
+ renderengine->drawLayers(display, layers, dstTexture, base::unique_fd()).get();
+ }
const nsecs_t timeAfter = systemTime();
const float compileTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6;
diff --git a/libs/renderengine/skia/GaneshVkRenderEngine.cpp b/libs/renderengine/skia/GaneshVkRenderEngine.cpp
index a3a43e2..cc73f40 100644
--- a/libs/renderengine/skia/GaneshVkRenderEngine.cpp
+++ b/libs/renderengine/skia/GaneshVkRenderEngine.cpp
@@ -21,12 +21,15 @@
#include <include/gpu/ganesh/vk/GrVkBackendSemaphore.h>
+#include <android-base/stringprintf.h>
#include <common/trace.h>
#include <log/log_main.h>
#include <sync/sync.h>
namespace android::renderengine::skia {
+using base::StringAppendF;
+
std::unique_ptr<GaneshVkRenderEngine> GaneshVkRenderEngine::create(
const RenderEngineCreationArgs& args) {
std::unique_ptr<GaneshVkRenderEngine> engine(new GaneshVkRenderEngine(args));
@@ -111,4 +114,9 @@
return res;
}
+void GaneshVkRenderEngine::appendBackendSpecificInfoToDump(std::string& result) {
+ StringAppendF(&result, "\n ------------RE Vulkan (Ganesh)----------\n");
+ SkiaVkRenderEngine::appendBackendSpecificInfoToDump(result);
+}
+
} // namespace android::renderengine::skia
diff --git a/libs/renderengine/skia/GaneshVkRenderEngine.h b/libs/renderengine/skia/GaneshVkRenderEngine.h
index e6123c2..ba17f71 100644
--- a/libs/renderengine/skia/GaneshVkRenderEngine.h
+++ b/libs/renderengine/skia/GaneshVkRenderEngine.h
@@ -28,6 +28,7 @@
std::unique_ptr<SkiaGpuContext> createContext(VulkanInterface& vulkanInterface) override;
void waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) override;
base::unique_fd flushAndSubmit(SkiaGpuContext* context, sk_sp<SkSurface> dstSurface) override;
+ void appendBackendSpecificInfoToDump(std::string& result) override;
private:
GaneshVkRenderEngine(const RenderEngineCreationArgs& args) : SkiaVkRenderEngine(args) {}
diff --git a/libs/renderengine/skia/GraphiteVkRenderEngine.cpp b/libs/renderengine/skia/GraphiteVkRenderEngine.cpp
index 390ad6e..a9332fa 100644
--- a/libs/renderengine/skia/GraphiteVkRenderEngine.cpp
+++ b/libs/renderengine/skia/GraphiteVkRenderEngine.cpp
@@ -25,6 +25,7 @@
#include <include/gpu/graphite/Recording.h>
#include <include/gpu/graphite/vk/VulkanGraphiteTypes.h>
+#include <android-base/stringprintf.h>
#include <log/log_main.h>
#include <sync/sync.h>
@@ -33,6 +34,8 @@
namespace android::renderengine::skia {
+using base::StringAppendF;
+
std::unique_ptr<GraphiteVkRenderEngine> GraphiteVkRenderEngine::create(
const RenderEngineCreationArgs& args) {
std::unique_ptr<GraphiteVkRenderEngine> engine(new GraphiteVkRenderEngine(args));
@@ -139,4 +142,9 @@
return drawFenceFd;
}
+void GraphiteVkRenderEngine::appendBackendSpecificInfoToDump(std::string& result) {
+ StringAppendF(&result, "\n ------------RE Vulkan (Graphite)----------\n");
+ SkiaVkRenderEngine::appendBackendSpecificInfoToDump(result);
+}
+
} // namespace android::renderengine::skia
diff --git a/libs/renderengine/skia/GraphiteVkRenderEngine.h b/libs/renderengine/skia/GraphiteVkRenderEngine.h
index cf24a3b..33a47f1 100644
--- a/libs/renderengine/skia/GraphiteVkRenderEngine.h
+++ b/libs/renderengine/skia/GraphiteVkRenderEngine.h
@@ -30,6 +30,7 @@
std::unique_ptr<SkiaGpuContext> createContext(VulkanInterface& vulkanInterface) override;
void waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) override;
base::unique_fd flushAndSubmit(SkiaGpuContext* context, sk_sp<SkSurface> dstSurface) override;
+ void appendBackendSpecificInfoToDump(std::string& result) override;
private:
GraphiteVkRenderEngine(const RenderEngineCreationArgs& args) : SkiaVkRenderEngine(args) {}
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 4ef7d5b..ddae9fc 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -541,7 +541,7 @@
void SkiaGLRenderEngine::appendBackendSpecificInfoToDump(std::string& result) {
const GLExtensions& extensions = GLExtensions::getInstance();
- StringAppendF(&result, "\n ------------RE GLES------------\n");
+ StringAppendF(&result, "\n ------------RE GLES (Ganesh)------------\n");
StringAppendF(&result, "EGL implementation : %s\n", extensions.getEGLVersion());
StringAppendF(&result, "%s\n", extensions.getEGLExtensions());
StringAppendF(&result, "GLES: %s, %s, %s\n", extensions.getVendor(), extensions.getRenderer(),
diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp
index ec9d3ef..5f2d1b1 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaRenderEngine.cpp
@@ -543,6 +543,21 @@
}
}
+ if (graphicBuffer && parameters.layer.luts) {
+ const bool dimInLinearSpace = parameters.display.dimmingStage !=
+ aidl::android::hardware::graphics::composer3::DimmingStage::GAMMA_OETF;
+ const ui::Dataspace runtimeEffectDataspace = !dimInLinearSpace
+ ? static_cast<ui::Dataspace>(
+ (parameters.outputDataSpace & ui::Dataspace::STANDARD_MASK) |
+ ui::Dataspace::TRANSFER_GAMMA2_2 |
+ (parameters.outputDataSpace & ui::Dataspace::RANGE_MASK))
+ : parameters.outputDataSpace;
+
+ shader = mLutShader.lutShader(shader, parameters.layer.luts,
+ parameters.layer.sourceDataspace,
+ toSkColorSpace(runtimeEffectDataspace));
+ }
+
if (parameters.requiresLinearEffect) {
const auto format = targetBuffer != nullptr
? std::optional<ui::PixelFormat>(
@@ -561,14 +576,14 @@
if (usingLocalTonemap) {
const float inputRatio =
hdrType == HdrRenderType::GENERIC_HDR ? 1.0f : parameters.layerDimmingRatio;
- static MouriMap kMapper;
- shader = kMapper.mouriMap(getActiveContext(), shader, inputRatio,
- parameters.display.targetHdrSdrRatio);
+ shader = localTonemap(shader, inputRatio, parameters.display.targetHdrSdrRatio);
}
// disable tonemapping if we already locally tonemapped
- auto inputDataspace =
- usingLocalTonemap ? parameters.outputDataSpace : parameters.layer.sourceDataspace;
+ // skip tonemapping if the luts is in use
+ auto inputDataspace = usingLocalTonemap || (graphicBuffer && parameters.layer.luts)
+ ? parameters.outputDataSpace
+ : parameters.layer.sourceDataspace;
auto effect =
shaders::LinearEffect{.inputDataspace = inputDataspace,
.outputDataspace = parameters.outputDataSpace,
@@ -602,6 +617,12 @@
return shader;
}
+sk_sp<SkShader> SkiaRenderEngine::localTonemap(sk_sp<SkShader> shader, float inputMultiplier,
+ float targetHdrSdrRatio) {
+ static MouriMap kMapper;
+ return kMapper.mouriMap(getActiveContext(), shader, inputMultiplier, targetHdrSdrRatio);
+}
+
void SkiaRenderEngine::initCanvas(SkCanvas* canvas, const DisplaySettings& display) {
if (CC_UNLIKELY(mCapture->isCaptureRunning())) {
// Record display settings when capture is running.
@@ -817,8 +838,7 @@
LOG_ALWAYS_FATAL_IF(activeSurface == dstSurface);
LOG_ALWAYS_FATAL_IF(canvas == dstCanvas);
- // save a snapshot of the activeSurface to use as input to the blur shaders
- blurInput = activeSurface->makeImageSnapshot();
+ blurInput = activeSurface->makeTemporaryImage();
// blit the offscreen framebuffer into the destination AHB. This ensures that
// even if the blurred image does not cover the screen (for example, during
@@ -832,12 +852,9 @@
dstCanvas->drawAnnotation(SkRect::Make(dstCanvas->imageInfo().dimensions()),
String8::format("SurfaceID|%" PRId64, id).c_str(),
nullptr);
- dstCanvas->drawImage(blurInput, 0, 0, SkSamplingOptions(), &paint);
- } else {
- activeSurface->draw(dstCanvas, 0, 0, SkSamplingOptions(), &paint);
}
+ dstCanvas->drawImage(blurInput, 0, 0, SkSamplingOptions(), &paint);
}
-
// assign dstCanvas to canvas and ensure that the canvas state is up to date
canvas = dstCanvas;
surfaceAutoSaveRestore.replace(canvas);
@@ -870,12 +887,6 @@
if (mBlurFilter && layerHasBlur(layer, ctModifiesAlpha)) {
std::unordered_map<uint32_t, sk_sp<SkImage>> cachedBlurs;
- // if multiple layers have blur, then we need to take a snapshot now because
- // only the lowest layer will have blurImage populated earlier
- if (!blurInput) {
- blurInput = activeSurface->makeImageSnapshot();
- }
-
// rect to be blurred in the coordinate space of blurInput
SkRect blurRect = canvas->getTotalMatrix().mapRect(bounds.rect());
@@ -899,6 +910,29 @@
// TODO(b/182216890): Filter out empty layers earlier
if (blurRect.width() > 0 && blurRect.height() > 0) {
+ // if multiple layers have blur, then we need to take a snapshot now because
+ // only the lowest layer will have blurImage populated earlier
+ if (!blurInput) {
+ bool requiresCrossFadeWithBlurInput = false;
+ if (layer.backgroundBlurRadius > 0 &&
+ layer.backgroundBlurRadius < mBlurFilter->getMaxCrossFadeRadius()) {
+ requiresCrossFadeWithBlurInput = true;
+ }
+ for (auto region : layer.blurRegions) {
+ if (region.blurRadius < mBlurFilter->getMaxCrossFadeRadius()) {
+ requiresCrossFadeWithBlurInput = true;
+ }
+ }
+ if (requiresCrossFadeWithBlurInput) {
+ // If we require cross fading with the blur input, we need to make sure we
+ // make a copy of the surface to the image since we will be writing to the
+ // surface while sampling the blurInput.
+ blurInput = activeSurface->makeImageSnapshot();
+ } else {
+ blurInput = activeSurface->makeTemporaryImage();
+ }
+ }
+
if (layer.backgroundBlurRadius > 0) {
SFTRACE_NAME("BackgroundBlur");
auto blurredImage = mBlurFilter->generate(context, layer.backgroundBlurRadius,
@@ -1001,7 +1035,7 @@
const auto& item = layer.source.buffer;
auto imageTextureRef = getOrCreateBackendTexture(item.buffer->getBuffer(), false);
- // if the layer's buffer has a fence, then we must must respect the fence prior to using
+ // if the layer's buffer has a fence, then we must respect the fence prior to using
// the buffer.
if (layer.source.buffer.fence != nullptr) {
waitFence(context, layer.source.buffer.fence->get());
@@ -1204,44 +1238,58 @@
resultPromise->set_value(std::move(drawFence));
}
-void SkiaRenderEngine::drawGainmapInternal(
+void SkiaRenderEngine::tonemapAndDrawGainmapInternal(
const std::shared_ptr<std::promise<FenceResult>>&& resultPromise,
- const std::shared_ptr<ExternalTexture>& sdr, base::borrowed_fd&& sdrFence,
const std::shared_ptr<ExternalTexture>& hdr, base::borrowed_fd&& hdrFence,
- float hdrSdrRatio, ui::Dataspace dataspace,
+ float hdrSdrRatio, ui::Dataspace dataspace, const std::shared_ptr<ExternalTexture>& sdr,
const std::shared_ptr<ExternalTexture>& gainmap) {
std::lock_guard<std::mutex> lock(mRenderingMutex);
auto context = getActiveContext();
- auto surfaceTextureRef = getOrCreateBackendTexture(gainmap->getBuffer(), true);
- sk_sp<SkSurface> dstSurface =
- surfaceTextureRef->getOrCreateSurface(ui::Dataspace::V0_SRGB_LINEAR);
+ auto gainmapTextureRef = getOrCreateBackendTexture(gainmap->getBuffer(), true);
+ sk_sp<SkSurface> gainmapSurface =
+ gainmapTextureRef->getOrCreateSurface(ui::Dataspace::V0_SRGB_LINEAR);
- waitFence(context, sdrFence);
- const auto sdrTextureRef = getOrCreateBackendTexture(sdr->getBuffer(), false);
- const auto sdrImage = sdrTextureRef->makeImage(dataspace, kPremul_SkAlphaType);
- const auto sdrShader =
- sdrImage->makeShader(SkTileMode::kClamp, SkTileMode::kClamp,
- SkSamplingOptions({SkFilterMode::kLinear, SkMipmapMode::kNone}),
- nullptr);
+ auto sdrTextureRef = getOrCreateBackendTexture(sdr->getBuffer(), true);
+ sk_sp<SkSurface> sdrSurface = sdrTextureRef->getOrCreateSurface(dataspace);
+
waitFence(context, hdrFence);
const auto hdrTextureRef = getOrCreateBackendTexture(hdr->getBuffer(), false);
const auto hdrImage = hdrTextureRef->makeImage(dataspace, kPremul_SkAlphaType);
const auto hdrShader =
hdrImage->makeShader(SkTileMode::kClamp, SkTileMode::kClamp,
- SkSamplingOptions({SkFilterMode::kLinear, SkMipmapMode::kNone}),
+ SkSamplingOptions({SkFilterMode::kNearest, SkMipmapMode::kNone}),
nullptr);
+ const auto tonemappedShader = localTonemap(hdrShader, 1.0f, 1.0f);
+
static GainmapFactory kGainmapFactory;
- const auto gainmapShader = kGainmapFactory.createSkShader(sdrShader, hdrShader, hdrSdrRatio);
+ const auto gainmapShader =
+ kGainmapFactory.createSkShader(tonemappedShader, hdrShader, hdrSdrRatio);
- const auto canvas = dstSurface->getCanvas();
- SkPaint paint;
- paint.setShader(gainmapShader);
- paint.setBlendMode(SkBlendMode::kSrc);
- canvas->drawPaint(paint);
+ sp<Fence> drawFence;
- auto drawFence = sp<Fence>::make(flushAndSubmit(context, dstSurface));
- trace(drawFence);
+ {
+ const auto canvas = sdrSurface->getCanvas();
+ SkPaint paint;
+ paint.setShader(tonemappedShader);
+ paint.setBlendMode(SkBlendMode::kSrc);
+ canvas->drawPaint(paint);
+
+ drawFence = sp<Fence>::make(flushAndSubmit(context, sdrSurface));
+ trace(drawFence);
+ }
+
+ {
+ const auto canvas = gainmapSurface->getCanvas();
+ SkPaint paint;
+ paint.setShader(gainmapShader);
+ paint.setBlendMode(SkBlendMode::kSrc);
+ canvas->drawPaint(paint);
+
+ auto gmFence = sp<Fence>::make(flushAndSubmit(context, gainmapSurface));
+ trace(gmFence);
+ drawFence = Fence::merge("gm-ss", drawFence, gmFence);
+ }
resultPromise->set_value(std::move(drawFence));
}
diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h
index b5f8898..92b7af9 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.h
+++ b/libs/renderengine/skia/SkiaRenderEngine.h
@@ -39,6 +39,7 @@
#include "filters/BlurFilter.h"
#include "filters/EdgeExtensionShaderFactory.h"
#include "filters/LinearEffect.h"
+#include "filters/LutShader.h"
#include "filters/StretchShaderFactory.h"
class SkData;
@@ -142,13 +143,11 @@
const std::vector<LayerSettings>& layers,
const std::shared_ptr<ExternalTexture>& buffer,
base::unique_fd&& bufferFence) override final;
- void drawGainmapInternal(const std::shared_ptr<std::promise<FenceResult>>&& resultPromise,
- const std::shared_ptr<ExternalTexture>& sdr,
- base::borrowed_fd&& sdrFence,
- const std::shared_ptr<ExternalTexture>& hdr,
- base::borrowed_fd&& hdrFence, float hdrSdrRatio,
- ui::Dataspace dataspace,
- const std::shared_ptr<ExternalTexture>& gainmap) override final;
+ void tonemapAndDrawGainmapInternal(
+ const std::shared_ptr<std::promise<FenceResult>>&& resultPromise,
+ const std::shared_ptr<ExternalTexture>& hdr, base::borrowed_fd&& hdrFence,
+ float hdrSdrRatio, ui::Dataspace dataspace, const std::shared_ptr<ExternalTexture>& sdr,
+ const std::shared_ptr<ExternalTexture>& gainmap) override final;
void dump(std::string& result) override final;
@@ -167,6 +166,8 @@
};
sk_sp<SkShader> createRuntimeEffectShader(const RuntimeEffectShaderParameters&);
+ sk_sp<SkShader> localTonemap(sk_sp<SkShader>, float inputMultiplier, float targetHdrSdrRatio);
+
const PixelFormat mDefaultPixelFormat;
// Identifier used for various mappings of layers to various
@@ -184,6 +185,7 @@
StretchShaderFactory mStretchShaderFactory;
EdgeExtensionShaderFactory mEdgeExtensionShaderFactory;
+ LutShader mLutShader;
sp<Fence> mLastDrawFence;
BlurFilter* mBlurFilter = nullptr;
diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.cpp b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
index 677a2b6..177abe6 100644
--- a/libs/renderengine/skia/SkiaVkRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
@@ -169,24 +169,26 @@
}
void SkiaVkRenderEngine::appendBackendSpecificInfoToDump(std::string& result) {
- StringAppendF(&result, "\n ------------RE Vulkan----------\n");
- StringAppendF(&result, "\n Vulkan device initialized: %d\n", sVulkanInterface.isInitialized());
- StringAppendF(&result, "\n Vulkan protected device initialized: %d\n",
+ // Subclasses will prepend a backend-specific name / section header
+ StringAppendF(&result, "Vulkan device initialized: %d\n", sVulkanInterface.isInitialized());
+ StringAppendF(&result, "Vulkan protected device initialized: %d\n",
sProtectedContentVulkanInterface.isInitialized());
if (!sVulkanInterface.isInitialized()) {
return;
}
- StringAppendF(&result, "\n Instance extensions:\n");
+ StringAppendF(&result, "Instance extensions: [\n");
for (const auto& name : sVulkanInterface.getInstanceExtensionNames()) {
- StringAppendF(&result, "\n %s\n", name.c_str());
+ StringAppendF(&result, " %s\n", name.c_str());
}
+ StringAppendF(&result, "]\n");
- StringAppendF(&result, "\n Device extensions:\n");
+ StringAppendF(&result, "Device extensions: [\n");
for (const auto& name : sVulkanInterface.getDeviceExtensionNames()) {
- StringAppendF(&result, "\n %s\n", name.c_str());
+ StringAppendF(&result, " %s\n", name.c_str());
}
+ StringAppendF(&result, "]\n");
}
} // namespace skia
diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.h b/libs/renderengine/skia/SkiaVkRenderEngine.h
index d2bb3d5..88b04df 100644
--- a/libs/renderengine/skia/SkiaVkRenderEngine.h
+++ b/libs/renderengine/skia/SkiaVkRenderEngine.h
@@ -81,7 +81,7 @@
SkiaRenderEngine::Contexts createContexts() override;
bool supportsProtectedContentImpl() const override;
bool useProtectedContextImpl(GrProtected isProtected) override;
- void appendBackendSpecificInfoToDump(std::string& result) override;
+ virtual void appendBackendSpecificInfoToDump(std::string& result) override;
// TODO: b/300533018 - refactor this to be non-static
static VulkanInterface& getVulkanInterface(bool protectedContext);
diff --git a/libs/renderengine/skia/VulkanInterface.cpp b/libs/renderengine/skia/VulkanInterface.cpp
index 37b69f6..7331bbc 100644
--- a/libs/renderengine/skia/VulkanInterface.cpp
+++ b/libs/renderengine/skia/VulkanInterface.cpp
@@ -204,10 +204,10 @@
BAIL("[%s] null", #expr); \
}
-#define VK_CHECK(expr) \
- if ((expr) != VK_SUCCESS) { \
- BAIL("[%s] failed. err = %d", #expr, expr); \
- return; \
+#define VK_CHECK(expr) \
+ if (VkResult result = (expr); result != VK_SUCCESS) { \
+ BAIL("[%s] failed. err = %d", #expr, result); \
+ return; \
}
#define VK_GET_PROC(F) \
diff --git a/libs/renderengine/skia/compat/GraphiteGpuContext.cpp b/libs/renderengine/skia/compat/GraphiteGpuContext.cpp
index 69f5832..7a72d09 100644
--- a/libs/renderengine/skia/compat/GraphiteGpuContext.cpp
+++ b/libs/renderengine/skia/compat/GraphiteGpuContext.cpp
@@ -110,8 +110,40 @@
return mContext->isDeviceLost();
}
+void GraphiteGpuContext::setResourceCacheLimit(size_t maxResourceBytes) {
+ // Graphite has a separate budget for its Context and its Recorder. For now the majority of
+ // memory that Graphite will allocate will be on the Recorder and minimal amount on the Context.
+ // The main allocations on the Context are MSAA buffers (not often, if ever used in
+ // RenderEngine) and stencil buffers. However, both of these should be "memoryless" in Vulkan on
+ // tiled GPUs, so they don't actually use GPU memory. However, in Vulkan there are scenarios
+ // where Vulkan could end up using real memory for them. Skia will regularly query the device to
+ // get the real memory usage and update the budgeted appropriately. Though for all real usage
+ // patterns we don't expect to ever trigger the device to allocate real memory.
+ //
+ // Therefore, we set the full maxResourceBytes budget on the Recorder. However, in the rare
+ // chance that the devcies does allocate real memory we don't want to immediately kill device
+ // performance by constantly trashing allocations on the Context. Thus we set the Context's
+ // budget to be 50% of the total budget to make sure we allow the MSAA or Stencil buffers to be
+ // allocated in Skia and not immediately discarded. But even with this extra 50% budget, as
+ // described above, this shouldn't result in actual GPU memory usage.
+ //
+ // TODO: We will need to revise this strategy for GLES which does not have the same memoryless
+ // textures.
+ // TODO: Work in Graphite has started to move a lot more of its scratch resources to be owned
+ // by the Context and not on Recorders. This will mean most memory is actually owned by the
+ // Context and thus the budgeting here will need to be updated.
+ mContext->setMaxBudgetedBytes(maxResourceBytes / 2);
+ mRecorder->setMaxBudgetedBytes(maxResourceBytes);
+}
+
+void GraphiteGpuContext::purgeUnlockedScratchResources() {
+ mContext->freeGpuResources();
+ mRecorder->freeGpuResources();
+}
+
void GraphiteGpuContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
mContext->dumpMemoryStatistics(traceMemoryDump);
+ mRecorder->dumpMemoryStatistics(traceMemoryDump);
}
} // namespace android::renderengine::skia
diff --git a/libs/renderengine/skia/compat/GraphiteGpuContext.h b/libs/renderengine/skia/compat/GraphiteGpuContext.h
index 413817f..57da796 100644
--- a/libs/renderengine/skia/compat/GraphiteGpuContext.h
+++ b/libs/renderengine/skia/compat/GraphiteGpuContext.h
@@ -39,16 +39,10 @@
size_t getMaxRenderTargetSize() const override;
size_t getMaxTextureSize() const override;
bool isAbandonedOrDeviceLost() override;
- // No-op (large resources like textures, surfaces, images, etc. created by clients don't count
- // towards Graphite's internal caching budgets, so adjusting its limits based on display change
- // events should be unnecessary. Additionally, Graphite doesn't expose many cache tweaking
- // functions yet, as its design may evolve.)
- void setResourceCacheLimit(size_t maxResourceBytes) override{};
- // TODO: b/293371537 - Triple-check and validate that no cleanup is necessary when switching
- // contexts.
- // No-op (unnecessary during context switch for Graphite's client-budgeted memory model).
- void purgeUnlockedScratchResources() override{};
+ void setResourceCacheLimit(size_t maxResourceBytes) override;
+ void purgeUnlockedScratchResources() override;
+
// No-op (only applicable to GL).
void resetContextIfApplicable() override{};
diff --git a/libs/renderengine/skia/debug/CaptureTimer.cpp b/libs/renderengine/skia/debug/CaptureTimer.cpp
index 11bcdb8..1c1ee0a 100644
--- a/libs/renderengine/skia/debug/CaptureTimer.cpp
+++ b/libs/renderengine/skia/debug/CaptureTimer.cpp
@@ -30,7 +30,7 @@
void CaptureTimer::setTimeout(TimeoutCallback function, std::chrono::milliseconds delay) {
this->clear = false;
- CommonPool::post([=]() {
+ CommonPool::post([=,this]() {
if (this->clear) return;
std::this_thread::sleep_for(delay);
if (this->clear) return;
diff --git a/libs/renderengine/skia/filters/BlurFilter.cpp b/libs/renderengine/skia/filters/BlurFilter.cpp
index cd1bd71..8edf98e 100644
--- a/libs/renderengine/skia/filters/BlurFilter.cpp
+++ b/libs/renderengine/skia/filters/BlurFilter.cpp
@@ -90,6 +90,8 @@
linearSampling, &blurMatrix);
if (blurRadius < mMaxCrossFadeRadius) {
+ LOG_ALWAYS_FATAL_IF(!input);
+
// For sampling Skia's API expects the inverse of what logically seems appropriate. In this
// case you might expect the matrix to simply be the canvas matrix.
SkMatrix inputMatrix;
diff --git a/libs/renderengine/skia/filters/GaussianBlurFilter.cpp b/libs/renderengine/skia/filters/GaussianBlurFilter.cpp
index 8c52c57..b03ebe3 100644
--- a/libs/renderengine/skia/filters/GaussianBlurFilter.cpp
+++ b/libs/renderengine/skia/filters/GaussianBlurFilter.cpp
@@ -64,7 +64,7 @@
SkSamplingOptions{SkFilterMode::kLinear, SkMipmapMode::kNone},
&paint,
SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint);
- return surface->makeImageSnapshot();
+ return surface->makeTemporaryImage();
}
} // namespace skia
diff --git a/libs/renderengine/skia/filters/KawaseBlurDualFilter.cpp b/libs/renderengine/skia/filters/KawaseBlurDualFilter.cpp
index db0b133..ff96b08 100644
--- a/libs/renderengine/skia/filters/KawaseBlurDualFilter.cpp
+++ b/libs/renderengine/skia/filters/KawaseBlurDualFilter.cpp
@@ -39,12 +39,36 @@
namespace skia {
KawaseBlurDualFilter::KawaseBlurDualFilter() : BlurFilter() {
- // A shader to sample each vertex of a unit regular heptagon
- // plus the original fragment coordinate.
- SkString blurString(R"(
+ // A shader to sample each vertex of a square, plus the original fragment coordinate,
+ // using a total of 5 samples.
+ SkString lowSampleBlurString(R"(
uniform shader child;
uniform float in_blurOffset;
uniform float in_crossFade;
+ uniform float in_weightedCrossFade;
+
+ const float2 STEP_0 = float2( 0.707106781, 0.707106781);
+ const float2 STEP_1 = float2( 0.707106781, -0.707106781);
+ const float2 STEP_2 = float2(-0.707106781, -0.707106781);
+ const float2 STEP_3 = float2(-0.707106781, 0.707106781);
+
+ half4 main(float2 xy) {
+ half3 c = child.eval(xy).rgb;
+
+ c += child.eval(xy + STEP_0 * in_blurOffset).rgb;
+ c += child.eval(xy + STEP_1 * in_blurOffset).rgb;
+ c += child.eval(xy + STEP_2 * in_blurOffset).rgb;
+ c += child.eval(xy + STEP_3 * in_blurOffset).rgb;
+
+ return half4(c * in_weightedCrossFade, in_crossFade);
+ }
+ )");
+
+ // A shader to sample each vertex of a unit regular heptagon, plus the original fragment
+ // coordinate, using a total of 8 samples.
+ SkString highSampleBlurString(R"(
+ uniform shader child;
+ uniform float in_blurOffset;
const float2 STEP_0 = float2( 1.0, 0.0);
const float2 STEP_1 = float2( 0.623489802, 0.781831482);
@@ -65,44 +89,48 @@
c += child.eval(xy + STEP_5 * in_blurOffset).rgb;
c += child.eval(xy + STEP_6 * in_blurOffset).rgb;
- return half4(c * 0.125 * in_crossFade, in_crossFade);
+ return half4(c * 0.125, 1.0);
}
)");
- auto [blurEffect, error] = SkRuntimeEffect::MakeForShader(blurString);
- LOG_ALWAYS_FATAL_IF(!blurEffect, "RuntimeShader error: %s", error.c_str());
- mBlurEffect = std::move(blurEffect);
-}
-
-static sk_sp<SkSurface> makeSurface(SkiaGpuContext* context, const SkRect& origRect, int scale) {
- SkImageInfo scaledInfo =
- SkImageInfo::MakeN32Premul(ceil(static_cast<float>(origRect.width()) / scale),
- ceil(static_cast<float>(origRect.height()) / scale));
- return context->createRenderTarget(scaledInfo);
+ auto [lowSampleBlurEffect, error] = SkRuntimeEffect::MakeForShader(lowSampleBlurString);
+ auto [highSampleBlurEffect, error2] = SkRuntimeEffect::MakeForShader(highSampleBlurString);
+ LOG_ALWAYS_FATAL_IF(!lowSampleBlurEffect, "RuntimeShader error: %s", error.c_str());
+ LOG_ALWAYS_FATAL_IF(!highSampleBlurEffect, "RuntimeShader error: %s", error2.c_str());
+ mLowSampleBlurEffect = std::move(lowSampleBlurEffect);
+ mHighSampleBlurEffect = std::move(highSampleBlurEffect);
}
void KawaseBlurDualFilter::blurInto(const sk_sp<SkSurface>& drawSurface,
const sk_sp<SkImage>& readImage, const float radius,
- const float alpha) const {
+ const float alpha,
+ const sk_sp<SkRuntimeEffect>& blurEffect) const {
const float scale = static_cast<float>(drawSurface->width()) / readImage->width();
SkMatrix blurMatrix = SkMatrix::Scale(scale, scale);
blurInto(drawSurface,
readImage->makeShader(SkTileMode::kClamp, SkTileMode::kClamp,
SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone),
blurMatrix),
- readImage->width() / static_cast<float>(drawSurface->width()), radius, alpha);
+ radius, alpha, blurEffect);
}
void KawaseBlurDualFilter::blurInto(const sk_sp<SkSurface>& drawSurface, sk_sp<SkShader> input,
- const float inverseScale, const float radius,
- const float alpha) const {
- SkRuntimeShaderBuilder blurBuilder(mBlurEffect);
- blurBuilder.child("child") = std::move(input);
- blurBuilder.uniform("in_inverseScale") = inverseScale;
- blurBuilder.uniform("in_blurOffset") = radius;
- blurBuilder.uniform("in_crossFade") = alpha;
+ const float radius, const float alpha,
+ const sk_sp<SkRuntimeEffect>& blurEffect) const {
SkPaint paint;
- paint.setShader(blurBuilder.makeShader(nullptr));
+ if (radius == 0) {
+ paint.setShader(std::move(input));
+ paint.setAlphaf(alpha);
+ } else {
+ SkRuntimeShaderBuilder blurBuilder(blurEffect);
+ blurBuilder.child("child") = std::move(input);
+ if (blurEffect == mLowSampleBlurEffect) {
+ blurBuilder.uniform("in_crossFade") = alpha;
+ blurBuilder.uniform("in_weightedCrossFade") = alpha * 0.2f;
+ }
+ blurBuilder.uniform("in_blurOffset") = radius;
+ paint.setShader(blurBuilder.makeShader(nullptr));
+ }
paint.setBlendMode(alpha == 1.0f ? SkBlendMode::kSrc : SkBlendMode::kSrcOver);
drawSurface->getCanvas()->drawPaint(paint);
}
@@ -116,32 +144,44 @@
// Use a variable number of blur passes depending on the radius. The non-integer part of this
// calculation is used to mix the final pass into the second-last with an alpha blend.
- constexpr int kMaxSurfaces = 4;
- const float filterDepth =
- std::min(kMaxSurfaces - 1.0f, 1.0f + std::max(0.0f, log2f(radius * kInputScale)));
+ constexpr int kMaxSurfaces = 3;
+ const float filterDepth = std::min(kMaxSurfaces - 1.0f, radius * kInputScale / 2.5f);
const int filterPasses = std::min(kMaxSurfaces - 1, static_cast<int>(ceil(filterDepth)));
- // Render into surfaces downscaled by 1x, 1x, 2x, and 4x from the initial downscale.
- sk_sp<SkSurface> surfaces[kMaxSurfaces] =
- {filterPasses >= 0 ? makeSurface(context, blurRect, 1 * kInverseInputScale) : nullptr,
- filterPasses >= 1 ? makeSurface(context, blurRect, 1 * kInverseInputScale) : nullptr,
- filterPasses >= 2 ? makeSurface(context, blurRect, 2 * kInverseInputScale) : nullptr,
- filterPasses >= 3 ? makeSurface(context, blurRect, 4 * kInverseInputScale) : nullptr};
+ auto makeSurface = [&](float scale) -> sk_sp<SkSurface> {
+ const auto newW = ceil(static_cast<float>(blurRect.width() / scale));
+ const auto newH = ceil(static_cast<float>(blurRect.height() / scale));
+ sk_sp<SkSurface> surface =
+ context->createRenderTarget(input->imageInfo().makeWH(newW, newH));
+ LOG_ALWAYS_FATAL_IF(!surface, "%s: Failed to create surface for blurring!", __func__);
+ return surface;
+ };
- // These weights for scaling offsets per-pass are handpicked to look good at 1 <= radius <= 600.
- static const float kWeights[7] = {1.0f, 2.0f, 3.5f, 1.0f, 2.0f, 2.0f, 2.0f};
+ // Render into surfaces downscaled by 1x, 2x, and 4x from the initial downscale.
+ sk_sp<SkSurface> surfaces[kMaxSurfaces] =
+ {filterPasses >= 0 ? makeSurface(1 * kInverseInputScale) : nullptr,
+ filterPasses >= 1 ? makeSurface(2 * kInverseInputScale) : nullptr,
+ filterPasses >= 2 ? makeSurface(4 * kInverseInputScale) : nullptr};
+
+ // These weights for scaling offsets per-pass are handpicked to look good at 1 <= radius <= 250.
+ static const float kWeights[5] = {
+ 1.0f, // 1st downsampling pass
+ 1.0f, // 2nd downsampling pass
+ 1.0f, // 3rd downsampling pass
+ 0.0f, // 1st upscaling pass. Set to zero to upscale without blurring for performance.
+ 1.0f, // 2nd upscaling pass
+ };
// Kawase is an approximation of Gaussian, but behaves differently because it is made up of many
// simpler blurs. A transformation is required to approximate the same effect as Gaussian.
- float sumSquaredR = powf(kWeights[0] * powf(2.0f, 1), 2.0f);
+ float sumSquaredR = powf(kWeights[0], 2.0f);
for (int i = 0; i < filterPasses; i++) {
const float alpha = std::min(1.0f, filterDepth - i);
- sumSquaredR += powf(powf(2.0f, i + 1) * alpha * kWeights[1 + i], 2.0f);
- sumSquaredR += powf(powf(2.0f, i + 1) * alpha * kWeights[6 - i], 2.0f);
+ sumSquaredR += powf(powf(2.0f, i) * alpha * kWeights[1 + i] / kInputScale, 2.0f);
+ sumSquaredR += powf(powf(2.0f, i + 1) * alpha * kWeights[4 - i] / kInputScale, 2.0f);
}
- // Solve for R = sqrt(sum(r_i^2)). Divide R by hypot(1,1) to find some (x,y) offsets.
- const float step = M_SQRT1_2 *
- sqrtf(max(0.0f, (powf(radius, 2.0f) - powf(kInverseInputScale, 2.0f)) / sumSquaredR));
+ // Solve for R = sqrt(sum(r_i^2)).
+ const float step = radius * sqrt(1.0f / sumSquaredR);
// Start by downscaling and doing the first blur pass.
{
@@ -154,18 +194,21 @@
input->makeShader(SkTileMode::kClamp, SkTileMode::kClamp,
SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone),
blurMatrix);
- blurInto(surfaces[0], std::move(sourceShader), kInputScale, kWeights[0] * step, 1.0f);
+ blurInto(surfaces[0], std::move(sourceShader), kWeights[0] * step, 1.0f,
+ mLowSampleBlurEffect);
}
// Next the remaining downscale blur passes.
for (int i = 0; i < filterPasses; i++) {
- blurInto(surfaces[i + 1], surfaces[i]->makeImageSnapshot(), kWeights[1 + i] * step, 1.0f);
+ // Blur with the higher sample effect into the smaller buffers, for better visual quality.
+ blurInto(surfaces[i + 1], surfaces[i]->makeTemporaryImage(), kWeights[1 + i] * step, 1.0f,
+ i == 0 ? mLowSampleBlurEffect : mHighSampleBlurEffect);
}
// Finally blur+upscale back to our original size.
for (int i = filterPasses - 1; i >= 0; i--) {
- blurInto(surfaces[i], surfaces[i + 1]->makeImageSnapshot(), kWeights[6 - i] * step,
- std::min(1.0f, filterDepth - i));
+ blurInto(surfaces[i], surfaces[i + 1]->makeTemporaryImage(), kWeights[4 - i] * step,
+ std::min(1.0f, filterDepth - i), mLowSampleBlurEffect);
}
- return surfaces[0]->makeImageSnapshot();
+ return surfaces[0]->makeTemporaryImage();
}
} // namespace skia
diff --git a/libs/renderengine/skia/filters/KawaseBlurDualFilter.h b/libs/renderengine/skia/filters/KawaseBlurDualFilter.h
index 6f4adbf..5efda35 100644
--- a/libs/renderengine/skia/filters/KawaseBlurDualFilter.h
+++ b/libs/renderengine/skia/filters/KawaseBlurDualFilter.h
@@ -41,13 +41,14 @@
const sk_sp<SkImage> blurInput, const SkRect& blurRect) const override;
private:
- sk_sp<SkRuntimeEffect> mBlurEffect;
+ sk_sp<SkRuntimeEffect> mLowSampleBlurEffect;
+ sk_sp<SkRuntimeEffect> mHighSampleBlurEffect;
void blurInto(const sk_sp<SkSurface>& drawSurface, const sk_sp<SkImage>& readImage,
- const float radius, const float alpha) const;
+ const float radius, const float alpha, const sk_sp<SkRuntimeEffect>&) const;
void blurInto(const sk_sp<SkSurface>& drawSurface, const sk_sp<SkShader> input,
- const float inverseScale, const float radius, const float alpha) const;
+ const float radius, const float alpha, const sk_sp<SkRuntimeEffect>&) const;
};
} // namespace skia
diff --git a/libs/renderengine/skia/filters/KawaseBlurFilter.cpp b/libs/renderengine/skia/filters/KawaseBlurFilter.cpp
index defaf6e..f71a63d 100644
--- a/libs/renderengine/skia/filters/KawaseBlurFilter.cpp
+++ b/libs/renderengine/skia/filters/KawaseBlurFilter.cpp
@@ -70,7 +70,7 @@
paint.setShader(std::move(shader));
paint.setBlendMode(SkBlendMode::kSrc);
surface->getCanvas()->drawPaint(paint);
- return surface->makeImageSnapshot();
+ return surface->makeTemporaryImage();
}
sk_sp<SkImage> KawaseBlurFilter::generate(SkiaGpuContext* context, const uint32_t blurRadius,
diff --git a/libs/renderengine/skia/filters/LutShader.cpp b/libs/renderengine/skia/filters/LutShader.cpp
new file mode 100644
index 0000000..f262158
--- /dev/null
+++ b/libs/renderengine/skia/filters/LutShader.cpp
@@ -0,0 +1,301 @@
+/*
+ * Copyright 2024 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 "LutShader.h"
+
+#include <SkM44.h>
+#include <SkTileMode.h>
+#include <common/trace.h>
+#include <cutils/ashmem.h>
+#include <math/half.h>
+#include <sys/mman.h>
+#include <ui/ColorSpace.h>
+
+#include "include/core/SkColorSpace.h"
+#include "src/core/SkColorFilterPriv.h"
+
+using aidl::android::hardware::graphics::composer3::LutProperties;
+
+namespace android {
+namespace renderengine {
+namespace skia {
+
+static const SkString kShader = SkString(R"(
+ uniform shader image;
+ uniform shader lut;
+ uniform int size;
+ uniform int key;
+ uniform int dimension;
+ uniform vec3 luminanceCoefficients; // for CIE_Y
+ // for hlg/pq transfer function, we need normalize it to [0.0, 1.0]
+ // we use `normalizeScalar` to do so
+ uniform float normalizeScalar;
+
+ vec4 main(vec2 xy) {
+ float4 rgba = image.eval(xy);
+ float3 linear = toLinearSrgb(rgba.rgb) * normalizeScalar;
+ if (dimension == 1) {
+ // RGB
+ if (key == 0) {
+ float indexR = linear.r * float(size - 1);
+ float indexG = linear.g * float(size - 1);
+ float indexB = linear.b * float(size - 1);
+ float gainR = lut.eval(vec2(indexR, 0.0) + 0.5).r;
+ float gainG = lut.eval(vec2(indexG, 0.0) + 0.5).r;
+ float gainB = lut.eval(vec2(indexB, 0.0) + 0.5).r;
+ linear = float3(linear.r * gainR, linear.g * gainG, linear.b * gainB);
+ // MAX_RGB
+ } else if (key == 1) {
+ float maxRGB = max(linear.r, max(linear.g, linear.b));
+ float index = maxRGB * float(size - 1);
+ float gain = lut.eval(vec2(index, 0.0) + 0.5).r;
+ linear = linear * gain;
+ // CIE_Y
+ } else if (key == 2) {
+ float y = dot(linear, luminanceCoefficients) / 3.0;
+ float index = y * float(size - 1);
+ float gain = lut.eval(vec2(index, 0.0) + 0.5).r;
+ linear = linear * gain;
+ }
+ } else if (dimension == 3) {
+ if (key == 0) {
+ float tx = linear.r * float(size - 1);
+ float ty = linear.g * float(size - 1);
+ float tz = linear.b * float(size - 1);
+
+ // calculate lower and upper bounds for each dimension
+ int x = int(tx);
+ int y = int(ty);
+ int z = int(tz);
+
+ int i000 = x + y * size + z * size * size;
+ int i100 = i000 + 1;
+ int i010 = i000 + size;
+ int i110 = i000 + size + 1;
+ int i001 = i000 + size * size;
+ int i101 = i000 + size * size + 1;
+ int i011 = i000 + size * size + size;
+ int i111 = i000 + size * size + size + 1;
+
+ // get 1d normalized indices
+ float c000 = float(i000) / float(size * size * size);
+ float c100 = float(i100) / float(size * size * size);
+ float c010 = float(i010) / float(size * size * size);
+ float c110 = float(i110) / float(size * size * size);
+ float c001 = float(i001) / float(size * size * size);
+ float c101 = float(i101) / float(size * size * size);
+ float c011 = float(i011) / float(size * size * size);
+ float c111 = float(i111) / float(size * size * size);
+
+ //TODO(b/377984618): support Tetrahedral interpolation
+ // perform trilinear interpolation
+ float3 c00 = mix(lut.eval(vec2(c000, 0.0) + 0.5).rgb,
+ lut.eval(vec2(c100, 0.0) + 0.5).rgb, linear.r);
+ float3 c01 = mix(lut.eval(vec2(c001, 0.0) + 0.5).rgb,
+ lut.eval(vec2(c101, 0.0) + 0.5).rgb, linear.r);
+ float3 c10 = mix(lut.eval(vec2(c010, 0.0) + 0.5).rgb,
+ lut.eval(vec2(c110, 0.0) + 0.5).rgb, linear.r);
+ float3 c11 = mix(lut.eval(vec2(c011, 0.0) + 0.5).rgb,
+ lut.eval(vec2(c111, 0.0) + 0.5).rgb, linear.r);
+
+ float3 c0 = mix(c00, c10, linear.g);
+ float3 c1 = mix(c01, c11, linear.g);
+
+ linear = mix(c0, c1, linear.b);
+ }
+ }
+ return float4(linear, rgba.a);
+ })");
+
+// same as shader::toColorSpace function
+// TODO: put this function in a general place
+static ColorSpace toColorSpace(ui::Dataspace dataspace) {
+ switch (dataspace & HAL_DATASPACE_STANDARD_MASK) {
+ case HAL_DATASPACE_STANDARD_BT709:
+ return ColorSpace::sRGB();
+ case HAL_DATASPACE_STANDARD_DCI_P3:
+ return ColorSpace::DisplayP3();
+ case HAL_DATASPACE_STANDARD_BT2020:
+ case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE:
+ return ColorSpace::BT2020();
+ case HAL_DATASPACE_STANDARD_ADOBE_RGB:
+ return ColorSpace::AdobeRGB();
+ case HAL_DATASPACE_STANDARD_BT601_625:
+ case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
+ case HAL_DATASPACE_STANDARD_BT601_525:
+ case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
+ case HAL_DATASPACE_STANDARD_BT470M:
+ case HAL_DATASPACE_STANDARD_FILM:
+ case HAL_DATASPACE_STANDARD_UNSPECIFIED:
+ default:
+ return ColorSpace::sRGB();
+ }
+}
+
+sk_sp<SkShader> LutShader::generateLutShader(sk_sp<SkShader> input,
+ const std::vector<float>& buffers,
+ const int32_t offset, const int32_t length,
+ const int32_t dimension, const int32_t size,
+ const int32_t samplingKey,
+ ui::Dataspace srcDataspace) {
+ SFTRACE_NAME("lut shader");
+ std::vector<half> buffer(length * 4); // 4 is for RGBA
+ auto d = static_cast<LutProperties::Dimension>(dimension);
+ if (d == LutProperties::Dimension::ONE_D) {
+ auto it = buffers.begin() + offset;
+ std::generate(buffer.begin(), buffer.end(), [it, i = 0]() mutable {
+ float val = (i++ % 4 == 0) ? *it++ : 0.0f;
+ return half(val);
+ });
+ } else {
+ for (int i = 0; i < length; i++) {
+ buffer[i * 4] = half(buffers[offset + i]);
+ buffer[i * 4 + 1] = half(buffers[offset + length + i]);
+ buffer[i * 4 + 2] = half(buffers[offset + length * 2 + i]);
+ buffer[i * 4 + 3] = half(0);
+ }
+ }
+ /**
+ * 1D Lut RGB/MAX_RGB
+ * (R0, 0, 0, 0)
+ * (R1, 0, 0, 0)
+ *
+ * 1D Lut CIE_Y
+ * (Y0, 0, 0, 0)
+ * (Y1, 0, 0, 0)
+ * ...
+ *
+ * 3D Lut MAX_RGB
+ * (R0, G0, B0, 0)
+ * (R1, G1, B1, 0)
+ * ...
+ */
+ SkImageInfo info = SkImageInfo::Make(length /* the number of rgba */, 1, kRGBA_F16_SkColorType,
+ kPremul_SkAlphaType);
+ SkBitmap bitmap;
+ bitmap.allocPixels(info);
+ if (!bitmap.installPixels(info, buffer.data(), info.minRowBytes())) {
+ ALOGW("bitmap.installPixels failed, skip this Lut!");
+ return input;
+ }
+
+ sk_sp<SkImage> lutImage = SkImages::RasterFromBitmap(bitmap);
+ if (!lutImage) {
+ ALOGW("Got a nullptr from SkImages::RasterFromBitmap, skip this Lut!");
+ return input;
+ }
+
+ mBuilder->child("image") = input;
+ mBuilder->child("lut") =
+ lutImage->makeRawShader(SkTileMode::kClamp, SkTileMode::kClamp,
+ d == LutProperties::Dimension::ONE_D
+ ? SkSamplingOptions(SkFilterMode::kLinear)
+ : SkSamplingOptions());
+
+ float normalizeScalar = 1.0;
+ switch (srcDataspace & HAL_DATASPACE_TRANSFER_MASK) {
+ case HAL_DATASPACE_TRANSFER_HLG:
+ normalizeScalar = 0.203;
+ break;
+ case HAL_DATASPACE_TRANSFER_ST2084:
+ normalizeScalar = 0.0203;
+ break;
+ default:
+ normalizeScalar = 1.0;
+ }
+ const int uSize = static_cast<int>(size);
+ const int uKey = static_cast<int>(samplingKey);
+ const int uDimension = static_cast<int>(dimension);
+ const float uNormalizeScalar = static_cast<float>(normalizeScalar);
+
+ if (static_cast<LutProperties::SamplingKey>(samplingKey) == LutProperties::SamplingKey::CIE_Y) {
+ // Use predefined colorspaces of input dataspace so that we can get D65 illuminant
+ mat3 toXYZMatrix(toColorSpace(srcDataspace).getRGBtoXYZ());
+ mBuilder->uniform("luminanceCoefficients") =
+ SkV3{toXYZMatrix[0][1], toXYZMatrix[1][1], toXYZMatrix[2][1]};
+ } else {
+ mBuilder->uniform("luminanceCoefficients") = SkV3{1.f, 1.f, 1.f};
+ }
+ mBuilder->uniform("size") = uSize;
+ mBuilder->uniform("key") = uKey;
+ mBuilder->uniform("dimension") = uDimension;
+ mBuilder->uniform("normalizeScalar") = uNormalizeScalar;
+ return mBuilder->makeShader();
+}
+
+sk_sp<SkShader> LutShader::lutShader(sk_sp<SkShader>& input,
+ std::shared_ptr<gui::DisplayLuts> displayLuts,
+ ui::Dataspace srcDataspace,
+ sk_sp<SkColorSpace> outColorSpace) {
+ if (mBuilder == nullptr) {
+ const static SkRuntimeEffect::Result instance = SkRuntimeEffect::MakeForShader(kShader);
+ mBuilder = std::make_unique<SkRuntimeShaderBuilder>(instance.effect);
+ }
+
+ auto& fd = displayLuts->getLutFileDescriptor();
+ if (fd.ok()) {
+ // de-gamma the image without changing the primaries
+ SkImage* baseImage = input->isAImage((SkMatrix*)nullptr, (SkTileMode*)nullptr);
+ sk_sp<SkColorSpace> baseColorSpace = baseImage && baseImage->colorSpace()
+ ? baseImage->refColorSpace()
+ : SkColorSpace::MakeSRGB();
+ sk_sp<SkColorSpace> lutMathColorSpace = baseColorSpace->makeLinearGamma();
+ input = input->makeWithWorkingColorSpace(lutMathColorSpace);
+
+ auto& offsets = displayLuts->offsets;
+ auto& lutProperties = displayLuts->lutProperties;
+ std::vector<float> buffers;
+ int fullLength = offsets[lutProperties.size() - 1];
+ if (lutProperties[lutProperties.size() - 1].dimension == 1) {
+ fullLength += lutProperties[lutProperties.size() - 1].size;
+ } else {
+ fullLength += (lutProperties[lutProperties.size() - 1].size *
+ lutProperties[lutProperties.size() - 1].size *
+ lutProperties[lutProperties.size() - 1].size * 3);
+ }
+ size_t bufferSize = fullLength * sizeof(float);
+
+ // decode the shared memory of luts
+ float* ptr =
+ (float*)mmap(NULL, bufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd.get(), 0);
+ if (ptr == MAP_FAILED) {
+ LOG_ALWAYS_FATAL("mmap failed");
+ }
+ buffers = std::vector<float>(ptr, ptr + fullLength);
+ munmap(ptr, bufferSize);
+
+ for (size_t i = 0; i < offsets.size(); i++) {
+ int bufferSizePerLut = (i == offsets.size() - 1) ? buffers.size() - offsets[i]
+ : offsets[i + 1] - offsets[i];
+ // divide by 3 for 3d Lut because of 3 (RGB) channels
+ if (static_cast<LutProperties::Dimension>(lutProperties[i].dimension) ==
+ LutProperties::Dimension::THREE_D) {
+ bufferSizePerLut /= 3;
+ }
+ input = generateLutShader(input, buffers, offsets[i], bufferSizePerLut,
+ lutProperties[i].dimension, lutProperties[i].size,
+ lutProperties[i].samplingKey, srcDataspace);
+ }
+
+ auto colorXformLutToDst =
+ SkColorFilterPriv::MakeColorSpaceXform(lutMathColorSpace, outColorSpace);
+ input = input->makeWithColorFilter(colorXformLutToDst);
+ }
+ return input;
+}
+
+} // namespace skia
+} // namespace renderengine
+} // namespace android
\ No newline at end of file
diff --git a/libs/renderengine/skia/filters/LutShader.h b/libs/renderengine/skia/filters/LutShader.h
new file mode 100644
index 0000000..7c62fca
--- /dev/null
+++ b/libs/renderengine/skia/filters/LutShader.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2024 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 <SkBitmap.h>
+#include <SkImage.h>
+#include <SkRuntimeEffect.h>
+
+#include <aidl/android/hardware/graphics/composer3/LutProperties.h>
+#include <gui/DisplayLuts.h>
+#include <ui/GraphicTypes.h>
+
+namespace android {
+namespace renderengine {
+namespace skia {
+
+class LutShader {
+public:
+ sk_sp<SkShader> lutShader(sk_sp<SkShader>& input, std::shared_ptr<gui::DisplayLuts> displayLuts,
+ ui::Dataspace srcDataspace, sk_sp<SkColorSpace> outColorSpace);
+
+private:
+ sk_sp<SkShader> generateLutShader(sk_sp<SkShader> input, const std::vector<float>& buffers,
+ const int32_t offset, const int32_t length,
+ const int32_t dimension, const int32_t size,
+ const int32_t samplingKey, ui::Dataspace srcDataspace);
+ std::unique_ptr<SkRuntimeShaderBuilder> mBuilder;
+};
+
+} // namespace skia
+} // namespace renderengine
+} // namespace android
diff --git a/libs/renderengine/skia/filters/MouriMap.cpp b/libs/renderengine/skia/filters/MouriMap.cpp
index b099bcf..5dc36e6 100644
--- a/libs/renderengine/skia/filters/MouriMap.cpp
+++ b/libs/renderengine/skia/filters/MouriMap.cpp
@@ -30,12 +30,12 @@
}
const SkString kCrosstalkAndChunk16x16(R"(
uniform shader bitmap;
- uniform float hdrSdrRatio;
+ uniform float inputMultiplier;
vec4 main(vec2 xy) {
float maximum = 0.0;
for (int y = 0; y < 16; y++) {
for (int x = 0; x < 16; x++) {
- float3 linear = toLinearSrgb(bitmap.eval((xy - 0.5) * 16 + 0.5 + vec2(x, y)).rgb) * hdrSdrRatio;
+ float3 linear = toLinearSrgb(bitmap.eval((xy - 0.5) * 16 + 0.5 + vec2(x, y)).rgb) * inputMultiplier;
float maxRGB = max(linear.r, max(linear.g, linear.b));
maximum = max(maximum, log2(max(maxRGB, 1.0)));
}
@@ -77,12 +77,12 @@
uniform shader image;
uniform shader lux;
uniform float scaleFactor;
- uniform float hdrSdrRatio;
+ uniform float inputMultiplier;
uniform float targetHdrSdrRatio;
vec4 main(vec2 xy) {
float localMax = lux.eval(xy * scaleFactor).r;
float4 rgba = image.eval(xy);
- float3 linear = toLinearSrgb(rgba.rgb) * hdrSdrRatio;
+ float3 linear = toLinearSrgb(rgba.rgb) * inputMultiplier;
if (localMax <= targetHdrSdrRatio) {
return float4(fromLinearSrgb(linear), rgba.a);
@@ -104,7 +104,7 @@
paint.setShader(std::move(shader));
paint.setBlendMode(SkBlendMode::kSrc);
surface->getCanvas()->drawPaint(paint);
- return surface->makeImageSnapshot();
+ return surface->makeTemporaryImage();
}
} // namespace
@@ -116,19 +116,19 @@
mTonemap(makeEffect(kTonemap)) {}
sk_sp<SkShader> MouriMap::mouriMap(SkiaGpuContext* context, sk_sp<SkShader> input,
- float hdrSdrRatio, float targetHdrSdrRatio) {
- auto downchunked = downchunk(context, input, hdrSdrRatio);
+ float inputMultiplier, float targetHdrSdrRatio) {
+ auto downchunked = downchunk(context, input, inputMultiplier);
auto localLux = blur(context, downchunked.get());
- return tonemap(input, localLux.get(), hdrSdrRatio, targetHdrSdrRatio);
+ return tonemap(input, localLux.get(), inputMultiplier, targetHdrSdrRatio);
}
sk_sp<SkImage> MouriMap::downchunk(SkiaGpuContext* context, sk_sp<SkShader> input,
- float hdrSdrRatio) const {
+ float inputMultiplier) const {
SkMatrix matrix;
SkImage* image = input->isAImage(&matrix, (SkTileMode*)nullptr);
SkRuntimeShaderBuilder crosstalkAndChunk16x16Builder(mCrosstalkAndChunk16x16);
crosstalkAndChunk16x16Builder.child("bitmap") = input;
- crosstalkAndChunk16x16Builder.uniform("hdrSdrRatio") = hdrSdrRatio;
+ crosstalkAndChunk16x16Builder.uniform("inputMultiplier") = inputMultiplier;
// TODO: fp16 might be overkill. Most practical surfaces use 8-bit RGB for HDR UI and 10-bit YUV
// for HDR video. These downsample operations compute log2(max(linear RGB, 1.0)). So we don't
// care about LDR precision since they all resolve to LDR-max. For appropriately mastered HDR
@@ -168,7 +168,7 @@
LOG_ALWAYS_FATAL_IF(!blurSurface, "%s: Failed to create surface!", __func__);
return makeImage(blurSurface.get(), blurBuilder);
}
-sk_sp<SkShader> MouriMap::tonemap(sk_sp<SkShader> input, SkImage* localLux, float hdrSdrRatio,
+sk_sp<SkShader> MouriMap::tonemap(sk_sp<SkShader> input, SkImage* localLux, float inputMultiplier,
float targetHdrSdrRatio) const {
static constexpr float kScaleFactor = 1.0f / 128.0f;
SkRuntimeShaderBuilder tonemapBuilder(mTonemap);
@@ -177,7 +177,7 @@
localLux->makeRawShader(SkTileMode::kClamp, SkTileMode::kClamp,
SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone));
tonemapBuilder.uniform("scaleFactor") = kScaleFactor;
- tonemapBuilder.uniform("hdrSdrRatio") = hdrSdrRatio;
+ tonemapBuilder.uniform("inputMultiplier") = inputMultiplier;
tonemapBuilder.uniform("targetHdrSdrRatio") = targetHdrSdrRatio;
return tonemapBuilder.makeShader();
}
diff --git a/libs/renderengine/skia/filters/MouriMap.h b/libs/renderengine/skia/filters/MouriMap.h
index 9ba2b6f..f4bfa15 100644
--- a/libs/renderengine/skia/filters/MouriMap.h
+++ b/libs/renderengine/skia/filters/MouriMap.h
@@ -62,10 +62,13 @@
public:
MouriMap();
// Apply the MouriMap tonemmaping operator to the input.
- // The HDR/SDR ratio describes the luminace range of the input. 1.0 means SDR. Anything larger
- // then 1.0 means that there is headroom above the SDR region.
- // Similarly, the target HDR/SDR ratio describes the luminance range of the output.
- sk_sp<SkShader> mouriMap(SkiaGpuContext* context, sk_sp<SkShader> input, float inputHdrSdrRatio,
+ // The inputMultiplier informs how to interpret the luminance encoding of the input.
+ // For a fixed point input, this is necessary to interpret what "1.0" means for the input
+ // pixels, so that the luminance can be scaled appropriately, such that the operator can
+ // transform SDR values to be within 1.0. For a floating point input, "1.0" always means SDR,
+ // so the caller must pass 1.0.
+ // The target HDR/SDR ratio describes the luminance range of the output.
+ sk_sp<SkShader> mouriMap(SkiaGpuContext* context, sk_sp<SkShader> input, float inputMultiplier,
float targetHdrSdrRatio);
private:
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp
index c187f93..67f4aa1 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.cpp
+++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp
@@ -23,6 +23,7 @@
#include <future>
#include <android-base/stringprintf.h>
+#include <common/FlagManager.h>
#include <common/trace.h>
#include <private/gui/SyncFeatures.h>
#include <processgroup/processgroup.h>
@@ -60,7 +61,7 @@
struct sched_param param = {0};
int sched_policy;
- if (enabled) {
+ if (enabled && !FlagManager::getInstance().disable_sched_fifo_re()) {
sched_policy = SCHED_FIFO;
param.sched_priority = kFifoPriority;
} else {
@@ -249,11 +250,10 @@
return;
}
-void RenderEngineThreaded::drawGainmapInternal(
+void RenderEngineThreaded::tonemapAndDrawGainmapInternal(
const std::shared_ptr<std::promise<FenceResult>>&& resultPromise,
- const std::shared_ptr<ExternalTexture>& sdr, base::borrowed_fd&& sdrFence,
const std::shared_ptr<ExternalTexture>& hdr, base::borrowed_fd&& hdrFence,
- float hdrSdrRatio, ui::Dataspace dataspace,
+ float hdrSdrRatio, ui::Dataspace dataspace, const std::shared_ptr<ExternalTexture>& sdr,
const std::shared_ptr<ExternalTexture>& gainmap) {
resultPromise->set_value(Fence::NO_FENCE);
return;
@@ -281,10 +281,9 @@
return resultFuture;
}
-ftl::Future<FenceResult> RenderEngineThreaded::drawGainmap(
- const std::shared_ptr<ExternalTexture>& sdr, base::borrowed_fd&& sdrFence,
+ftl::Future<FenceResult> RenderEngineThreaded::tonemapAndDrawGainmap(
const std::shared_ptr<ExternalTexture>& hdr, base::borrowed_fd&& hdrFence,
- float hdrSdrRatio, ui::Dataspace dataspace,
+ float hdrSdrRatio, ui::Dataspace dataspace, const std::shared_ptr<ExternalTexture>& sdr,
const std::shared_ptr<ExternalTexture>& gainmap) {
SFTRACE_CALL();
const auto resultPromise = std::make_shared<std::promise<FenceResult>>();
@@ -292,13 +291,14 @@
{
std::lock_guard lock(mThreadMutex);
mNeedsPostRenderCleanup = true;
- mFunctionCalls.push([resultPromise, sdr, sdrFence = std::move(sdrFence), hdr,
- hdrFence = std::move(hdrFence), hdrSdrRatio, dataspace,
+ mFunctionCalls.push([resultPromise, hdr, hdrFence = std::move(hdrFence), hdrSdrRatio,
+ dataspace, sdr,
gainmap](renderengine::RenderEngine& instance) mutable {
- SFTRACE_NAME("REThreaded::drawGainmap");
- instance.updateProtectedContext({}, {sdr.get(), hdr.get(), gainmap.get()});
- instance.drawGainmapInternal(std::move(resultPromise), sdr, std::move(sdrFence), hdr,
- std::move(hdrFence), hdrSdrRatio, dataspace, gainmap);
+ SFTRACE_NAME("REThreaded::tonemapAndDrawGainmap");
+ instance.updateProtectedContext({}, {hdr.get(), sdr.get(), gainmap.get()});
+ instance.tonemapAndDrawGainmapInternal(std::move(resultPromise), hdr,
+ std::move(hdrFence), hdrSdrRatio, dataspace, sdr,
+ gainmap);
});
}
mCondition.notify_one();
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h
index cb6e924..8554b55 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.h
+++ b/libs/renderengine/threaded/RenderEngineThreaded.h
@@ -55,12 +55,10 @@
const std::vector<LayerSettings>& layers,
const std::shared_ptr<ExternalTexture>& buffer,
base::unique_fd&& bufferFence) override;
- ftl::Future<FenceResult> drawGainmap(const std::shared_ptr<ExternalTexture>& sdr,
- base::borrowed_fd&& sdrFence,
- const std::shared_ptr<ExternalTexture>& hdr,
- base::borrowed_fd&& hdrFence, float hdrSdrRatio,
- ui::Dataspace dataspace,
- const std::shared_ptr<ExternalTexture>& gainmap) override;
+ ftl::Future<FenceResult> tonemapAndDrawGainmap(
+ const std::shared_ptr<ExternalTexture>& hdr, base::borrowed_fd&& hdrFence,
+ float hdrSdrRatio, ui::Dataspace dataspace, const std::shared_ptr<ExternalTexture>& sdr,
+ const std::shared_ptr<ExternalTexture>& gainmap) override;
int getContextPriority() override;
bool supportsBackgroundBlur() override;
@@ -77,13 +75,11 @@
const std::vector<LayerSettings>& layers,
const std::shared_ptr<ExternalTexture>& buffer,
base::unique_fd&& bufferFence) override;
- void drawGainmapInternal(const std::shared_ptr<std::promise<FenceResult>>&& resultPromise,
- const std::shared_ptr<ExternalTexture>& sdr,
- base::borrowed_fd&& sdrFence,
- const std::shared_ptr<ExternalTexture>& hdr,
- base::borrowed_fd&& hdrFence, float hdrSdrRatio,
- ui::Dataspace dataspace,
- const std::shared_ptr<ExternalTexture>& gainmap) override;
+ void tonemapAndDrawGainmapInternal(
+ const std::shared_ptr<std::promise<FenceResult>>&& resultPromise,
+ const std::shared_ptr<ExternalTexture>& hdr, base::borrowed_fd&& hdrFence,
+ float hdrSdrRatio, ui::Dataspace dataspace, const std::shared_ptr<ExternalTexture>& sdr,
+ const std::shared_ptr<ExternalTexture>& gainmap) override;
private:
void threadMain(CreateInstanceFactory factory);
diff --git a/libs/sensor/Android.bp b/libs/sensor/Android.bp
index 659666d..a687a37 100644
--- a/libs/sensor/Android.bp
+++ b/libs/sensor/Android.bp
@@ -69,6 +69,7 @@
static_libs: [
"libsensor_flags_c_lib",
+ "android.permission.flags-aconfig-cc",
],
export_include_dirs: ["include"],
diff --git a/libs/sensor/OWNERS b/libs/sensor/OWNERS
index 7347ac7..4929b3f 100644
--- a/libs/sensor/OWNERS
+++ b/libs/sensor/OWNERS
@@ -1 +1 @@
-bduddie@google.com
+include platform/frameworks/native:/services/sensorservice/OWNERS
\ No newline at end of file
diff --git a/libs/sensor/Sensor.cpp b/libs/sensor/Sensor.cpp
index a1549ea..797efbe 100644
--- a/libs/sensor/Sensor.cpp
+++ b/libs/sensor/Sensor.cpp
@@ -21,6 +21,7 @@
#include <binder/AppOpsManager.h>
#include <binder/IPermissionController.h>
#include <binder/IServiceManager.h>
+#include <android_permission_flags.h>
/*
* The permission to use for activity recognition sensors (like step counter).
@@ -121,7 +122,9 @@
break;
case SENSOR_TYPE_HEART_RATE: {
mStringType = SENSOR_STRING_TYPE_HEART_RATE;
- mRequiredPermission = SENSOR_PERMISSION_BODY_SENSORS;
+ mRequiredPermission =
+ android::permission::flags::replace_body_sensor_permission_enabled() ?
+ SENSOR_PERMISSION_READ_HEART_RATE : SENSOR_PERMISSION_BODY_SENSORS;
AppOpsManager appOps;
mRequiredAppOp = appOps.permissionToOpCode(String16(mRequiredPermission));
mFlags |= SENSOR_FLAG_ON_CHANGE_MODE;
@@ -303,7 +306,18 @@
}
if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor.requiredPermission) {
mRequiredPermission = hwSensor.requiredPermission;
- if (!strcmp(mRequiredPermission, SENSOR_PERMISSION_BODY_SENSORS)) {
+ bool requiresBodySensorPermission =
+ !strcmp(mRequiredPermission, SENSOR_PERMISSION_BODY_SENSORS);
+ if (android::permission::flags::replace_body_sensor_permission_enabled()) {
+ if (requiresBodySensorPermission) {
+ ALOGE("Sensor %s using deprecated Body Sensor permission", mName.c_str());
+ }
+
+ AppOpsManager appOps;
+ // Lookup to see if an AppOp exists for the permission. If none
+ // does, the default value of -1 is used.
+ mRequiredAppOp = appOps.permissionToOpCode(String16(mRequiredPermission));
+ } else if (requiresBodySensorPermission) {
AppOpsManager appOps;
mRequiredAppOp = appOps.permissionToOpCode(String16(SENSOR_PERMISSION_BODY_SENSORS));
}
diff --git a/libs/shaders/OWNERS b/libs/shaders/OWNERS
index 6d91da3..6977a49 100644
--- a/libs/shaders/OWNERS
+++ b/libs/shaders/OWNERS
@@ -1,4 +1,3 @@
alecmouri@google.com
jreck@google.com
sallyqi@google.com
-scroggo@google.com
\ No newline at end of file
diff --git a/libs/tonemap/OWNERS b/libs/tonemap/OWNERS
index 6d91da3..6977a49 100644
--- a/libs/tonemap/OWNERS
+++ b/libs/tonemap/OWNERS
@@ -1,4 +1,3 @@
alecmouri@google.com
jreck@google.com
sallyqi@google.com
-scroggo@google.com
\ No newline at end of file
diff --git a/libs/tracing_perfetto/Android.bp b/libs/tracing_perfetto/Android.bp
index b5c56c5..1ef83a4 100644
--- a/libs/tracing_perfetto/Android.bp
+++ b/libs/tracing_perfetto/Android.bp
@@ -21,7 +21,7 @@
default_applicable_licenses: ["frameworks_native_license"],
}
-cc_library_shared {
+cc_library {
name: "libtracing_perfetto",
export_include_dirs: [
"include",
@@ -37,14 +37,20 @@
srcs: [
"tracing_perfetto.cpp",
"tracing_perfetto_internal.cpp",
+ "tracing_sdk.cpp",
],
shared_libs: [
"libbase",
"libcutils",
"libperfetto_c",
- "android.os.flags-aconfig-cc-host",
+ ],
+
+ export_shared_lib_headers: [
+ "libperfetto_c",
],
host_supported: true,
+ // for vndbinder
+ vendor_available: true,
}
diff --git a/libs/tracing_perfetto/include/tracing_sdk.h b/libs/tracing_perfetto/include/tracing_sdk.h
new file mode 100644
index 0000000..271d7c8
--- /dev/null
+++ b/libs/tracing_perfetto/include/tracing_sdk.h
@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2024 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 <android-base/logging.h>
+#include <stdint.h>
+
+#include <optional>
+#include <vector>
+
+#include "perfetto/public/producer.h"
+#include "perfetto/public/te_category_macros.h"
+#include "perfetto/public/te_macros.h"
+#include "perfetto/public/track_event.h"
+
+#include "perfetto/public/abi/pb_decoder_abi.h"
+#include "perfetto/public/pb_utils.h"
+#include "perfetto/public/tracing_session.h"
+
+/**
+ * The objects declared here are intended to be managed by Java.
+ * This means the Java Garbage Collector is responsible for freeing the
+ * underlying native resources.
+ *
+ * The static methods prefixed with `delete_` are special. They are designed to be
+ * invoked by Java through the `NativeAllocationRegistry` when the
+ * corresponding Java object becomes unreachable. These methods act as
+ * callbacks to ensure proper deallocation of native resources.
+ */
+namespace tracing_perfetto {
+/**
+ * @brief Represents extra data associated with a trace event.
+ * This class manages a collection of PerfettoTeHlExtra pointers.
+ */
+class Extra;
+
+/**
+ * @brief Emits a trace event.
+ * @param type The type of the event.
+ * @param cat The category of the event.
+ * @param name The name of the event.
+ * @param arg_ptr Pointer to Extra data.
+ */
+void trace_event(int type, const PerfettoTeCategory* cat, const char* name,
+ Extra* extra);
+
+/**
+ * @brief Gets the process track UUID.
+ */
+uint64_t get_process_track_uuid();
+
+/**
+ * @brief Gets the thread track UUID for a given PID.
+ */
+uint64_t get_thread_track_uuid(pid_t tid);
+
+/**
+ * @brief Holder for all the other classes in the file.
+ */
+class Extra {
+ public:
+ Extra();
+ void push_extra(PerfettoTeHlExtra* extra);
+ void pop_extra();
+ void clear_extras();
+ static void delete_extra(Extra* extra);
+
+ PerfettoTeHlExtra* const* get() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Extra);
+
+ // These PerfettoTeHlExtra pointers are really pointers to all the other
+ // types of extras: Category, DebugArg, Counter etc. Those objects are
+ // individually managed by Java.
+ std::vector<PerfettoTeHlExtra*> extras_;
+};
+
+/**
+ * @brief Represents a trace event category.
+ */
+class Category {
+ public:
+ Category(const std::string& name, const std::string& tag,
+ const std::string& severity);
+
+ ~Category();
+
+ void register_category();
+
+ void unregister_category();
+
+ bool is_category_enabled();
+
+ static void delete_category(Category* category);
+
+ const PerfettoTeCategory* get() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Category);
+ PerfettoTeCategory category_;
+ const std::string name_;
+ const std::string tag_;
+ const std::string severity_;
+};
+
+/**
+ * @brief Represents one end of a flow between two events.
+ */
+class Flow {
+ public:
+ Flow();
+
+ void set_process_flow(uint64_t id);
+ void set_process_terminating_flow(uint64_t id);
+ static void delete_flow(Flow* flow);
+
+ const PerfettoTeHlExtraFlow* get() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Flow);
+ PerfettoTeHlExtraFlow flow_;
+};
+
+/**
+ * @brief Represents a named track.
+ */
+class NamedTrack {
+ public:
+ NamedTrack(uint64_t id, uint64_t parent_uuid, const std::string& name);
+
+ static void delete_track(NamedTrack* track);
+
+ const PerfettoTeHlExtraNamedTrack* get() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NamedTrack);
+ const std::string name_;
+ PerfettoTeHlExtraNamedTrack track_;
+};
+
+/**
+ * @brief Represents a registered track.
+ */
+class RegisteredTrack {
+ public:
+ RegisteredTrack(uint64_t id, uint64_t parent_uuid, const std::string& name,
+ bool is_counter);
+ ~RegisteredTrack();
+
+ void register_track();
+ void unregister_track();
+ static void delete_track(RegisteredTrack* track);
+
+ const PerfettoTeHlExtraRegisteredTrack* get() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RegisteredTrack);
+ PerfettoTeRegisteredTrack registered_track_;
+ PerfettoTeHlExtraRegisteredTrack track_;
+ const std::string name_;
+ const uint64_t id_;
+ const uint64_t parent_uuid_;
+ const bool is_counter_;
+};
+
+/**
+ * @brief Represents a counter track event.
+ * @tparam T The data type of the counter (int64_t or double).
+ */
+template <typename T>
+class Counter {
+ public:
+ template <typename>
+ struct always_false : std::false_type {};
+
+ struct TypeMap {
+ using type = std::invoke_result_t<decltype([]() {
+ if constexpr (std::is_same_v<T, int64_t>) {
+ return std::type_identity<PerfettoTeHlExtraCounterInt64>{};
+ } else if constexpr (std::is_same_v<T, double>) {
+ return std::type_identity<PerfettoTeHlExtraCounterDouble>{};
+ } else {
+ return std::type_identity<void>{};
+ }
+ })>::type;
+
+ static constexpr int enum_value = []() {
+ if constexpr (std::is_same_v<T, int64_t>) {
+ return PERFETTO_TE_HL_EXTRA_TYPE_COUNTER_INT64;
+ } else if constexpr (std::is_same_v<T, double>) {
+ return PERFETTO_TE_HL_EXTRA_TYPE_COUNTER_DOUBLE;
+ } else {
+ static_assert(always_false<T>::value, "Unsupported type");
+ return 0; // Never reached, just to satisfy return type
+ }
+ }();
+ };
+
+ Counter() {
+ static_assert(!std::is_same_v<typename TypeMap::type, void>,
+ "Unsupported type for Counter");
+
+ typename TypeMap::type counter;
+ counter.header = {TypeMap::enum_value};
+ counter_ = std::move(counter);
+ }
+
+ void set_value(T value) {
+ if constexpr (std::is_same_v<T, int64_t>) {
+ counter_.value = value;
+ } else if constexpr (std::is_same_v<T, double>) {
+ counter_.value = value;
+ }
+ }
+
+ static void delete_counter(Counter* counter) {
+ delete counter;
+ }
+
+ const TypeMap::type* get() const {
+ return &counter_;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Counter);
+ TypeMap::type counter_;
+};
+
+/**
+ * @brief Represents a debug argument for a trace event.
+ * @tparam T The data type of the argument (bool, int64_t, double, const char*).
+ */
+template <typename T>
+class DebugArg {
+ public:
+ template <typename>
+ struct always_false : std::false_type {};
+
+ struct TypeMap {
+ using type = std::invoke_result_t<decltype([]() {
+ if constexpr (std::is_same_v<T, bool>) {
+ return std::type_identity<PerfettoTeHlExtraDebugArgBool>{};
+ } else if constexpr (std::is_same_v<T, int64_t>) {
+ return std::type_identity<PerfettoTeHlExtraDebugArgInt64>{};
+ } else if constexpr (std::is_same_v<T, double>) {
+ return std::type_identity<PerfettoTeHlExtraDebugArgDouble>{};
+ } else if constexpr (std::is_same_v<T, const char*>) {
+ return std::type_identity<PerfettoTeHlExtraDebugArgString>{};
+ } else {
+ return std::type_identity<void>{};
+ }
+ })>::type;
+
+ static constexpr int enum_value = []() {
+ if constexpr (std::is_same_v<T, bool>) {
+ return PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_BOOL;
+ } else if constexpr (std::is_same_v<T, int64_t>) {
+ return PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_INT64;
+ } else if constexpr (std::is_same_v<T, double>) {
+ return PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_DOUBLE;
+ } else if constexpr (std::is_same_v<T, const char*>) {
+ return PERFETTO_TE_HL_EXTRA_TYPE_DEBUG_ARG_STRING;
+ } else {
+ static_assert(always_false<T>::value, "Unsupported type");
+ return 0; // Never reached, just to satisfy return type
+ }
+ }();
+ };
+
+ DebugArg(const std::string& name) : name_(name) {
+ static_assert(!std::is_same_v<typename TypeMap::type, void>,
+ "Unsupported type for DebugArg");
+
+ typename TypeMap::type arg;
+ arg.header = {TypeMap::enum_value};
+ arg.name = name_.c_str();
+ arg_ = std::move(arg);
+ }
+
+ void set_value(T value) {
+ if constexpr (std::is_same_v<T, const char*>) {
+ arg_.value = value;
+ } else if constexpr (std::is_same_v<T, int64_t>) {
+ arg_.value = value;
+ } else if constexpr (std::is_same_v<T, bool>) {
+ arg_.value = value;
+ } else if constexpr (std::is_same_v<T, double>) {
+ arg_.value = value;
+ }
+ }
+
+ static void delete_arg(DebugArg* arg) {
+ delete arg;
+ }
+
+ const TypeMap::type* get() const {
+ return &arg_;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DebugArg);
+ TypeMap::type arg_;
+ const std::string name_;
+};
+
+template <typename T>
+class ProtoField {
+ public:
+ template <typename>
+ struct always_false : std::false_type {};
+
+ struct TypeMap {
+ using type = std::invoke_result_t<decltype([]() {
+ if constexpr (std::is_same_v<T, int64_t>) {
+ return std::type_identity<PerfettoTeHlProtoFieldVarInt>{};
+ } else if constexpr (std::is_same_v<T, double>) {
+ return std::type_identity<PerfettoTeHlProtoFieldDouble>{};
+ } else if constexpr (std::is_same_v<T, const char*>) {
+ return std::type_identity<PerfettoTeHlProtoFieldCstr>{};
+ } else {
+ return std::type_identity<void>{};
+ }
+ })>::type;
+
+ static constexpr PerfettoTeHlProtoFieldType enum_value = []() {
+ if constexpr (std::is_same_v<T, int64_t>) {
+ return PERFETTO_TE_HL_PROTO_TYPE_VARINT;
+ } else if constexpr (std::is_same_v<T, double>) {
+ return PERFETTO_TE_HL_PROTO_TYPE_DOUBLE;
+ } else if constexpr (std::is_same_v<T, const char*>) {
+ return PERFETTO_TE_HL_PROTO_TYPE_CSTR;
+ } else {
+ static_assert(always_false<T>::value, "Unsupported type");
+ return 0; // Never reached, just to satisfy return type
+ }
+ }();
+ };
+
+ ProtoField() {
+ static_assert(!std::is_same_v<typename TypeMap::type, void>,
+ "Unsupported type for ProtoField");
+
+ typename TypeMap::type arg;
+ arg.header.type = TypeMap::enum_value;
+ arg_ = std::move(arg);
+ }
+
+ void set_value(uint32_t id, T value) {
+ if constexpr (std::is_same_v<T, int64_t>) {
+ arg_.header.id = id;
+ arg_.value = value;
+ } else if constexpr (std::is_same_v<T, double>) {
+ arg_.header.id = id;
+ arg_.value = value;
+ } else if constexpr (std::is_same_v<T, const char*>) {
+ arg_.header.id = id;
+ arg_.str = value;
+ }
+ }
+
+ static void delete_field(ProtoField* field) {
+ delete field;
+ }
+
+ const TypeMap::type* get() const {
+ return &arg_;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ProtoField);
+ TypeMap::type arg_;
+};
+
+class ProtoFieldNested {
+ public:
+ ProtoFieldNested();
+
+ void add_field(PerfettoTeHlProtoField* field);
+ void set_id(uint32_t id);
+ static void delete_field(ProtoFieldNested* field);
+
+ const PerfettoTeHlProtoFieldNested* get() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ProtoFieldNested);
+ PerfettoTeHlProtoFieldNested field_;
+ // These PerfettoTeHlProtoField pointers are really pointers to all the other
+ // types of protos: PerfettoTeHlProtoFieldVarInt, PerfettoTeHlProtoFieldVarInt,
+ // PerfettoTeHlProtoFieldVarInt, PerfettoTeHlProtoFieldNested. Those objects are
+ // individually managed by Java.
+ std::vector<PerfettoTeHlProtoField*> fields_;
+};
+
+class Proto {
+ public:
+ Proto();
+
+ void add_field(PerfettoTeHlProtoField* field);
+ void clear_fields();
+ static void delete_proto(Proto* proto);
+
+ const PerfettoTeHlExtraProtoFields* get() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Proto);
+ PerfettoTeHlExtraProtoFields proto_;
+ // These PerfettoTeHlProtoField pointers are really pointers to all the other
+ // types of protos: PerfettoTeHlProtoFieldVarInt, PerfettoTeHlProtoFieldVarInt,
+ // PerfettoTeHlProtoFieldVarInt, PerfettoTeHlProtoFieldNested. Those objects are
+ // individually managed by Java.
+ std::vector<PerfettoTeHlProtoField*> fields_;
+};
+
+class Session {
+ public:
+ Session(bool is_backend_in_process, void* buf, size_t len);
+ ~Session();
+ Session(const Session&) = delete;
+ Session& operator=(const Session&) = delete;
+
+ bool FlushBlocking(uint32_t timeout_ms);
+ void StopBlocking();
+ std::vector<uint8_t> ReadBlocking();
+
+ static void delete_session(Session* session);
+
+ struct PerfettoTracingSessionImpl* session_ = nullptr;
+};
+
+/**
+ * @brief Activates a trigger.
+ * @param name The name of the trigger.
+ * @param ttl_ms The time-to-live of the trigger in milliseconds.
+ */
+void activate_trigger(const char* name, uint32_t ttl_ms);
+} // namespace tracing_perfetto
diff --git a/libs/tracing_perfetto/tests/Android.bp b/libs/tracing_perfetto/tests/Android.bp
index d203467..79fb704 100644
--- a/libs/tracing_perfetto/tests/Android.bp
+++ b/libs/tracing_perfetto/tests/Android.bp
@@ -36,7 +36,6 @@
"android.os.flags-aconfig-cc-host",
"libbase",
"libperfetto_c",
- "liblog",
"libprotobuf-cpp-lite",
"libtracing_perfetto",
],
@@ -44,5 +43,8 @@
"tracing_perfetto_test.cpp",
"utils.cpp",
],
+ local_include_dirs: [
+ "include",
+ ],
test_suites: ["device-tests"],
}
diff --git a/libs/tracing_perfetto/tests/include/utils.h b/libs/tracing_perfetto/tests/include/utils.h
new file mode 100644
index 0000000..b2630e1
--- /dev/null
+++ b/libs/tracing_perfetto/tests/include/utils.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2024 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.
+ */
+
+// Copied from //external/perfetto/src/shared_lib/test/utils.h
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <cassert>
+#include <condition_variable>
+#include <cstdint>
+#include <functional>
+#include <iterator>
+#include <memory>
+#include <mutex>
+#include <ostream>
+#include <string>
+#include <vector>
+
+#include "perfetto/public/abi/pb_decoder_abi.h"
+#include "perfetto/public/pb_utils.h"
+#include "perfetto/public/tracing_session.h"
+
+// Pretty printer for gtest
+void PrintTo(const PerfettoPbDecoderField& field, std::ostream*);
+
+namespace perfetto {
+namespace shlib {
+namespace test_utils {
+
+class WaitableEvent {
+ public:
+ WaitableEvent() = default;
+ void Notify() {
+ std::unique_lock<std::mutex> lock(m_);
+ notified_ = true;
+ cv_.notify_one();
+ }
+ bool WaitForNotification() {
+ std::unique_lock<std::mutex> lock(m_);
+ cv_.wait(lock, [this] { return notified_; });
+ return notified_;
+ }
+ bool IsNotified() {
+ std::unique_lock<std::mutex> lock(m_);
+ return notified_;
+ }
+
+ private:
+ std::mutex m_;
+ std::condition_variable cv_;
+ bool notified_ = false;
+};
+
+class TracingSession {
+ public:
+ class Builder {
+ public:
+ Builder() = default;
+ Builder& add_enabled_category(std::string category) {
+ enabled_categories_.push_back(std::move(category));
+ return *this;
+ }
+ Builder& add_disabled_category(std::string category) {
+ disabled_categories_.push_back(std::move(category));
+ return *this;
+ }
+ Builder& add_atrace_category(std::string category) {
+ atrace_categories_.push_back(std::move(category));
+ return *this;
+ }
+ Builder& add_atrace_category_prefer_sdk(std::string category) {
+ atrace_categories_prefer_sdk_.push_back(std::move(category));
+ return *this;
+ }
+ TracingSession Build();
+
+ private:
+ std::vector<std::string> enabled_categories_;
+ std::vector<std::string> disabled_categories_;
+ std::vector<std::string> atrace_categories_;
+ std::vector<std::string> atrace_categories_prefer_sdk_;
+ };
+
+ static TracingSession Adopt(struct PerfettoTracingSessionImpl*);
+ static TracingSession FromBytes(void *buf, size_t len);
+
+ TracingSession(TracingSession&&) noexcept;
+
+ ~TracingSession();
+
+ struct PerfettoTracingSessionImpl* session() const {
+ return session_;
+ }
+
+ bool FlushBlocking(uint32_t timeout_ms);
+ void WaitForStopped();
+ void StopBlocking();
+ std::vector<uint8_t> ReadBlocking();
+
+ private:
+ TracingSession() = default;
+ struct PerfettoTracingSessionImpl* session_;
+ std::unique_ptr<WaitableEvent> stopped_;
+};
+
+} // namespace test_utils
+} // namespace shlib
+} // namespace perfetto
+
+#endif // UTILS_H
diff --git a/libs/tracing_perfetto/tests/tracing_perfetto_test.cpp b/libs/tracing_perfetto/tests/tracing_perfetto_test.cpp
index e9fee2e..b21a090 100644
--- a/libs/tracing_perfetto/tests/tracing_perfetto_test.cpp
+++ b/libs/tracing_perfetto/tests/tracing_perfetto_test.cpp
@@ -22,6 +22,7 @@
#include <unistd.h>
#include "gtest/gtest.h"
+
#include "perfetto/public/abi/data_source_abi.h"
#include "perfetto/public/abi/heap_buffer.h"
#include "perfetto/public/abi/pb_decoder_abi.h"
diff --git a/libs/tracing_perfetto/tests/utils.cpp b/libs/tracing_perfetto/tests/utils.cpp
index 8c4d4a8..af61bc2 100644
--- a/libs/tracing_perfetto/tests/utils.cpp
+++ b/libs/tracing_perfetto/tests/utils.cpp
@@ -34,36 +34,17 @@
namespace perfetto {
namespace shlib {
namespace test_utils {
-namespace {
-
-std::string ToHexChars(uint8_t val) {
- std::string ret;
- uint8_t high_nibble = (val & 0xF0) >> 4;
- uint8_t low_nibble = (val & 0xF);
- static const char hex_chars[] = "0123456789ABCDEF";
- ret.push_back(hex_chars[high_nibble]);
- ret.push_back(hex_chars[low_nibble]);
- return ret;
-}
-
-} // namespace
-
TracingSession TracingSession::Builder::Build() {
perfetto::protos::TraceConfig trace_config;
trace_config.add_buffers()->set_size_kb(1024);
- auto* track_event_ds_config = trace_config.add_data_sources()->mutable_config();
- auto* ftrace_ds_config = trace_config.add_data_sources()->mutable_config();
-
- track_event_ds_config->set_name("track_event");
- track_event_ds_config->set_target_buffer(0);
-
- ftrace_ds_config->set_name("linux.ftrace");
- ftrace_ds_config->set_target_buffer(0);
-
{
- auto* ftrace_config = ftrace_ds_config->mutable_ftrace_config();
if (!atrace_categories_.empty()) {
+ auto* ftrace_ds_config = trace_config.add_data_sources()->mutable_config();
+ ftrace_ds_config->set_name("linux.ftrace");
+ ftrace_ds_config->set_target_buffer(0);
+
+ auto* ftrace_config = ftrace_ds_config->mutable_ftrace_config();
ftrace_config->add_ftrace_events("ftrace/print");
for (const std::string& cat : atrace_categories_) {
ftrace_config->add_atrace_categories(cat);
@@ -76,8 +57,14 @@
}
{
- auto* track_event_config = track_event_ds_config->mutable_track_event_config();
if (!enabled_categories_.empty() || !disabled_categories_.empty()) {
+ auto* track_event_ds_config = trace_config.add_data_sources()->mutable_config();
+
+ track_event_ds_config->set_name("track_event");
+ track_event_ds_config->set_target_buffer(0);
+
+ auto* track_event_config = track_event_ds_config->mutable_track_event_config();
+
for (const std::string& cat : enabled_categories_) {
track_event_config->add_enabled_categories(cat);
}
@@ -88,13 +75,17 @@
}
}
- struct PerfettoTracingSessionImpl* ts =
- PerfettoTracingSessionCreate(PERFETTO_BACKEND_SYSTEM);
-
std::string trace_config_string;
trace_config.SerializeToString(&trace_config_string);
- PerfettoTracingSessionSetup(ts, trace_config_string.data(), trace_config_string.length());
+ return TracingSession::FromBytes(trace_config_string.data(), trace_config_string.length());
+}
+
+TracingSession TracingSession::FromBytes(void *buf, size_t len) {
+ struct PerfettoTracingSessionImpl* ts =
+ PerfettoTracingSessionCreate(PERFETTO_BACKEND_SYSTEM);
+
+ PerfettoTracingSessionSetup(ts, buf, len);
// Fails to start here
PerfettoTracingSessionStartBlocking(ts);
@@ -177,39 +168,3 @@
} // namespace test_utils
} // namespace shlib
} // namespace perfetto
-
-void PrintTo(const PerfettoPbDecoderField& field, std::ostream* pos) {
- std::ostream& os = *pos;
- PerfettoPbDecoderStatus status =
- static_cast<PerfettoPbDecoderStatus>(field.status);
- switch (status) {
- case PERFETTO_PB_DECODER_ERROR:
- os << "MALFORMED PROTOBUF";
- break;
- case PERFETTO_PB_DECODER_DONE:
- os << "DECODER DONE";
- break;
- case PERFETTO_PB_DECODER_OK:
- switch (field.wire_type) {
- case PERFETTO_PB_WIRE_TYPE_DELIMITED:
- os << "\"";
- for (size_t i = 0; i < field.value.delimited.len; i++) {
- os << perfetto::shlib::test_utils::ToHexChars(
- field.value.delimited.start[i])
- << " ";
- }
- os << "\"";
- break;
- case PERFETTO_PB_WIRE_TYPE_VARINT:
- os << "varint: " << field.value.integer64;
- break;
- case PERFETTO_PB_WIRE_TYPE_FIXED32:
- os << "fixed32: " << field.value.integer32;
- break;
- case PERFETTO_PB_WIRE_TYPE_FIXED64:
- os << "fixed64: " << field.value.integer64;
- break;
- }
- break;
- }
-}
diff --git a/libs/tracing_perfetto/tests/utils.h b/libs/tracing_perfetto/tests/utils.h
deleted file mode 100644
index 8edb414..0000000
--- a/libs/tracing_perfetto/tests/utils.h
+++ /dev/null
@@ -1,457 +0,0 @@
-/*
- * Copyright 2024 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.
- */
-
-// Copied from //external/perfetto/src/shared_lib/test/utils.h
-
-#ifndef UTILS_H
-#define UTILS_H
-
-#include <cassert>
-#include <condition_variable>
-#include <cstdint>
-#include <functional>
-#include <iterator>
-#include <memory>
-#include <mutex>
-#include <ostream>
-#include <string>
-#include <vector>
-
-#include "gmock/gmock-matchers.h"
-#include "gmock/gmock-more-matchers.h"
-#include "gtest/gtest-matchers.h"
-#include "gtest/gtest.h"
-#include "perfetto/public/abi/pb_decoder_abi.h"
-#include "perfetto/public/pb_utils.h"
-#include "perfetto/public/tracing_session.h"
-
-// Pretty printer for gtest
-void PrintTo(const PerfettoPbDecoderField& field, std::ostream*);
-
-namespace perfetto {
-namespace shlib {
-namespace test_utils {
-
-class WaitableEvent {
- public:
- WaitableEvent() = default;
- void Notify() {
- std::unique_lock<std::mutex> lock(m_);
- notified_ = true;
- cv_.notify_one();
- }
- bool WaitForNotification() {
- std::unique_lock<std::mutex> lock(m_);
- cv_.wait(lock, [this] { return notified_; });
- return notified_;
- }
- bool IsNotified() {
- std::unique_lock<std::mutex> lock(m_);
- return notified_;
- }
-
- private:
- std::mutex m_;
- std::condition_variable cv_;
- bool notified_ = false;
-};
-
-class TracingSession {
- public:
- class Builder {
- public:
- Builder() = default;
- Builder& add_enabled_category(std::string category) {
- enabled_categories_.push_back(std::move(category));
- return *this;
- }
- Builder& add_disabled_category(std::string category) {
- disabled_categories_.push_back(std::move(category));
- return *this;
- }
- Builder& add_atrace_category(std::string category) {
- atrace_categories_.push_back(std::move(category));
- return *this;
- }
- Builder& add_atrace_category_prefer_sdk(std::string category) {
- atrace_categories_prefer_sdk_.push_back(std::move(category));
- return *this;
- }
- TracingSession Build();
-
- private:
- std::vector<std::string> enabled_categories_;
- std::vector<std::string> disabled_categories_;
- std::vector<std::string> atrace_categories_;
- std::vector<std::string> atrace_categories_prefer_sdk_;
- };
-
- static TracingSession Adopt(struct PerfettoTracingSessionImpl*);
-
- TracingSession(TracingSession&&) noexcept;
-
- ~TracingSession();
-
- struct PerfettoTracingSessionImpl* session() const {
- return session_;
- }
-
- bool FlushBlocking(uint32_t timeout_ms);
- void WaitForStopped();
- void StopBlocking();
- std::vector<uint8_t> ReadBlocking();
-
- private:
- TracingSession() = default;
- struct PerfettoTracingSessionImpl* session_;
- std::unique_ptr<WaitableEvent> stopped_;
-};
-
-template <typename FieldSkipper>
-class FieldViewBase {
- public:
- class Iterator {
- public:
- using iterator_category = std::input_iterator_tag;
- using value_type = const PerfettoPbDecoderField;
- using pointer = value_type;
- using reference = value_type;
- reference operator*() const {
- struct PerfettoPbDecoder decoder;
- decoder.read_ptr = read_ptr_;
- decoder.end_ptr = end_ptr_;
- struct PerfettoPbDecoderField field;
- do {
- field = PerfettoPbDecoderParseField(&decoder);
- } while (field.status == PERFETTO_PB_DECODER_OK &&
- skipper_.ShouldSkip(field));
- return field;
- }
- Iterator& operator++() {
- struct PerfettoPbDecoder decoder;
- decoder.read_ptr = read_ptr_;
- decoder.end_ptr = end_ptr_;
- PerfettoPbDecoderSkipField(&decoder);
- read_ptr_ = decoder.read_ptr;
- AdvanceToFirstInterestingField();
- return *this;
- }
- Iterator operator++(int) {
- Iterator tmp = *this;
- ++(*this);
- return tmp;
- }
-
- friend bool operator==(const Iterator& a, const Iterator& b) {
- return a.read_ptr_ == b.read_ptr_;
- }
- friend bool operator!=(const Iterator& a, const Iterator& b) {
- return a.read_ptr_ != b.read_ptr_;
- }
-
- private:
- Iterator(const uint8_t* read_ptr, const uint8_t* end_ptr,
- const FieldSkipper& skipper)
- : read_ptr_(read_ptr), end_ptr_(end_ptr), skipper_(skipper) {
- AdvanceToFirstInterestingField();
- }
- void AdvanceToFirstInterestingField() {
- struct PerfettoPbDecoder decoder;
- decoder.read_ptr = read_ptr_;
- decoder.end_ptr = end_ptr_;
- struct PerfettoPbDecoderField field;
- const uint8_t* prev_read_ptr;
- do {
- prev_read_ptr = decoder.read_ptr;
- field = PerfettoPbDecoderParseField(&decoder);
- } while (field.status == PERFETTO_PB_DECODER_OK &&
- skipper_.ShouldSkip(field));
- if (field.status == PERFETTO_PB_DECODER_OK) {
- read_ptr_ = prev_read_ptr;
- } else {
- read_ptr_ = decoder.read_ptr;
- }
- }
- friend class FieldViewBase<FieldSkipper>;
- const uint8_t* read_ptr_;
- const uint8_t* end_ptr_;
- const FieldSkipper& skipper_;
- };
- using value_type = const PerfettoPbDecoderField;
- using const_iterator = Iterator;
- template <typename... Args>
- explicit FieldViewBase(const uint8_t* begin, const uint8_t* end, Args... args)
- : begin_(begin), end_(end), s_(args...) {
- }
- template <typename... Args>
- explicit FieldViewBase(const std::vector<uint8_t>& data, Args... args)
- : FieldViewBase(data.data(), data.data() + data.size(), args...) {
- }
- template <typename... Args>
- explicit FieldViewBase(const struct PerfettoPbDecoderField& field,
- Args... args)
- : s_(args...) {
- if (field.wire_type != PERFETTO_PB_WIRE_TYPE_DELIMITED) {
- abort();
- }
- begin_ = field.value.delimited.start;
- end_ = begin_ + field.value.delimited.len;
- }
- Iterator begin() const {
- return Iterator(begin_, end_, s_);
- }
- Iterator end() const {
- return Iterator(end_, end_, s_);
- }
- PerfettoPbDecoderField front() const {
- return *begin();
- }
-
- size_t size() const {
- size_t count = 0;
- for (auto field : *this) {
- (void)field;
- count++;
- }
- return count;
- }
-
- bool ok() const {
- for (auto field : *this) {
- if (field.status != PERFETTO_PB_DECODER_OK) {
- return false;
- }
- }
- return true;
- }
-
- private:
- const uint8_t* begin_;
- const uint8_t* end_;
- FieldSkipper s_;
-};
-
-// Pretty printer for gtest
-template <typename FieldSkipper>
-void PrintTo(const FieldViewBase<FieldSkipper>& field_view, std::ostream* pos) {
- std::ostream& os = *pos;
- os << "{";
- for (PerfettoPbDecoderField f : field_view) {
- PrintTo(f, pos);
- os << ", ";
- }
- os << "}";
-}
-
-class IdFieldSkipper {
- public:
- explicit IdFieldSkipper(uint32_t id) : id_(id) {
- }
- explicit IdFieldSkipper(int32_t id) : id_(static_cast<uint32_t>(id)) {
- }
- bool ShouldSkip(const struct PerfettoPbDecoderField& field) const {
- return field.id != id_;
- }
-
- private:
- uint32_t id_;
-};
-
-class NoFieldSkipper {
- public:
- NoFieldSkipper() = default;
- bool ShouldSkip(const struct PerfettoPbDecoderField&) const {
- return false;
- }
-};
-
-// View over all the fields of a contiguous serialized protobuf message.
-//
-// Examples:
-//
-// for (struct PerfettoPbDecoderField field : FieldView(msg_begin, msg_end)) {
-// //...
-// }
-// FieldView fields2(/*PerfettoPbDecoderField*/ nested_field);
-// FieldView fields3(/*std::vector<uint8_t>*/ data);
-// size_t num = fields1.size(); // The number of fields.
-// bool ok = fields1.ok(); // Checks that the message is not malformed.
-using FieldView = FieldViewBase<NoFieldSkipper>;
-
-// Like `FieldView`, but only considers fields with a specific id.
-//
-// Examples:
-//
-// IdFieldView fields(msg_begin, msg_end, id)
-using IdFieldView = FieldViewBase<IdFieldSkipper>;
-
-// Matches a PerfettoPbDecoderField with the specified id. Accepts another
-// matcher to match the contents of the field.
-//
-// Example:
-// PerfettoPbDecoderField field = ...
-// EXPECT_THAT(field, PbField(900, VarIntField(5)));
-template <typename M>
-auto PbField(int32_t id, M m) {
- return testing::AllOf(
- testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
- testing::Field(&PerfettoPbDecoderField::id, id), m);
-}
-
-// Matches a PerfettoPbDecoderField submessage field. Accepts a container
-// matcher for the subfields.
-//
-// Example:
-// PerfettoPbDecoderField field = ...
-// EXPECT_THAT(field, MsgField(ElementsAre(...)));
-template <typename M>
-auto MsgField(M m) {
- auto f = [](const PerfettoPbDecoderField& field) { return FieldView(field); };
- return testing::AllOf(
- testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
- testing::Field(&PerfettoPbDecoderField::wire_type,
- PERFETTO_PB_WIRE_TYPE_DELIMITED),
- testing::ResultOf(f, m));
-}
-
-// Matches a PerfettoPbDecoderField length delimited field. Accepts a string
-// matcher.
-//
-// Example:
-// PerfettoPbDecoderField field = ...
-// EXPECT_THAT(field, StringField("string"));
-template <typename M>
-auto StringField(M m) {
- auto f = [](const PerfettoPbDecoderField& field) {
- return std::string(
- reinterpret_cast<const char*>(field.value.delimited.start),
- field.value.delimited.len);
- };
- return testing::AllOf(
- testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
- testing::Field(&PerfettoPbDecoderField::wire_type,
- PERFETTO_PB_WIRE_TYPE_DELIMITED),
- testing::ResultOf(f, m));
-}
-
-// Matches a PerfettoPbDecoderField VarInt field. Accepts an integer matcher
-//
-// Example:
-// PerfettoPbDecoderField field = ...
-// EXPECT_THAT(field, VarIntField(1)));
-template <typename M>
-auto VarIntField(M m) {
- auto f = [](const PerfettoPbDecoderField& field) {
- return field.value.integer64;
- };
- return testing::AllOf(
- testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
- testing::Field(&PerfettoPbDecoderField::wire_type,
- PERFETTO_PB_WIRE_TYPE_VARINT),
- testing::ResultOf(f, m));
-}
-
-// Matches a PerfettoPbDecoderField fixed64 field. Accepts an integer matcher
-//
-// Example:
-// PerfettoPbDecoderField field = ...
-// EXPECT_THAT(field, Fixed64Field(1)));
-template <typename M>
-auto Fixed64Field(M m) {
- auto f = [](const PerfettoPbDecoderField& field) {
- return field.value.integer64;
- };
- return testing::AllOf(
- testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
- testing::Field(&PerfettoPbDecoderField::wire_type,
- PERFETTO_PB_WIRE_TYPE_FIXED64),
- testing::ResultOf(f, m));
-}
-
-// Matches a PerfettoPbDecoderField fixed32 field. Accepts an integer matcher
-//
-// Example:
-// PerfettoPbDecoderField field = ...
-// EXPECT_THAT(field, Fixed32Field(1)));
-template <typename M>
-auto Fixed32Field(M m) {
- auto f = [](const PerfettoPbDecoderField& field) {
- return field.value.integer32;
- };
- return testing::AllOf(
- testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
- testing::Field(&PerfettoPbDecoderField::wire_type,
- PERFETTO_PB_WIRE_TYPE_FIXED32),
- testing::ResultOf(f, m));
-}
-
-// Matches a PerfettoPbDecoderField double field. Accepts a double matcher
-//
-// Example:
-// PerfettoPbDecoderField field = ...
-// EXPECT_THAT(field, DoubleField(1.0)));
-template <typename M>
-auto DoubleField(M m) {
- auto f = [](const PerfettoPbDecoderField& field) {
- return field.value.double_val;
- };
- return testing::AllOf(
- testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
- testing::Field(&PerfettoPbDecoderField::wire_type,
- PERFETTO_PB_WIRE_TYPE_FIXED64),
- testing::ResultOf(f, m));
-}
-
-// Matches a PerfettoPbDecoderField float field. Accepts a float matcher
-//
-// Example:
-// PerfettoPbDecoderField field = ...
-// EXPECT_THAT(field, FloatField(1.0)));
-template <typename M>
-auto FloatField(M m) {
- auto f = [](const PerfettoPbDecoderField& field) {
- return field.value.float_val;
- };
- return testing::AllOf(
- testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
- testing::Field(&PerfettoPbDecoderField::wire_type,
- PERFETTO_PB_WIRE_TYPE_FIXED32),
- testing::ResultOf(f, m));
-}
-
-// Matches a PerfettoPbDecoderField submessage field. Accepts a container
-// matcher for the subfields.
-//
-// Example:
-// PerfettoPbDecoderField field = ...
-// EXPECT_THAT(field, AllFieldsWithId(900, ElementsAre(...)));
-template <typename M>
-auto AllFieldsWithId(int32_t id, M m) {
- auto f = [id](const PerfettoPbDecoderField& field) {
- return IdFieldView(field, id);
- };
- return testing::AllOf(
- testing::Field(&PerfettoPbDecoderField::status, PERFETTO_PB_DECODER_OK),
- testing::Field(&PerfettoPbDecoderField::wire_type,
- PERFETTO_PB_WIRE_TYPE_DELIMITED),
- testing::ResultOf(f, m));
-}
-
-} // namespace test_utils
-} // namespace shlib
-} // namespace perfetto
-
-#endif // UTILS_H
diff --git a/libs/tracing_perfetto/tracing_perfetto.cpp b/libs/tracing_perfetto/tracing_perfetto.cpp
index c35e078..4b70213 100644
--- a/libs/tracing_perfetto/tracing_perfetto.cpp
+++ b/libs/tracing_perfetto/tracing_perfetto.cpp
@@ -17,6 +17,7 @@
#include "tracing_perfetto.h"
#include <cutils/trace.h>
+
#include <cstdarg>
#include "perfetto/public/te_category_macros.h"
@@ -43,8 +44,10 @@
void traceFormatBegin(uint64_t category, const char* fmt, ...) {
struct PerfettoTeCategory* perfettoTeCategory =
internal::toPerfettoCategory(category);
- const bool preferAtrace = internal::shouldPreferAtrace(perfettoTeCategory, category);
- const bool preferPerfetto = internal::isPerfettoCategoryEnabled(perfettoTeCategory);
+ const bool preferAtrace =
+ internal::shouldPreferAtrace(perfettoTeCategory, category);
+ const bool preferPerfetto =
+ internal::isPerfettoCategoryEnabled(perfettoTeCategory);
if (CC_LIKELY(!(preferAtrace || preferPerfetto))) {
return;
}
@@ -57,7 +60,6 @@
vsnprintf(buf, BUFFER_SIZE, fmt, ap);
va_end(ap);
-
if (preferAtrace) {
atrace_begin(category, buf);
} else if (preferPerfetto) {
@@ -99,26 +101,28 @@
}
void traceAsyncBeginForTrack(uint64_t category, const char* name,
- const char* trackName, int32_t cookie) {
+ const char* trackName, int32_t cookie) {
struct PerfettoTeCategory* perfettoTeCategory =
internal::toPerfettoCategory(category);
if (internal::shouldPreferAtrace(perfettoTeCategory, category)) {
atrace_async_for_track_begin(category, trackName, name, cookie);
} else if (internal::isPerfettoCategoryEnabled(perfettoTeCategory)) {
- internal::perfettoTraceAsyncBeginForTrack(*perfettoTeCategory, name, trackName, cookie);
+ internal::perfettoTraceAsyncBeginForTrack(*perfettoTeCategory, name,
+ trackName, cookie);
}
}
void traceAsyncEndForTrack(uint64_t category, const char* trackName,
- int32_t cookie) {
+ int32_t cookie) {
struct PerfettoTeCategory* perfettoTeCategory =
internal::toPerfettoCategory(category);
if (internal::shouldPreferAtrace(perfettoTeCategory, category)) {
atrace_async_for_track_end(category, trackName, cookie);
} else if (internal::isPerfettoCategoryEnabled(perfettoTeCategory)) {
- internal::perfettoTraceAsyncEndForTrack(*perfettoTeCategory, trackName, cookie);
+ internal::perfettoTraceAsyncEndForTrack(*perfettoTeCategory, trackName,
+ cookie);
}
}
@@ -136,8 +140,10 @@
void traceFormatInstant(uint64_t category, const char* fmt, ...) {
struct PerfettoTeCategory* perfettoTeCategory =
internal::toPerfettoCategory(category);
- const bool preferAtrace = internal::shouldPreferAtrace(perfettoTeCategory, category);
- const bool preferPerfetto = internal::isPerfettoCategoryEnabled(perfettoTeCategory);
+ const bool preferAtrace =
+ internal::shouldPreferAtrace(perfettoTeCategory, category);
+ const bool preferPerfetto =
+ internal::isPerfettoCategoryEnabled(perfettoTeCategory);
if (CC_LIKELY(!(preferAtrace || preferPerfetto))) {
return;
}
@@ -158,7 +164,7 @@
}
void traceInstantForTrack(uint64_t category, const char* trackName,
- const char* name) {
+ const char* name) {
struct PerfettoTeCategory* perfettoTeCategory =
internal::toPerfettoCategory(category);
@@ -181,20 +187,21 @@
}
void traceCounter32(uint64_t category, const char* name, int32_t value) {
- struct PerfettoTeCategory* perfettoTeCategory = internal::toPerfettoCategory(category);
+ struct PerfettoTeCategory* perfettoTeCategory =
+ internal::toPerfettoCategory(category);
if (internal::shouldPreferAtrace(perfettoTeCategory, category)) {
atrace_int(category, name, value);
} else if (internal::isPerfettoCategoryEnabled(perfettoTeCategory)) {
internal::perfettoTraceCounter(*perfettoTeCategory, name,
- static_cast<int64_t>(value));
+ static_cast<int64_t>(value));
}
}
bool isTagEnabled(uint64_t category) {
struct PerfettoTeCategory* perfettoTeCategory =
internal::toPerfettoCategory(category);
- return internal::isPerfettoCategoryEnabled(perfettoTeCategory)
- || atrace_is_tag_enabled(category);
+ return internal::isPerfettoCategoryEnabled(perfettoTeCategory) ||
+ atrace_is_tag_enabled(category);
}
} // namespace tracing_perfetto
diff --git a/libs/tracing_perfetto/tracing_perfetto_internal.cpp b/libs/tracing_perfetto/tracing_perfetto_internal.cpp
index 9a0042a..4478732 100644
--- a/libs/tracing_perfetto/tracing_perfetto_internal.cpp
+++ b/libs/tracing_perfetto/tracing_perfetto_internal.cpp
@@ -14,15 +14,16 @@
* limitations under the License.
*/
+// Should match the definitions in: frameworks/native/cmds/atrace/atrace.cpp
#define FRAMEWORK_CATEGORIES(C) \
C(always, "always", "Always category") \
- C(graphics, "graphics", "Graphics category") \
+ C(graphics, "gfx", "Graphics category") \
C(input, "input", "Input category") \
C(view, "view", "View category") \
C(webview, "webview", "WebView category") \
C(windowmanager, "wm", "WindowManager category") \
C(activitymanager, "am", "ActivityManager category") \
- C(syncmanager, "syncmanager", "SyncManager category") \
+ C(syncmanager, "sm", "SyncManager category") \
C(audio, "audio", "Audio category") \
C(video, "video", "Video category") \
C(camera, "camera", "Camera category") \
@@ -33,7 +34,7 @@
C(rs, "rs", "RS category") \
C(bionic, "bionic", "Bionic category") \
C(power, "power", "Power category") \
- C(packagemanager, "packagemanager", "PackageManager category") \
+ C(packagemanager, "pm", "PackageManager category") \
C(systemserver, "ss", "System Server category") \
C(database, "database", "Database category") \
C(network, "network", "Network category") \
@@ -47,7 +48,6 @@
#include <atomic>
#include <mutex>
-#include <android_os.h>
#include <android-base/properties.h>
#include <cutils/trace.h>
#include <inttypes.h>
@@ -228,14 +228,11 @@
}
void registerWithPerfetto(bool test) {
- if (!android::os::perfetto_sdk_tracing()) {
- return;
- }
-
static std::once_flag registration;
std::call_once(registration, [test]() {
struct PerfettoProducerInitArgs args = PERFETTO_PRODUCER_INIT_ARGS_INIT();
args.backends = test ? PERFETTO_BACKEND_IN_PROCESS : PERFETTO_BACKEND_SYSTEM;
+ args.shmem_size_hint_kb = 1024;
PerfettoProducerInit(args);
PerfettoTeInit();
PERFETTO_TE_REGISTER_CATEGORIES(FRAMEWORK_CATEGORIES);
@@ -253,15 +250,31 @@
void perfettoTraceAsyncBeginForTrack(const struct PerfettoTeCategory& category, const char* name,
const char* trackName, uint64_t cookie) {
PERFETTO_TE(
- category, PERFETTO_TE_SLICE_BEGIN(name),
- PERFETTO_TE_NAMED_TRACK(trackName, cookie, PerfettoTeProcessTrackUuid()));
+ category, PERFETTO_TE_SLICE_BEGIN(name),
+ PERFETTO_TE_PROTO_TRACK(
+ PerfettoTeNamedTrackUuid(trackName, cookie,
+ PerfettoTeProcessTrackUuid()),
+ PERFETTO_TE_PROTO_FIELD_CSTR(
+ perfetto_protos_TrackDescriptor_atrace_name_field_number,
+ trackName),
+ PERFETTO_TE_PROTO_FIELD_VARINT(
+ perfetto_protos_TrackDescriptor_parent_uuid_field_number,
+ PerfettoTeProcessTrackUuid())));
}
void perfettoTraceAsyncEndForTrack(const struct PerfettoTeCategory& category,
const char* trackName, uint64_t cookie) {
- PERFETTO_TE(
- category, PERFETTO_TE_SLICE_END(),
- PERFETTO_TE_NAMED_TRACK(trackName, cookie, PerfettoTeProcessTrackUuid()));
+ PERFETTO_TE(
+ category, PERFETTO_TE_SLICE_END(),
+ PERFETTO_TE_PROTO_TRACK(
+ PerfettoTeNamedTrackUuid(trackName, cookie,
+ PerfettoTeProcessTrackUuid()),
+ PERFETTO_TE_PROTO_FIELD_CSTR(
+ perfetto_protos_TrackDescriptor_atrace_name_field_number,
+ trackName),
+ PERFETTO_TE_PROTO_FIELD_VARINT(
+ perfetto_protos_TrackDescriptor_parent_uuid_field_number,
+ PerfettoTeProcessTrackUuid())));
}
void perfettoTraceAsyncBegin(const struct PerfettoTeCategory& category, const char* name,
@@ -281,14 +294,35 @@
void perfettoTraceInstantForTrack(const struct PerfettoTeCategory& category,
const char* trackName, const char* name) {
PERFETTO_TE(
- category, PERFETTO_TE_INSTANT(name),
- PERFETTO_TE_NAMED_TRACK(trackName, 1, PerfettoTeProcessTrackUuid()));
+ category, PERFETTO_TE_INSTANT(name),
+ PERFETTO_TE_PROTO_TRACK(
+ PerfettoTeNamedTrackUuid(trackName, 1,
+ PerfettoTeProcessTrackUuid()),
+ PERFETTO_TE_PROTO_FIELD_CSTR(
+ perfetto_protos_TrackDescriptor_atrace_name_field_number,
+ trackName),
+ PERFETTO_TE_PROTO_FIELD_VARINT(
+ perfetto_protos_TrackDescriptor_parent_uuid_field_number,
+ PerfettoTeProcessTrackUuid())));
}
void perfettoTraceCounter(const struct PerfettoTeCategory& category,
- [[maybe_unused]] const char* name, int64_t value) {
- PERFETTO_TE(category, PERFETTO_TE_COUNTER(),
- PERFETTO_TE_INT_COUNTER(value));
+ const char* name, int64_t value) {
+ PERFETTO_TE(
+ category, PERFETTO_TE_COUNTER(),
+ PERFETTO_TE_PROTO_TRACK(
+ PerfettoTeCounterTrackUuid(name,
+ PerfettoTeProcessTrackUuid()),
+ PERFETTO_TE_PROTO_FIELD_CSTR(
+ perfetto_protos_TrackDescriptor_atrace_name_field_number,
+ name),
+ PERFETTO_TE_PROTO_FIELD_VARINT(
+ perfetto_protos_TrackDescriptor_parent_uuid_field_number,
+ PerfettoTeProcessTrackUuid()),
+ PERFETTO_TE_PROTO_FIELD_BYTES(
+ perfetto_protos_TrackDescriptor_counter_field_number,
+ PERFETTO_NULL, 0)),
+ PERFETTO_TE_INT_COUNTER(value));
}
} // namespace internal
diff --git a/libs/tracing_perfetto/tracing_perfetto_internal.h b/libs/tracing_perfetto/tracing_perfetto_internal.h
index 3e1ac2a..0e3fb07 100644
--- a/libs/tracing_perfetto/tracing_perfetto_internal.h
+++ b/libs/tracing_perfetto/tracing_perfetto_internal.h
@@ -25,8 +25,6 @@
namespace internal {
-bool isPerfettoRegistered();
-
struct PerfettoTeCategory* toPerfettoCategory(uint64_t category);
void registerWithPerfetto(bool test = false);
diff --git a/libs/tracing_perfetto/tracing_sdk.cpp b/libs/tracing_perfetto/tracing_sdk.cpp
new file mode 100644
index 0000000..70b8be9
--- /dev/null
+++ b/libs/tracing_perfetto/tracing_sdk.cpp
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2024 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 "tracing_sdk.h"
+
+#include <android-base/logging.h>
+#include <cutils/trace.h>
+
+#include <cstdarg>
+#include <cstdlib>
+
+#include "perfetto/public/abi/producer_abi.h"
+#include "perfetto/public/te_category_macros.h"
+#include "perfetto/public/te_macros.h"
+#include "perfetto/public/track_event.h"
+#include "tracing_perfetto.h"
+
+namespace tracing_perfetto {
+void trace_event(int type, const PerfettoTeCategory* perfettoTeCategory,
+ const char* name, tracing_perfetto::Extra* extra) {
+ bool enabled = PERFETTO_UNLIKELY(PERFETTO_ATOMIC_LOAD_EXPLICIT(
+ perfettoTeCategory->enabled, PERFETTO_MEMORY_ORDER_RELAXED));
+ if (enabled) {
+ extra->push_extra(nullptr);
+ PerfettoTeHlEmitImpl(perfettoTeCategory->impl, type,
+ type == PERFETTO_TE_TYPE_COUNTER ? nullptr : name,
+ extra->get());
+ extra->clear_extras();
+ }
+}
+
+uint64_t get_process_track_uuid() {
+ return PerfettoTeProcessTrackUuid();
+}
+
+uint64_t get_thread_track_uuid(pid_t tid) {
+ // Cating a signed pid_t to unsigned
+ return PerfettoTeProcessTrackUuid() ^ PERFETTO_STATIC_CAST(uint64_t, tid);
+}
+
+Extra::Extra() {
+}
+
+void Extra::push_extra(PerfettoTeHlExtra* ptr) {
+ extras_.push_back(ptr);
+}
+
+void Extra::pop_extra() {
+ extras_.pop_back();
+}
+
+void Extra::clear_extras() {
+ extras_.clear();
+}
+
+void Extra::delete_extra(Extra* ptr) {
+ delete ptr;
+}
+
+PerfettoTeHlExtra* const* Extra::get() const {
+ return extras_.data();
+}
+
+Category::Category(const std::string& name, const std::string& tag,
+ const std::string& severity)
+ : category_({.enabled = &perfetto_atomic_false}),
+ name_(name),
+ tag_(tag),
+ severity_(severity) {
+}
+
+Category::~Category() {
+ unregister_category();
+}
+
+void Category::register_category() {
+ if (category_.impl) return;
+
+ std::vector<const char*> tags;
+ if (!tag_.empty()) tags.push_back(tag_.data());
+ if (!severity_.empty()) tags.push_back(severity_.data());
+
+ category_.desc = {name_.c_str(), name_.c_str(), tags.data(), tags.size()};
+
+ PerfettoTeCategoryRegister(&category_);
+ PerfettoTePublishCategories();
+}
+
+void Category::unregister_category() {
+ if (!category_.impl) return;
+
+ PerfettoTeCategoryUnregister(&category_);
+ PerfettoTePublishCategories();
+}
+
+bool Category::is_category_enabled() {
+ return PERFETTO_UNLIKELY(PERFETTO_ATOMIC_LOAD_EXPLICIT(
+ (category_).enabled, PERFETTO_MEMORY_ORDER_RELAXED));
+}
+
+const PerfettoTeCategory* Category::get() const {
+ return &category_;
+}
+
+void Category::delete_category(Category* ptr) {
+ delete ptr;
+}
+
+Flow::Flow() : flow_{} {
+}
+
+void Flow::set_process_flow(uint64_t id) {
+ flow_.header.type = PERFETTO_TE_HL_EXTRA_TYPE_FLOW;
+ PerfettoTeFlow ret = PerfettoTeProcessScopedFlow(id);
+ flow_.id = ret.id;
+}
+
+void Flow::set_process_terminating_flow(uint64_t id) {
+ flow_.header.type = PERFETTO_TE_HL_EXTRA_TYPE_TERMINATING_FLOW;
+ PerfettoTeFlow ret = PerfettoTeProcessScopedFlow(id);
+ flow_.id = ret.id;
+}
+
+const PerfettoTeHlExtraFlow* Flow::get() const {
+ return &flow_;
+}
+
+void Flow::delete_flow(Flow* ptr) {
+ delete ptr;
+}
+
+NamedTrack::NamedTrack(uint64_t id, uint64_t parent_uuid,
+ const std::string& name)
+ : name_(name),
+ track_{{PERFETTO_TE_HL_EXTRA_TYPE_NAMED_TRACK},
+ name_.data(),
+ id,
+ parent_uuid} {
+}
+
+const PerfettoTeHlExtraNamedTrack* NamedTrack::get() const {
+ return &track_;
+}
+
+void NamedTrack::delete_track(NamedTrack* ptr) {
+ delete ptr;
+}
+
+RegisteredTrack::RegisteredTrack(uint64_t id, uint64_t parent_uuid,
+ const std::string& name, bool is_counter)
+ : registered_track_{},
+ track_{{PERFETTO_TE_HL_EXTRA_TYPE_REGISTERED_TRACK},
+ &(registered_track_.impl)},
+ name_(name),
+ id_(id),
+ parent_uuid_(parent_uuid),
+ is_counter_(is_counter) {
+ register_track();
+}
+
+RegisteredTrack::~RegisteredTrack() {
+ unregister_track();
+}
+
+void RegisteredTrack::register_track() {
+ if (registered_track_.impl.descriptor) return;
+
+ if (is_counter_) {
+ PerfettoTeCounterTrackRegister(®istered_track_, name_.data(),
+ parent_uuid_);
+ } else {
+ PerfettoTeNamedTrackRegister(®istered_track_, name_.data(), id_,
+ parent_uuid_);
+ }
+}
+
+void RegisteredTrack::unregister_track() {
+ if (!registered_track_.impl.descriptor) return;
+ PerfettoTeRegisteredTrackUnregister(®istered_track_);
+}
+
+const PerfettoTeHlExtraRegisteredTrack* RegisteredTrack::get() const {
+ return &track_;
+}
+
+void RegisteredTrack::delete_track(RegisteredTrack* ptr) {
+ delete ptr;
+}
+
+Proto::Proto() : proto_({PERFETTO_TE_HL_EXTRA_TYPE_PROTO_FIELDS}, nullptr) {
+}
+
+void Proto::add_field(PerfettoTeHlProtoField* ptr) {
+ if (!fields_.empty()) {
+ fields_.pop_back();
+ }
+
+ fields_.push_back(ptr);
+ fields_.push_back(nullptr);
+ proto_.fields = fields_.data();
+}
+
+void Proto::clear_fields() {
+ fields_.clear();
+ proto_.fields = nullptr;
+}
+
+void Proto::delete_proto(Proto* ptr) {
+ delete ptr;
+}
+
+const PerfettoTeHlExtraProtoFields* Proto::get() const {
+ return &proto_;
+}
+
+ProtoFieldNested::ProtoFieldNested()
+ : field_({PERFETTO_TE_HL_PROTO_TYPE_NESTED}, nullptr) {
+}
+
+void ProtoFieldNested::add_field(PerfettoTeHlProtoField* ptr) {
+ if (!fields_.empty()) {
+ fields_.pop_back();
+ }
+
+ fields_.push_back(ptr);
+ fields_.push_back(nullptr);
+ field_.fields = fields_.data();
+}
+
+void ProtoFieldNested::set_id(uint32_t id) {
+ fields_.clear();
+ field_.header.id = id;
+ field_.fields = nullptr;
+}
+
+void ProtoFieldNested::delete_field(ProtoFieldNested* ptr) {
+ delete ptr;
+}
+
+const PerfettoTeHlProtoFieldNested* ProtoFieldNested::get() const {
+ return &field_;
+}
+
+Session::Session(bool is_backend_in_process, void* buf, size_t len) {
+ session_ = PerfettoTracingSessionCreate(is_backend_in_process
+ ? PERFETTO_BACKEND_IN_PROCESS
+ : PERFETTO_BACKEND_SYSTEM);
+
+ PerfettoTracingSessionSetup(session_, buf, len);
+
+ PerfettoTracingSessionStartBlocking(session_);
+}
+
+Session::~Session() {
+ PerfettoTracingSessionStopBlocking(session_);
+ PerfettoTracingSessionDestroy(session_);
+}
+
+bool Session::FlushBlocking(uint32_t timeout_ms) {
+ return PerfettoTracingSessionFlushBlocking(session_, timeout_ms);
+}
+
+void Session::StopBlocking() {
+ PerfettoTracingSessionStopBlocking(session_);
+}
+
+std::vector<uint8_t> Session::ReadBlocking() {
+ std::vector<uint8_t> data;
+ PerfettoTracingSessionReadTraceBlocking(
+ session_,
+ [](struct PerfettoTracingSessionImpl*, const void* trace_data,
+ size_t size, bool, void* user_arg) {
+ auto& dst = *static_cast<std::vector<uint8_t>*>(user_arg);
+ auto* src = static_cast<const uint8_t*>(trace_data);
+ dst.insert(dst.end(), src, src + size);
+ },
+ &data);
+ return data;
+}
+
+void Session::delete_session(Session* ptr) {
+ delete ptr;
+}
+
+void activate_trigger(const char* name, uint32_t ttl_ms) {
+ const char* names[] = {name, nullptr};
+ PerfettoProducerActivateTriggers(names, ttl_ms);
+}
+} // namespace tracing_perfetto
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 12230f9..87e213e 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -136,6 +136,7 @@
"GraphicBuffer.cpp",
"GraphicBufferAllocator.cpp",
"GraphicBufferMapper.cpp",
+ "PictureProfileHandle.cpp",
"PixelFormat.cpp",
"PublicFormat.cpp",
"StaticAsserts.cpp",
diff --git a/libs/ui/DisplayIdentification.cpp b/libs/ui/DisplayIdentification.cpp
index 8b13d78..78e84fc 100644
--- a/libs/ui/DisplayIdentification.cpp
+++ b/libs/ui/DisplayIdentification.cpp
@@ -19,10 +19,14 @@
#include <algorithm>
#include <cctype>
+#include <cstdint>
#include <numeric>
#include <optional>
#include <span>
+#include <string>
+#include <string_view>
+#include <ftl/concat.h>
#include <ftl/hash.h>
#include <log/log.h>
#include <ui/DisplayIdentification.h>
@@ -194,6 +198,21 @@
const uint16_t productId =
static_cast<uint16_t>(edid[kProductIdOffset] | (edid[kProductIdOffset + 1] << 8));
+ // Bytes 12-15: display serial number, in little-endian (LSB). This field is
+ // optional and its absence is marked by having all bytes set to 0x00.
+ // Values do not represent ASCII characters.
+ constexpr size_t kSerialNumberOffset = 12;
+ if (edid.size() < kSerialNumberOffset + sizeof(uint32_t)) {
+ ALOGE("Invalid EDID: block zero S/N is truncated.");
+ return {};
+ }
+ const uint32_t blockZeroSerialNumber = edid[kSerialNumberOffset] +
+ (edid[kSerialNumberOffset + 1] << 8) + (edid[kSerialNumberOffset + 2] << 16) +
+ (edid[kSerialNumberOffset + 3] << 24);
+ const auto hashedBlockZeroSNOpt = blockZeroSerialNumber == 0
+ ? std::nullopt
+ : ftl::stable_hash(std::string_view(std::to_string(blockZeroSerialNumber)));
+
constexpr size_t kManufactureWeekOffset = 16;
if (edid.size() < kManufactureWeekOffset + sizeof(uint8_t)) {
ALOGE("Invalid EDID: manufacture week is truncated.");
@@ -212,6 +231,15 @@
ALOGW_IF(manufactureOrModelYear <= 0xf,
"Invalid EDID: model year or manufacture year cannot be in the range [0x0, 0xf].");
+ constexpr size_t kMaxHorizontalPhysicalSizeOffset = 21;
+ constexpr size_t kMaxVerticalPhysicalSizeOffset = 22;
+ if (edid.size() < kMaxVerticalPhysicalSizeOffset + sizeof(uint8_t)) {
+ ALOGE("Invalid EDID: display's physical size is truncated.");
+ return {};
+ }
+ ui::Size maxPhysicalSizeInCm(edid[kMaxHorizontalPhysicalSizeOffset],
+ edid[kMaxVerticalPhysicalSizeOffset]);
+
constexpr size_t kDescriptorOffset = 54;
if (edid.size() < kDescriptorOffset) {
ALOGE("Invalid EDID: descriptors are missing.");
@@ -222,7 +250,8 @@
view = view.subspan(kDescriptorOffset);
std::string_view displayName;
- std::string_view serialNumber;
+ std::string_view descriptorBlockSerialNumber;
+ std::optional<uint64_t> hashedDescriptorBlockSNOpt = std::nullopt;
std::string_view asciiText;
ui::Size preferredDTDPixelSize;
ui::Size preferredDTDPhysicalSize;
@@ -247,7 +276,10 @@
asciiText = parseEdidText(descriptor);
break;
case 0xff:
- serialNumber = parseEdidText(descriptor);
+ descriptorBlockSerialNumber = parseEdidText(descriptor);
+ hashedDescriptorBlockSNOpt = descriptorBlockSerialNumber.empty()
+ ? std::nullopt
+ : ftl::stable_hash(descriptorBlockSerialNumber);
break;
}
} else if (isDetailedTimingDescriptor(view)) {
@@ -288,7 +320,7 @@
if (modelString.empty()) {
ALOGW("Invalid EDID: falling back to serial number due to missing display name.");
- modelString = serialNumber;
+ modelString = descriptorBlockSerialNumber;
}
if (modelString.empty()) {
ALOGW("Invalid EDID: falling back to ASCII text due to missing serial number.");
@@ -341,11 +373,14 @@
return Edid{
.manufacturerId = manufacturerId,
.productId = productId,
+ .hashedBlockZeroSerialNumberOpt = hashedBlockZeroSNOpt,
+ .hashedDescriptorBlockSerialNumberOpt = hashedDescriptorBlockSNOpt,
.pnpId = *pnpId,
.modelHash = modelHash,
.displayName = displayName,
.manufactureOrModelYear = manufactureOrModelYear,
.manufactureWeek = manufactureWeek,
+ .physicalSizeInCm = maxPhysicalSizeInCm,
.cea861Block = cea861Block,
.preferredDetailedTimingDescriptor = preferredDetailedTimingDescriptor,
};
@@ -358,10 +393,6 @@
return a && b && c ? std::make_optional(PnpId{a, b, c}) : std::nullopt;
}
-std::optional<PnpId> getPnpId(PhysicalDisplayId displayId) {
- return getPnpId(displayId.getManufacturerId());
-}
-
std::optional<DisplayIdentificationInfo> parseDisplayIdentificationData(
uint8_t port, const DisplayIdentificationData& data) {
if (data.empty()) {
@@ -383,6 +414,7 @@
return DisplayIdentificationInfo{
.id = displayId,
.name = std::string(edid->displayName),
+ .port = port,
.deviceProductInfo = buildDeviceProductInfo(*edid),
.preferredDetailedTimingDescriptor = edid->preferredDetailedTimingDescriptor,
};
@@ -392,4 +424,27 @@
return PhysicalDisplayId::fromEdid(0, kVirtualEdidManufacturerId, id);
}
+PhysicalDisplayId generateEdidDisplayId(const Edid& edid) {
+ const ftl::Concat displayDetailsString{edid.manufacturerId,
+ edid.productId,
+ ftl::truncated<13>(edid.displayName),
+ edid.manufactureWeek,
+ edid.manufactureOrModelYear,
+ edid.physicalSizeInCm.getWidth(),
+ edid.physicalSizeInCm.getHeight()};
+
+ // String has to be cropped to 64 characters (at most) for ftl::stable_hash.
+ // This is fine as the accuracy or completeness of the above fields is not
+ // critical for a ID fabrication.
+ const std::optional<uint64_t> hashedDisplayDetailsOpt =
+ ftl::stable_hash(std::string_view(displayDetailsString.c_str(), 64));
+
+ // Combine the hashes via bit-shifted XORs.
+ const uint64_t id = (hashedDisplayDetailsOpt.value_or(0) << 17) ^
+ (edid.hashedBlockZeroSerialNumberOpt.value_or(0) >> 11) ^
+ (edid.hashedDescriptorBlockSerialNumberOpt.value_or(0) << 23);
+
+ return PhysicalDisplayId::fromValue(id);
+}
+
} // namespace android
diff --git a/libs/ui/Gralloc5.cpp b/libs/ui/Gralloc5.cpp
index c9ec036..2143f79 100644
--- a/libs/ui/Gralloc5.cpp
+++ b/libs/ui/Gralloc5.cpp
@@ -23,7 +23,6 @@
#include <aidlcommonsupport/NativeHandle.h>
#include <android/binder_manager.h>
#include <android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h>
-#include <android/llndk-versioning.h>
#include <binder/IPCThreadState.h>
#include <dlfcn.h>
#include <ui/FatVector.h>
@@ -91,7 +90,7 @@
}
void* so = nullptr;
- if API_LEVEL_AT_LEAST (__ANDROID_API_V__, 202404) {
+ if (__builtin_available(android __ANDROID_API_V__, *)) {
so = AServiceManager_openDeclaredPassthroughHal("mapper", mapperSuffix.c_str(),
RTLD_LOCAL | RTLD_NOW);
} else {
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index b0c6e44..18c9a6b 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -596,6 +596,8 @@
width = height = stride = format = usage_deprecated = 0;
layerCount = 0;
usage = 0;
+ native_handle_close(handle);
+ native_handle_delete(const_cast<native_handle_t*>(handle));
handle = nullptr;
ALOGE("unflatten: registerBuffer failed: %s (%d)", strerror(-err), err);
return err;
diff --git a/libs/ui/OWNERS b/libs/ui/OWNERS
index a0b5fe7..2a85a4b 100644
--- a/libs/ui/OWNERS
+++ b/libs/ui/OWNERS
@@ -2,6 +2,5 @@
alecmouri@google.com
chrisforbes@google.com
jreck@google.com
-lpy@google.com
mathias@google.com
romainguy@google.com
diff --git a/services/surfaceflinger/RenderArea.cpp b/libs/ui/PictureProfileHandle.cpp
similarity index 66%
rename from services/surfaceflinger/RenderArea.cpp
rename to libs/ui/PictureProfileHandle.cpp
index 5fea521..0701e90 100644
--- a/services/surfaceflinger/RenderArea.cpp
+++ b/libs/ui/PictureProfileHandle.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 The Android Open Source Project
+ * Copyright (C) 2009 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.
@@ -14,18 +14,16 @@
* limitations under the License.
*/
-#include "RenderArea.h"
+#include <ui/PictureProfileHandle.h>
+
+#include <format>
namespace android {
-float RenderArea::getCaptureFillValue(CaptureFill captureFill) {
- switch(captureFill) {
- case CaptureFill::CLEAR:
- return 0.0f;
- case CaptureFill::OPAQUE:
- default:
- return 1.0f;
- }
+const PictureProfileHandle PictureProfileHandle::NONE(0);
+
+::std::string toString(const PictureProfileHandle& handle) {
+ return std::format("{:#010x}", handle.getId());
}
} // namespace android
diff --git a/libs/ui/PublicFormat.cpp b/libs/ui/PublicFormat.cpp
index c9663ed..dbc0884 100644
--- a/libs/ui/PublicFormat.cpp
+++ b/libs/ui/PublicFormat.cpp
@@ -30,6 +30,7 @@
case PublicFormat::DEPTH_POINT_CLOUD:
case PublicFormat::DEPTH_JPEG:
case PublicFormat::HEIC:
+ case PublicFormat::HEIC_ULTRAHDR:
case PublicFormat::JPEG_R:
return HAL_PIXEL_FORMAT_BLOB;
case PublicFormat::DEPTH16:
@@ -74,6 +75,9 @@
case PublicFormat::HEIC:
dataspace = Dataspace::HEIF;
break;
+ case PublicFormat::HEIC_ULTRAHDR:
+ dataspace = Dataspace::HEIF_ULTRAHDR;
+ break;
case PublicFormat::JPEG_R:
dataspace = Dataspace::JPEG_R;
break;
@@ -153,6 +157,9 @@
return PublicFormat::DEPTH_JPEG;
} else if (dataSpace == static_cast<android_dataspace>(Dataspace::JPEG_R)) {
return PublicFormat::JPEG_R;
+ } else if (dataSpace == static_cast<android_dataspace>(
+ Dataspace::HEIF_ULTRAHDR)) {
+ return PublicFormat::HEIC_ULTRAHDR;
}else {
// Assume otherwise-marked blobs are also JPEG
return PublicFormat::JPEG;
diff --git a/libs/ui/include/ui/DisplayId.h b/libs/ui/include/ui/DisplayId.h
index 8a14db8..937e3f1 100644
--- a/libs/ui/include/ui/DisplayId.h
+++ b/libs/ui/include/ui/DisplayId.h
@@ -20,7 +20,6 @@
#include <ostream>
#include <string>
-#include <ftl/hash.h>
#include <ftl/optional.h>
namespace android {
@@ -31,31 +30,16 @@
// Flag indicating that the display is virtual.
static constexpr uint64_t FLAG_VIRTUAL = 1ULL << 63;
- // Flag indicating that the ID is stable across reboots.
- static constexpr uint64_t FLAG_STABLE = 1ULL << 62;
-
- // TODO(b/162612135) Remove default constructor
+ // TODO: b/162612135 - Remove default constructor.
DisplayId() = default;
constexpr DisplayId(const DisplayId&) = default;
DisplayId& operator=(const DisplayId&) = default;
+ static constexpr DisplayId fromValue(uint64_t value) { return DisplayId(value); }
constexpr bool isVirtual() const { return value & FLAG_VIRTUAL; }
- constexpr bool isStable() const { return value & FLAG_STABLE; }
uint64_t value;
- // For deserialization.
- static constexpr std::optional<DisplayId> fromValue(uint64_t);
-
- // As above, but also upcast to Id.
- template <typename Id>
- static constexpr std::optional<Id> fromValue(uint64_t value) {
- if (const auto id = Id::tryCast(DisplayId(value))) {
- return id;
- }
- return {};
- }
-
protected:
explicit constexpr DisplayId(uint64_t id) : value(id) {}
};
@@ -79,6 +63,9 @@
// DisplayId of a physical display, such as the internal display or externally connected display.
struct PhysicalDisplayId : DisplayId {
+ // TODO: b/162612135 - Remove default constructor.
+ PhysicalDisplayId() = default;
+
static constexpr ftl::Optional<PhysicalDisplayId> tryCast(DisplayId id) {
if (id.isVirtual()) {
return std::nullopt;
@@ -86,7 +73,7 @@
return PhysicalDisplayId(id);
}
- // Returns a stable ID based on EDID information.
+ // Returns a stable ID based on EDID and port information.
static constexpr PhysicalDisplayId fromEdid(uint8_t port, uint16_t manufacturerId,
uint32_t modelHash) {
return PhysicalDisplayId(FLAG_STABLE, port, manufacturerId, modelHash);
@@ -99,13 +86,18 @@
return PhysicalDisplayId(0, port, kManufacturerId, kModelHash);
}
- // TODO(b/162612135) Remove default constructor
- PhysicalDisplayId() = default;
+ static constexpr PhysicalDisplayId fromValue(uint64_t value) {
+ return PhysicalDisplayId(value);
+ }
- constexpr uint16_t getManufacturerId() const { return static_cast<uint16_t>(value >> 40); }
constexpr uint8_t getPort() const { return static_cast<uint8_t>(value); }
private:
+ // Flag indicating that the ID is stable across reboots.
+ static constexpr uint64_t FLAG_STABLE = 1ULL << 62;
+
+ using DisplayId::DisplayId;
+
constexpr PhysicalDisplayId(uint64_t flags, uint8_t port, uint16_t manufacturerId,
uint32_t modelHash)
: DisplayId(flags | (static_cast<uint64_t>(manufacturerId) << 40) |
@@ -127,8 +119,15 @@
return std::nullopt;
}
+ static constexpr VirtualDisplayId fromValue(uint64_t value) {
+ return VirtualDisplayId(SkipVirtualFlag{}, value);
+ }
+
protected:
+ struct SkipVirtualFlag {};
+ constexpr VirtualDisplayId(SkipVirtualFlag, uint64_t value) : DisplayId(value) {}
explicit constexpr VirtualDisplayId(uint64_t value) : DisplayId(FLAG_VIRTUAL | value) {}
+
explicit constexpr VirtualDisplayId(DisplayId other) : DisplayId(other) {}
};
@@ -142,20 +141,17 @@
return std::nullopt;
}
+ static constexpr HalVirtualDisplayId fromValue(uint64_t value) {
+ return HalVirtualDisplayId(SkipVirtualFlag{}, value);
+ }
+
private:
- explicit constexpr HalVirtualDisplayId(DisplayId other) : VirtualDisplayId(other) {}
+ using VirtualDisplayId::VirtualDisplayId;
};
struct GpuVirtualDisplayId : VirtualDisplayId {
explicit constexpr GpuVirtualDisplayId(BaseId baseId) : VirtualDisplayId(FLAG_GPU | baseId) {}
- static constexpr std::optional<GpuVirtualDisplayId> fromUniqueId(const std::string& uniqueId) {
- if (const auto hashOpt = ftl::stable_hash(uniqueId)) {
- return GpuVirtualDisplayId(HashTag{}, *hashOpt);
- }
- return {};
- }
-
static constexpr std::optional<GpuVirtualDisplayId> tryCast(DisplayId id) {
if (id.isVirtual() && (id.value & FLAG_GPU)) {
return GpuVirtualDisplayId(id);
@@ -163,12 +159,12 @@
return std::nullopt;
}
-private:
- struct HashTag {}; // Disambiguate with BaseId constructor.
- constexpr GpuVirtualDisplayId(HashTag, uint64_t hash)
- : VirtualDisplayId(FLAG_STABLE | FLAG_GPU | hash) {}
+ static constexpr GpuVirtualDisplayId fromValue(uint64_t value) {
+ return GpuVirtualDisplayId(SkipVirtualFlag{}, value);
+ }
- explicit constexpr GpuVirtualDisplayId(DisplayId other) : VirtualDisplayId(other) {}
+private:
+ using VirtualDisplayId::VirtualDisplayId;
};
// HalDisplayId is the ID of a display which is managed by HWC.
@@ -184,20 +180,13 @@
return HalDisplayId(id);
}
+ static constexpr HalDisplayId fromValue(uint64_t value) { return HalDisplayId(value); }
+
private:
+ using DisplayId::DisplayId;
explicit constexpr HalDisplayId(DisplayId other) : DisplayId(other) {}
};
-constexpr std::optional<DisplayId> DisplayId::fromValue(uint64_t value) {
- if (const auto id = fromValue<PhysicalDisplayId>(value)) {
- return id;
- }
- if (const auto id = fromValue<VirtualDisplayId>(value)) {
- return id;
- }
- return {};
-}
-
static_assert(sizeof(DisplayId) == sizeof(uint64_t));
static_assert(sizeof(HalDisplayId) == sizeof(uint64_t));
static_assert(sizeof(VirtualDisplayId) == sizeof(uint64_t));
diff --git a/libs/ui/include/ui/DisplayIdentification.h b/libs/ui/include/ui/DisplayIdentification.h
index 648e024..1e3449c 100644
--- a/libs/ui/include/ui/DisplayIdentification.h
+++ b/libs/ui/include/ui/DisplayIdentification.h
@@ -42,6 +42,7 @@
struct DisplayIdentificationInfo {
PhysicalDisplayId id;
std::string name;
+ uint8_t port;
std::optional<DeviceProductInfo> deviceProductInfo;
std::optional<DetailedTimingDescriptor> preferredDetailedTimingDescriptor;
};
@@ -69,11 +70,15 @@
struct Edid {
uint16_t manufacturerId;
uint16_t productId;
+ std::optional<uint64_t> hashedBlockZeroSerialNumberOpt;
+ std::optional<uint64_t> hashedDescriptorBlockSerialNumberOpt;
PnpId pnpId;
uint32_t modelHash;
+ // Up to 13 characters of ASCII text terminated by LF and padded with SP.
std::string_view displayName;
uint8_t manufactureOrModelYear;
uint8_t manufactureWeek;
+ ui::Size physicalSizeInCm;
std::optional<Cea861ExtensionBlock> cea861Block;
std::optional<DetailedTimingDescriptor> preferredDetailedTimingDescriptor;
};
@@ -81,11 +86,14 @@
bool isEdid(const DisplayIdentificationData&);
std::optional<Edid> parseEdid(const DisplayIdentificationData&);
std::optional<PnpId> getPnpId(uint16_t manufacturerId);
-std::optional<PnpId> getPnpId(PhysicalDisplayId);
std::optional<DisplayIdentificationInfo> parseDisplayIdentificationData(
uint8_t port, const DisplayIdentificationData&);
PhysicalDisplayId getVirtualDisplayId(uint32_t id);
+// Generates a consistent, stable, and hashed display ID that is based on the
+// display's parsed EDID fields.
+PhysicalDisplayId generateEdidDisplayId(const Edid& edid);
+
} // namespace android
diff --git a/libs/ui/include/ui/DisplayMap.h b/libs/ui/include/ui/DisplayMap.h
index 65d2b8f..834a304 100644
--- a/libs/ui/include/ui/DisplayMap.h
+++ b/libs/ui/include/ui/DisplayMap.h
@@ -18,6 +18,7 @@
#include <ftl/small_map.h>
#include <ftl/small_vector.h>
+#include <ftl/unit.h>
namespace android::ui {
@@ -30,6 +31,8 @@
constexpr size_t kPhysicalDisplayCapacity = 3;
template <typename Key, typename Value>
using PhysicalDisplayMap = ftl::SmallMap<Key, Value, kPhysicalDisplayCapacity>;
+template <typename Key>
+using PhysicalDisplaySet = ftl::SmallMap<Key, ftl::Unit, kPhysicalDisplayCapacity>;
template <typename T>
using DisplayVector = ftl::SmallVector<T, kDisplayCapacity>;
diff --git a/libs/ui/include/ui/DynamicDisplayInfo.h b/libs/ui/include/ui/DynamicDisplayInfo.h
index 25a2b6e..9d97151 100644
--- a/libs/ui/include/ui/DynamicDisplayInfo.h
+++ b/libs/ui/include/ui/DynamicDisplayInfo.h
@@ -22,6 +22,7 @@
#include <optional>
#include <vector>
+#include <ui/FrameRateCategoryRate.h>
#include <ui/GraphicTypes.h>
#include <ui/HdrCapabilities.h>
@@ -55,6 +56,12 @@
std::optional<ui::DisplayMode> getActiveDisplayMode() const;
bool hasArrSupport;
+
+ // Represents frame rate for FrameRateCategory Normal and High.
+ ui::FrameRateCategoryRate frameRateCategoryRate;
+
+ // All the refresh rates supported for the default display mode.
+ std::vector<float> supportedRefreshRates;
};
} // namespace android::ui
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp b/libs/ui/include/ui/FrameRateCategoryRate.h
similarity index 60%
copy from services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp
copy to libs/ui/include/ui/FrameRateCategoryRate.h
index d383283..9c392d9 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp
+++ b/libs/ui/include/ui/FrameRateCategoryRate.h
@@ -14,12 +14,22 @@
* limitations under the License.
*/
-#include "mock/DisplayHardware/MockPowerHintSessionWrapper.h"
+#pragma once
-namespace android::Hwc2::mock {
+namespace android::ui {
-// Explicit default instantiation is recommended.
-MockPowerHintSessionWrapper::MockPowerHintSessionWrapper()
- : power::PowerHintSessionWrapper(nullptr) {}
+// Represents frame rate for FrameRateCategory Normal and High.
+class FrameRateCategoryRate {
+public:
+ FrameRateCategoryRate(float normal = 0, float high = 0) : mNormal(normal), mHigh(high) {}
-} // namespace android::Hwc2::mock
+ float getNormal() const { return mNormal; }
+
+ float getHigh() const { return mHigh; }
+
+private:
+ float mNormal;
+ float mHigh;
+};
+
+} // namespace android::ui
\ No newline at end of file
diff --git a/libs/ui/include/ui/PictureProfileHandle.h b/libs/ui/include/ui/PictureProfileHandle.h
new file mode 100644
index 0000000..f840650
--- /dev/null
+++ b/libs/ui/include/ui/PictureProfileHandle.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 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 <stdint.h>
+#include <array>
+#include <string>
+
+namespace android {
+
+/**
+ * An opaque value that uniquely identifies a picture profile, or a set of parameters, which
+ * describes the configuration of a picture processing pipeline that is applied to a graphic buffer
+ * to enhance its quality prior to rendering on the display.
+ */
+typedef int64_t PictureProfileId;
+
+/**
+ * A picture profile handle wraps the picture profile ID for type-safety, and represents an opaque
+ * handle that doesn't have the performance drawbacks of Binders.
+ */
+class PictureProfileHandle {
+public:
+ // A profile that represents no picture processing.
+ static const PictureProfileHandle NONE;
+
+ PictureProfileHandle() { *this = NONE; }
+ explicit PictureProfileHandle(PictureProfileId id) : mId(id) {}
+
+ PictureProfileId const& getId() const { return mId; }
+
+ inline bool operator==(const PictureProfileHandle& rhs) { return mId == rhs.mId; }
+ inline bool operator!=(const PictureProfileHandle& rhs) { return !(*this == rhs); }
+
+ // Is the picture profile effectively null, or not-specified?
+ inline bool operator!() const { return mId == NONE.mId; }
+
+ operator bool() const { return !!*this; }
+
+ friend ::std::string toString(const PictureProfileHandle& handle);
+
+private:
+ PictureProfileId mId;
+};
+
+} // namespace android
diff --git a/libs/ui/include/ui/PublicFormat.h b/libs/ui/include/ui/PublicFormat.h
index 2248cca..7c17763 100644
--- a/libs/ui/include/ui/PublicFormat.h
+++ b/libs/ui/include/ui/PublicFormat.h
@@ -59,6 +59,8 @@
DEPTH_JPEG = 0x69656963,
JPEG_R = 0x1005,
HEIC = 0x48454946,
+ HEIC_ULTRAHDR = 0x1006,
+ YCBCR_P210 = 0x3c,
};
/* Convert from android.graphics.ImageFormat/PixelFormat enums to graphics.h HAL
diff --git a/libs/ui/include_types/ui/HdrRenderTypeUtils.h b/libs/ui/include_types/ui/HdrRenderTypeUtils.h
index b0af878..98018d9 100644
--- a/libs/ui/include_types/ui/HdrRenderTypeUtils.h
+++ b/libs/ui/include_types/ui/HdrRenderTypeUtils.h
@@ -36,7 +36,7 @@
*/
inline HdrRenderType getHdrRenderType(ui::Dataspace dataspace,
std::optional<ui::PixelFormat> pixelFormat,
- float hdrSdrRatio = 1.f) {
+ float hdrSdrRatio = 1.f, bool hasHdrMetadata = false) {
const auto transfer = dataspace & HAL_DATASPACE_TRANSFER_MASK;
const auto range = dataspace & HAL_DATASPACE_RANGE_MASK;
@@ -49,7 +49,8 @@
HAL_DATASPACE_RANGE_EXTENDED);
if ((dataspace == BT2020_LINEAR_EXT || dataspace == ui::Dataspace::V0_SCRGB) &&
- pixelFormat.has_value() && pixelFormat.value() == ui::PixelFormat::RGBA_FP16) {
+ pixelFormat.has_value() && pixelFormat.value() == ui::PixelFormat::RGBA_FP16 &&
+ hasHdrMetadata) {
return HdrRenderType::GENERIC_HDR;
}
@@ -61,4 +62,24 @@
return HdrRenderType::SDR;
}
-} // namespace android
\ No newline at end of file
+/**
+ * Returns the maximum headroom allowed for this content under "idealized"
+ * display conditions (low surround luminance, high-enough display brightness).
+ *
+ * TODO: take into account hdr metadata, but square it with the fact that some
+ * HLG content has CTA.861-3 metadata
+ */
+inline float getIdealizedMaxHeadroom(ui::Dataspace dataspace) {
+ const auto transfer = dataspace & HAL_DATASPACE_TRANSFER_MASK;
+
+ switch (transfer) {
+ case HAL_DATASPACE_TRANSFER_ST2084:
+ return 10000.0f / 203.0f;
+ case HAL_DATASPACE_TRANSFER_HLG:
+ return 1000.0f / 203.0f;
+ default:
+ return 1.0f;
+ }
+}
+
+} // namespace android
diff --git a/libs/ui/tests/DisplayId_test.cpp b/libs/ui/tests/DisplayId_test.cpp
index ef686df..209acba 100644
--- a/libs/ui/tests/DisplayId_test.cpp
+++ b/libs/ui/tests/DisplayId_test.cpp
@@ -26,7 +26,6 @@
constexpr uint32_t modelHash = 42;
const PhysicalDisplayId id = PhysicalDisplayId::fromEdid(port, manufacturerId, modelHash);
EXPECT_EQ(port, id.getPort());
- EXPECT_EQ(manufacturerId, id.getManufacturerId());
EXPECT_FALSE(VirtualDisplayId::tryCast(id));
EXPECT_FALSE(HalVirtualDisplayId::tryCast(id));
EXPECT_FALSE(GpuVirtualDisplayId::tryCast(id));
@@ -34,7 +33,7 @@
EXPECT_TRUE(HalDisplayId::tryCast(id));
EXPECT_EQ(id, DisplayId::fromValue(id.value));
- EXPECT_EQ(id, DisplayId::fromValue<PhysicalDisplayId>(id.value));
+ EXPECT_EQ(id, PhysicalDisplayId::fromValue(id.value));
}
TEST(DisplayIdTest, createPhysicalIdFromPort) {
@@ -48,7 +47,7 @@
EXPECT_TRUE(HalDisplayId::tryCast(id));
EXPECT_EQ(id, DisplayId::fromValue(id.value));
- EXPECT_EQ(id, DisplayId::fromValue<PhysicalDisplayId>(id.value));
+ EXPECT_EQ(id, PhysicalDisplayId::fromValue(id.value));
}
TEST(DisplayIdTest, createGpuVirtualId) {
@@ -60,7 +59,7 @@
EXPECT_FALSE(HalDisplayId::tryCast(id));
EXPECT_EQ(id, DisplayId::fromValue(id.value));
- EXPECT_EQ(id, DisplayId::fromValue<GpuVirtualDisplayId>(id.value));
+ EXPECT_EQ(id, GpuVirtualDisplayId::fromValue(id.value));
}
TEST(DisplayIdTest, createVirtualIdFromGpuVirtualId) {
@@ -75,21 +74,6 @@
EXPECT_EQ((id.isVirtual() && isGpuVirtualId), GpuVirtualDisplayId::tryCast(id).has_value());
}
-TEST(DisplayIdTest, createGpuVirtualIdFromUniqueId) {
- static const std::string kUniqueId("virtual:ui:DisplayId_test");
- const auto idOpt = GpuVirtualDisplayId::fromUniqueId(kUniqueId);
- ASSERT_TRUE(idOpt.has_value());
- const GpuVirtualDisplayId id = idOpt.value();
- EXPECT_TRUE(VirtualDisplayId::tryCast(id));
- EXPECT_TRUE(GpuVirtualDisplayId::tryCast(id));
- EXPECT_FALSE(HalVirtualDisplayId::tryCast(id));
- EXPECT_FALSE(PhysicalDisplayId::tryCast(id));
- EXPECT_FALSE(HalDisplayId::tryCast(id));
-
- EXPECT_EQ(id, DisplayId::fromValue(id.value));
- EXPECT_EQ(id, DisplayId::fromValue<GpuVirtualDisplayId>(id.value));
-}
-
TEST(DisplayIdTest, createHalVirtualId) {
const HalVirtualDisplayId id(42);
EXPECT_TRUE(VirtualDisplayId::tryCast(id));
@@ -99,7 +83,7 @@
EXPECT_TRUE(HalDisplayId::tryCast(id));
EXPECT_EQ(id, DisplayId::fromValue(id.value));
- EXPECT_EQ(id, DisplayId::fromValue<HalVirtualDisplayId>(id.value));
+ EXPECT_EQ(id, HalVirtualDisplayId::fromValue(id.value));
}
TEST(DisplayIdTest, createVirtualIdFromHalVirtualId) {
diff --git a/libs/ui/tests/DisplayIdentification_test.cpp b/libs/ui/tests/DisplayIdentification_test.cpp
index 76e3f66..75c71a5 100644
--- a/libs/ui/tests/DisplayIdentification_test.cpp
+++ b/libs/ui/tests/DisplayIdentification_test.cpp
@@ -33,7 +33,7 @@
namespace {
const unsigned char kInternalEdid[] =
- "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\xa3\x42\x31\x00\x00\x00\x00"
+ "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\xa3\x42\x31\x4e\x61\xbc\x00"
"\x00\x15\x01\x03\x80\x1a\x10\x78\x0a\xd3\xe5\x95\x5c\x60\x90\x27"
"\x19\x50\x54\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
"\x01\x01\x01\x01\x01\x01\x9e\x1b\x00\xa0\x50\x20\x12\x30\x10\x30"
@@ -54,7 +54,7 @@
// Extended EDID with timing extension.
const unsigned char kExternalEedid[] =
- "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\x2d\xfe\x08\x00\x00\x00\x00"
+ "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\x2d\xfe\x08\xb1\x7f\x39\x05"
"\x29\x15\x01\x03\x80\x10\x09\x78\x0a\xee\x91\xa3\x54\x4c\x99\x26"
"\x0f\x50\x54\xbd\xef\x80\x71\x4f\x81\xc0\x81\x00\x81\x80\x95\x00"
"\xa9\xc0\xb3\x00\x01\x01\x02\x3a\x80\x18\x71\x38\x2d\x40\x58\x2c"
@@ -112,7 +112,7 @@
"\x07";
const unsigned char kCtlDisplayEdid[] =
- "\x00\xff\xff\xff\xff\xff\xff\x00\x0e\x8c\x9d\x24\x00\x00\x00\x00"
+ "\x00\xff\xff\xff\xff\xff\xff\x00\x0e\x8c\x9d\x24\x30\x41\xab\x00"
"\xff\x17\x01\x04\xa5\x34\x1d\x78\x3a\xa7\x25\xa4\x57\x51\xa0\x26"
"\x10\x50\x54\xbf\xef\x80\xb3\x00\xa9\x40\x95\x00\x81\x40\x81\x80"
"\x95\x0f\x71\x4f\x90\x40\x02\x3a\x80\x18\x71\x38\x2d\x40\x58\x2c"
@@ -191,8 +191,13 @@
EXPECT_EQ(hash("121AT11-801"), 626564263);
EXPECT_TRUE(edid->displayName.empty());
EXPECT_EQ(12610, edid->productId);
+ EXPECT_TRUE(edid->hashedBlockZeroSerialNumberOpt.has_value());
+ EXPECT_EQ(ftl::stable_hash("12345678"), edid->hashedBlockZeroSerialNumberOpt.value());
+ EXPECT_FALSE(edid->hashedDescriptorBlockSerialNumberOpt.has_value());
EXPECT_EQ(21, edid->manufactureOrModelYear);
EXPECT_EQ(0, edid->manufactureWeek);
+ EXPECT_EQ(26, edid->physicalSizeInCm.width);
+ EXPECT_EQ(16, edid->physicalSizeInCm.height);
EXPECT_FALSE(edid->cea861Block);
EXPECT_EQ(1280, edid->preferredDetailedTimingDescriptor->pixelSizeCount.width);
EXPECT_EQ(800, edid->preferredDetailedTimingDescriptor->pixelSizeCount.height);
@@ -207,8 +212,14 @@
EXPECT_EQ(hash("HP ZR30w"), 918492362);
EXPECT_EQ("HP ZR30w", edid->displayName);
EXPECT_EQ(10348, edid->productId);
+ EXPECT_TRUE(edid->hashedBlockZeroSerialNumberOpt.has_value());
+ EXPECT_EQ(ftl::stable_hash("16843009"), edid->hashedBlockZeroSerialNumberOpt.value());
+ EXPECT_TRUE(edid->hashedDescriptorBlockSerialNumberOpt.has_value());
+ EXPECT_EQ(ftl::stable_hash("CN4202137Q"), edid->hashedDescriptorBlockSerialNumberOpt.value());
EXPECT_EQ(22, edid->manufactureOrModelYear);
EXPECT_EQ(2, edid->manufactureWeek);
+ EXPECT_EQ(64, edid->physicalSizeInCm.width);
+ EXPECT_EQ(40, edid->physicalSizeInCm.height);
EXPECT_FALSE(edid->cea861Block);
EXPECT_EQ(1280, edid->preferredDetailedTimingDescriptor->pixelSizeCount.width);
EXPECT_EQ(800, edid->preferredDetailedTimingDescriptor->pixelSizeCount.height);
@@ -223,8 +234,13 @@
EXPECT_EQ(hash("SAMSUNG"), 1201368132);
EXPECT_EQ("SAMSUNG", edid->displayName);
EXPECT_EQ(2302, edid->productId);
+ EXPECT_TRUE(edid->hashedBlockZeroSerialNumberOpt.has_value());
+ EXPECT_EQ(ftl::stable_hash("87654321"), edid->hashedBlockZeroSerialNumberOpt.value());
+ EXPECT_FALSE(edid->hashedDescriptorBlockSerialNumberOpt.has_value());
EXPECT_EQ(21, edid->manufactureOrModelYear);
EXPECT_EQ(41, edid->manufactureWeek);
+ EXPECT_EQ(16, edid->physicalSizeInCm.width);
+ EXPECT_EQ(9, edid->physicalSizeInCm.height);
ASSERT_TRUE(edid->cea861Block);
ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock);
auto physicalAddress = edid->cea861Block->hdmiVendorDataBlock->physicalAddress;
@@ -245,8 +261,13 @@
EXPECT_EQ(hash("Panasonic-TV"), 3876373262);
EXPECT_EQ("Panasonic-TV", edid->displayName);
EXPECT_EQ(41622, edid->productId);
+ EXPECT_TRUE(edid->hashedBlockZeroSerialNumberOpt.has_value());
+ EXPECT_EQ(ftl::stable_hash("16843009"), edid->hashedBlockZeroSerialNumberOpt.value());
+ EXPECT_FALSE(edid->hashedDescriptorBlockSerialNumberOpt.has_value());
EXPECT_EQ(29, edid->manufactureOrModelYear);
EXPECT_EQ(0, edid->manufactureWeek);
+ EXPECT_EQ(128, edid->physicalSizeInCm.width);
+ EXPECT_EQ(72, edid->physicalSizeInCm.height);
ASSERT_TRUE(edid->cea861Block);
ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock);
physicalAddress = edid->cea861Block->hdmiVendorDataBlock->physicalAddress;
@@ -267,8 +288,12 @@
EXPECT_EQ(hash("Hisense"), 2859844809);
EXPECT_EQ("Hisense", edid->displayName);
EXPECT_EQ(0, edid->productId);
+ EXPECT_FALSE(edid->hashedBlockZeroSerialNumberOpt.has_value());
+ EXPECT_FALSE(edid->hashedDescriptorBlockSerialNumberOpt.has_value());
EXPECT_EQ(29, edid->manufactureOrModelYear);
EXPECT_EQ(18, edid->manufactureWeek);
+ EXPECT_EQ(0, edid->physicalSizeInCm.width);
+ EXPECT_EQ(0, edid->physicalSizeInCm.height);
ASSERT_TRUE(edid->cea861Block);
ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock);
physicalAddress = edid->cea861Block->hdmiVendorDataBlock->physicalAddress;
@@ -289,8 +314,13 @@
EXPECT_EQ(hash("LP2361"), 1523181158);
EXPECT_EQ("LP2361", edid->displayName);
EXPECT_EQ(9373, edid->productId);
+ EXPECT_TRUE(edid->hashedBlockZeroSerialNumberOpt.has_value());
+ EXPECT_EQ(ftl::stable_hash("11223344"), edid->hashedBlockZeroSerialNumberOpt.value());
+ EXPECT_FALSE(edid->hashedDescriptorBlockSerialNumberOpt.has_value());
EXPECT_EQ(23, edid->manufactureOrModelYear);
EXPECT_EQ(0xff, edid->manufactureWeek);
+ EXPECT_EQ(52, edid->physicalSizeInCm.width);
+ EXPECT_EQ(29, edid->physicalSizeInCm.height);
ASSERT_TRUE(edid->cea861Block);
EXPECT_FALSE(edid->cea861Block->hdmiVendorDataBlock);
EXPECT_EQ(1360, edid->preferredDetailedTimingDescriptor->pixelSizeCount.width);
@@ -346,6 +376,22 @@
EXPECT_EQ(4633127902230889474, tertiaryInfo->id.value);
}
+TEST(DisplayIdentificationTest, generateEdidDisplayId) {
+ const auto firstExternalDisplayEdidOpt = parseEdid(getExternalEdid());
+ ASSERT_TRUE(firstExternalDisplayEdidOpt);
+ const PhysicalDisplayId firstExternalDisplayId =
+ generateEdidDisplayId(firstExternalDisplayEdidOpt.value());
+
+ const auto secondExternalDisplayEdidOpt = parseEdid(getExternalEedid());
+ ASSERT_TRUE(secondExternalDisplayEdidOpt);
+ const PhysicalDisplayId secondExternalDisplayId =
+ generateEdidDisplayId(secondExternalDisplayEdidOpt.value());
+
+ // Display IDs should be unique.
+ EXPECT_EQ(4067182673952280501u, firstExternalDisplayId.value);
+ EXPECT_EQ(14712168404707886855u, secondExternalDisplayId.value);
+}
+
TEST(DisplayIdentificationTest, deviceProductInfo) {
using ManufactureYear = DeviceProductInfo::ManufactureYear;
using ManufactureWeekAndYear = DeviceProductInfo::ManufactureWeekAndYear;
@@ -432,19 +478,7 @@
}
}
-TEST(DisplayIdentificationTest, fromPort) {
- // Manufacturer ID should be invalid.
- ASSERT_FALSE(getPnpId(PhysicalDisplayId::fromPort(0)));
- ASSERT_FALSE(getPnpId(PhysicalDisplayId::fromPort(0xffu)));
-}
-
-TEST(DisplayIdentificationTest, getVirtualDisplayId) {
- // Manufacturer ID should be invalid.
- ASSERT_FALSE(getPnpId(getVirtualDisplayId(0)));
- ASSERT_FALSE(getPnpId(getVirtualDisplayId(0xffff'ffffu)));
-}
-
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wextra"
\ No newline at end of file
+#pragma clang diagnostic pop // ignored "-Wextra"
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 5159ffe..eb747c7 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -8,6 +8,11 @@
default_applicable_licenses: ["frameworks_native_license"],
}
+cc_aconfig_library {
+ name: "libegl_flags_c_lib",
+ aconfig_declarations: "graphicsenv_flags",
+}
+
cc_library {
name: "libETC1",
srcs: ["ETC1/etc1.cpp"],
@@ -63,6 +68,18 @@
unversioned_until: "current",
}
+aconfig_declarations {
+ name: "egl_flags",
+ package: "com.android.graphics.egl.flags",
+ container: "system",
+ srcs: ["EGL/egl_flags.aconfig"],
+}
+
+cc_aconfig_library {
+ name: "libegl_flags",
+ aconfig_declarations: "egl_flags",
+}
+
cc_defaults {
name: "gl_libs_defaults",
cflags: [
@@ -135,11 +152,18 @@
"EGL/MultifileBlobCache.cpp",
],
export_include_dirs: ["EGL"],
+ shared_libs: [
+ "libegl_flags",
+ "libz",
+ ],
}
cc_library_shared {
name: "libEGL",
- defaults: ["egl_libs_defaults"],
+ defaults: [
+ "aconfig_lib_cc_static_link.defaults",
+ "egl_libs_defaults",
+ ],
llndk: {
symbol_file: "libEGL.map.txt",
export_llndk_headers: ["gl_headers"],
@@ -163,16 +187,19 @@
"android.hardware.configstore@1.0",
"android.hardware.configstore-utils",
"libbase",
+ "libegl_flags",
"libhidlbase",
"libnativebridge_lazy",
"libnativeloader_lazy",
"libutils",
"libSurfaceFlingerProp",
"libunwindstack",
+ "libz",
],
static_libs: [
"libEGL_getProcAddress",
"libEGL_blobCache",
+ "libegl_flags_c_lib",
],
ldflags: [
"-Wl,--exclude-libs=libEGL_getProcAddress.a",
@@ -198,7 +225,9 @@
"EGL/MultifileBlobCache_test.cpp",
],
shared_libs: [
+ "libegl_flags",
"libutils",
+ "libz",
],
}
diff --git a/opengl/libs/EGL/FileBlobCache.cpp b/opengl/libs/EGL/FileBlobCache.cpp
index 4a0fac4..573ca54 100644
--- a/opengl/libs/EGL/FileBlobCache.cpp
+++ b/opengl/libs/EGL/FileBlobCache.cpp
@@ -27,6 +27,7 @@
#include <log/log.h>
#include <utils/Trace.h>
+#include <zlib.h>
// Cache file header
static const char* cacheFileMagic = "EGL$";
@@ -34,20 +35,10 @@
namespace android {
-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;
+uint32_t GenerateCRC32(const uint8_t *data, size_t size)
+{
+ const unsigned long initialValue = crc32_z(0u, nullptr, 0u);
+ return static_cast<uint32_t>(crc32_z(initialValue, data, size));
}
FileBlobCache::FileBlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize,
@@ -101,7 +92,7 @@
return;
}
uint32_t* crc = reinterpret_cast<uint32_t*>(buf + 4);
- if (crc32c(buf + headerSize, cacheSize) != *crc) {
+ if (GenerateCRC32(buf + headerSize, cacheSize) != *crc) {
ALOGE("cache file failed CRC check");
close(fd);
return;
@@ -175,7 +166,7 @@
// Write the file magic and CRC
memcpy(buf, cacheFileMagic, 4);
uint32_t* crc = reinterpret_cast<uint32_t*>(buf + 4);
- *crc = crc32c(buf + headerSize, cacheSize);
+ *crc = GenerateCRC32(buf + headerSize, cacheSize);
if (write(fd, buf, fileSize) == -1) {
ALOGE("error writing cache file: %s (%d)", strerror(errno),
diff --git a/opengl/libs/EGL/FileBlobCache.h b/opengl/libs/EGL/FileBlobCache.h
index f083b0d..224444d 100644
--- a/opengl/libs/EGL/FileBlobCache.h
+++ b/opengl/libs/EGL/FileBlobCache.h
@@ -22,7 +22,7 @@
namespace android {
-uint32_t crc32c(const uint8_t* buf, size_t len);
+uint32_t GenerateCRC32(const uint8_t *data, size_t size);
class FileBlobCache : public BlobCache {
public:
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 3be8ddc..7012df2 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -548,6 +548,10 @@
.flags = ANDROID_DLEXT_USE_NAMESPACE,
.library_namespace = ns,
};
+ auto prop = base::GetProperty("debug.angle.libs.suffix", "");
+ if (!prop.empty()) {
+ name = std::string("lib") + kind + "_" + prop + ".so";
+ }
so = do_android_dlopen_ext(name.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
}
diff --git a/opengl/libs/EGL/MultifileBlobCache.cpp b/opengl/libs/EGL/MultifileBlobCache.cpp
index 9905210..04c525e 100644
--- a/opengl/libs/EGL/MultifileBlobCache.cpp
+++ b/opengl/libs/EGL/MultifileBlobCache.cpp
@@ -38,11 +38,20 @@
#include <utils/JenkinsHash.h>
+#include <com_android_graphics_egl_flags.h>
+
+using namespace com::android::graphics::egl;
+
using namespace std::literals;
constexpr uint32_t kMultifileMagic = 'MFB$';
constexpr uint32_t kCrcPlaceholder = 0;
+// When removing files, what fraction of the overall limit should be reached when removing files
+// A divisor of two will decrease the cache to 50%, four to 25% and so on
+// We use the same limit to manage size and entry count
+constexpr uint32_t kCacheLimitDivisor = 2;
+
namespace {
// Helper function to close entries or free them
@@ -72,6 +81,7 @@
mMaxTotalEntries(maxTotalEntries),
mTotalCacheSize(0),
mTotalCacheEntries(0),
+ mTotalCacheSizeDivisor(kCacheLimitDivisor),
mHotCacheLimit(0),
mHotCacheSize(0),
mWorkerThreadIdle(true) {
@@ -80,8 +90,13 @@
return;
}
- // Set the cache version, override if debug value set
+ // Set the cache version
mCacheVersion = kMultifileBlobCacheVersion;
+ // Bump the version if we're using flagged features
+ if (flags::multifile_blobcache_advanced_usage()) {
+ mCacheVersion++;
+ }
+ // Override if debug value set
int debugCacheVersion = base::GetIntProperty("debug.egl.blobcache.cache_version", -1);
if (debugCacheVersion >= 0) {
ALOGV("INIT: Using %u as cacheVersion instead of %u", debugCacheVersion, mCacheVersion);
@@ -122,7 +137,7 @@
// Check that our cacheVersion and buildId match
struct stat st;
if (stat(mMultifileDirName.c_str(), &st) == 0) {
- if (checkStatus(mMultifileDirName.c_str())) {
+ if (checkStatus(mMultifileDirName)) {
statusGood = true;
} else {
ALOGV("INIT: Cache status has changed, clearing the cache");
@@ -214,9 +229,8 @@
}
// Ensure we have a good CRC
- if (header.crc !=
- crc32c(mappedEntry + sizeof(MultifileHeader),
- fileSize - sizeof(MultifileHeader))) {
+ if (header.crc != GenerateCRC32(mappedEntry + sizeof(MultifileHeader),
+ fileSize - sizeof(MultifileHeader))) {
ALOGV("INIT: Entry %u failed CRC check! Removing.", entryHash);
if (remove(fullPath.c_str()) != 0) {
ALOGE("Error removing %s: %s", fullPath.c_str(), std::strerror(errno));
@@ -238,11 +252,9 @@
ALOGV("INIT: Entry %u is good, tracking it now.", entryHash);
- // Track details for rapid lookup later
- trackEntry(entryHash, header.valueSize, fileSize, st.st_atime);
-
- // Track the total size
- increaseTotalCacheSize(fileSize);
+ // Track details for rapid lookup later and update total size
+ // Note access time is a full timespec instead of just seconds
+ trackEntry(entryHash, header.valueSize, fileSize, st.st_atim);
// Preload the entry for fast retrieval
if ((mHotCacheSize + fileSize) < mHotCacheLimit) {
@@ -318,6 +330,28 @@
// Generate a hash of the key and use it to track this entry
uint32_t entryHash = android::JenkinsHashMixBytes(0, static_cast<const uint8_t*>(key), keySize);
+ std::string fullPath = mMultifileDirName + "/" + std::to_string(entryHash);
+
+ // See if we already have this file
+ if (flags::multifile_blobcache_advanced_usage() && contains(entryHash)) {
+ // Remove previous entry from hot cache
+ removeFromHotCache(entryHash);
+
+ // Remove previous entry and update the overall cache size
+ removeEntry(entryHash);
+
+ // If valueSize is zero, this is an indication that the user wants to remove the entry from
+ // cache It has already been removed from tracking, now remove it from disk It is safe to do
+ // this immediately because we drained the write queue in removeFromHotCache
+ if (valueSize == 0) {
+ ALOGV("SET: Zero size detected for existing entry, removing %u from cache", entryHash);
+ if (remove(fullPath.c_str()) != 0) {
+ ALOGW("SET: Error removing %s: %s", fullPath.c_str(), std::strerror(errno));
+ }
+ return;
+ }
+ }
+
size_t fileSize = sizeof(MultifileHeader) + keySize + valueSize;
// If we're going to be over the cache limit, kick off a trim to clear space
@@ -340,13 +374,12 @@
memcpy(static_cast<void*>(buffer + sizeof(MultifileHeader) + keySize),
static_cast<const void*>(value), valueSize);
- std::string fullPath = mMultifileDirName + "/" + std::to_string(entryHash);
-
- // Track the size and access time for quick recall
- trackEntry(entryHash, valueSize, fileSize, time(0));
-
- // Update the overall cache size
- increaseTotalCacheSize(fileSize);
+ // Track the size and access time for quick recall and update the overall cache size
+ struct timespec time = {0, 0};
+ if (flags::multifile_blobcache_advanced_usage()) {
+ clock_gettime(CLOCK_REALTIME, &time);
+ }
+ trackEntry(entryHash, valueSize, fileSize, time);
// Keep the entry in hot cache for quick retrieval
ALOGV("SET: Adding %u to hot cache.", entryHash);
@@ -428,6 +461,14 @@
if (mHotCache.find(entryHash) != mHotCache.end()) {
ALOGV("GET: HotCache HIT for entry %u", entryHash);
cacheEntry = mHotCache[entryHash].entryBuffer;
+
+ if (flags::multifile_blobcache_advanced_usage()) {
+ // Update last access time on disk
+ struct timespec times[2];
+ times[0].tv_nsec = UTIME_NOW;
+ times[1].tv_nsec = UTIME_OMIT;
+ utimensat(0, fullPath.c_str(), times, 0);
+ }
} else {
ALOGV("GET: HotCache MISS for entry: %u", entryHash);
@@ -456,6 +497,14 @@
cacheEntry =
reinterpret_cast<uint8_t*>(mmap(nullptr, fileSize, PROT_READ, MAP_PRIVATE, fd, 0));
+ if (flags::multifile_blobcache_advanced_usage()) {
+ // Update last access time and omit last modify time
+ struct timespec times[2];
+ times[0].tv_nsec = UTIME_NOW;
+ times[1].tv_nsec = UTIME_OMIT;
+ futimens(fd, times);
+ }
+
// We can close the file now and the mmap will remain
close(fd);
@@ -492,6 +541,13 @@
return 0;
}
+ if (flags::multifile_blobcache_advanced_usage()) {
+ // Update the entry time for this hash, so it reflects LRU
+ struct timespec time;
+ clock_gettime(CLOCK_REALTIME, &time);
+ updateEntryTime(entryHash, time);
+ }
+
// Remaining entry following the key is the value
uint8_t* cachedValue = cacheEntry + (keySize + sizeof(MultifileHeader));
memcpy(value, cachedValue, cachedValueSize);
@@ -532,9 +588,9 @@
mBuildId.length() > PROP_VALUE_MAX ? PROP_VALUE_MAX : mBuildId.length());
// Finally update the crc, using cacheVersion and everything the follows
- status.crc =
- crc32c(reinterpret_cast<uint8_t*>(&status) + offsetof(MultifileStatus, cacheVersion),
- sizeof(status) - offsetof(MultifileStatus, cacheVersion));
+ status.crc = GenerateCRC32(
+ reinterpret_cast<uint8_t *>(&status) + offsetof(MultifileStatus, cacheVersion),
+ sizeof(status) - offsetof(MultifileStatus, cacheVersion));
// Create the status file
std::string cacheStatus = baseDir + "/" + kMultifileBlobCacheStatusFile;
@@ -599,9 +655,9 @@
}
// Ensure we have a good CRC
- if (status.crc !=
- crc32c(reinterpret_cast<uint8_t*>(&status) + offsetof(MultifileStatus, cacheVersion),
- sizeof(status) - offsetof(MultifileStatus, cacheVersion))) {
+ if (status.crc != GenerateCRC32(reinterpret_cast<uint8_t *>(&status) +
+ offsetof(MultifileStatus, cacheVersion),
+ sizeof(status) - offsetof(MultifileStatus, cacheVersion))) {
ALOGE("STATUS(CHECK): Cache status failed CRC check!");
return false;
}
@@ -627,9 +683,47 @@
}
void MultifileBlobCache::trackEntry(uint32_t entryHash, EGLsizeiANDROID valueSize, size_t fileSize,
- time_t accessTime) {
+ const timespec& accessTime) {
+#if COM_ANDROID_GRAPHICS_EGL_FLAGS(MULTIFILE_BLOBCACHE_ADVANCED_USAGE)
+ // When we add this entry to the map, it is sorted by accessTime
+ MultifileEntryStatsMapIter entryStatsIter =
+ mEntryStats.emplace(std::piecewise_construct, std::forward_as_tuple(accessTime),
+ std::forward_as_tuple(entryHash, valueSize, fileSize));
+
+ // Track all entries with quick access to its stats
+ mEntries.emplace(entryHash, entryStatsIter);
+#else
+ (void)accessTime;
mEntries.insert(entryHash);
- mEntryStats[entryHash] = {valueSize, fileSize, accessTime};
+ mEntryStats[entryHash] = {entryHash, valueSize, fileSize};
+#endif // COM_ANDROID_GRAPHICS_EGL_FLAGS(MULTIFILE_BLOBCACHE_ADVANCED_USAGE)
+
+ increaseTotalCacheSize(fileSize);
+}
+
+bool MultifileBlobCache::removeEntry(uint32_t entryHash) {
+ auto entryIter = mEntries.find(entryHash);
+ if (entryIter == mEntries.end()) {
+ return false;
+ }
+
+#if COM_ANDROID_GRAPHICS_EGL_FLAGS(MULTIFILE_BLOBCACHE_ADVANCED_USAGE)
+ MultifileEntryStatsMapIter entryStatsIter = entryIter->second;
+ MultifileEntryStats entryStats = entryStatsIter->second;
+ decreaseTotalCacheSize(entryStats.fileSize);
+#else
+ auto entryStatsIter = mEntryStats.find(entryHash);
+ if (entryStatsIter == mEntryStats.end()) {
+ ALOGE("Failed to remove entryHash (%u) from mEntryStats", entryHash);
+ return false;
+ }
+ decreaseTotalCacheSize(entryStatsIter->second.fileSize);
+#endif // COM_ANDROID_GRAPHICS_EGL_FLAGS(MULTIFILE_BLOBCACHE_ADVANCED_USAGE)
+
+ mEntryStats.erase(entryStatsIter);
+ mEntries.erase(entryIter);
+
+ return true;
}
bool MultifileBlobCache::contains(uint32_t hashEntry) const {
@@ -637,7 +731,40 @@
}
MultifileEntryStats MultifileBlobCache::getEntryStats(uint32_t entryHash) {
+#if COM_ANDROID_GRAPHICS_EGL_FLAGS(MULTIFILE_BLOBCACHE_ADVANCED_USAGE)
+ auto entryIter = mEntries.find(entryHash);
+ if (entryIter == mEntries.end()) {
+ return {};
+ }
+
+ MultifileEntryStatsMapIter entryStatsIter = entryIter->second;
+ MultifileEntryStats entryStats = entryStatsIter->second;
+ return entryStats;
+#else
return mEntryStats[entryHash];
+#endif // COM_ANDROID_GRAPHICS_EGL_FLAGS(MULTIFILE_BLOBCACHE_ADVANCED_USAGE)
+}
+
+void MultifileBlobCache::updateEntryTime(uint32_t entryHash, const timespec& newTime) {
+#if COM_ANDROID_GRAPHICS_EGL_FLAGS(MULTIFILE_BLOBCACHE_ADVANCED_USAGE)
+ // This function updates the ordering of the map by removing the old iterators
+ // and re-adding them. If should be perforant as it does not perform a full re-sort.
+ // First, pull out the old entryStats
+ auto entryIter = mEntries.find(entryHash);
+ MultifileEntryStatsMapIter entryStatsIter = entryIter->second;
+ MultifileEntryStats entryStats = std::move(entryStatsIter->second);
+
+ // Remove the old iterators
+ mEntryStats.erase(entryStatsIter);
+ mEntries.erase(entryIter);
+
+ // Insert the new with updated time
+ entryStatsIter = mEntryStats.emplace(std::make_pair(newTime, std::move(entryStats)));
+ mEntries.emplace(entryHash, entryStatsIter);
+#else
+ (void)entryHash;
+ (void)newTime;
+#endif // COM_ANDROID_GRAPHICS_EGL_FLAGS(MULTIFILE_BLOBCACHE_ADVANCED_USAGE)
}
void MultifileBlobCache::increaseTotalCacheSize(size_t fileSize) {
@@ -719,31 +846,32 @@
bool MultifileBlobCache::applyLRU(size_t cacheSizeLimit, size_t cacheEntryLimit) {
// Walk through our map of sorted last access times and remove files until under the limit
for (auto cacheEntryIter = mEntryStats.begin(); cacheEntryIter != mEntryStats.end();) {
+#if COM_ANDROID_GRAPHICS_EGL_FLAGS(MULTIFILE_BLOBCACHE_ADVANCED_USAGE)
+ const MultifileEntryStats& entryStats = cacheEntryIter->second;
+ uint32_t entryHash = entryStats.entryHash;
+#else
uint32_t entryHash = cacheEntryIter->first;
+ const MultifileEntryStats& entryStats = cacheEntryIter->second;
+#endif // COM_ANDROID_GRAPHICS_EGL_FLAGS(MULTIFILE_BLOBCACHE_ADVANCED_USAGE)
ALOGV("LRU: Removing entryHash %u", entryHash);
- // Track the overall size
- MultifileEntryStats entryStats = getEntryStats(entryHash);
- decreaseTotalCacheSize(entryStats.fileSize);
-
// Remove it from hot cache if present
removeFromHotCache(entryHash);
// Remove it from the system
std::string entryPath = mMultifileDirName + "/" + std::to_string(entryHash);
if (remove(entryPath.c_str()) != 0) {
- ALOGE("LRU: Error removing %s: %s", entryPath.c_str(), std::strerror(errno));
- return false;
+ // Continue evicting invalid item (app's cache might be cleared)
+ ALOGW("LRU: Error removing %s: %s", entryPath.c_str(), std::strerror(errno));
}
// Increment the iterator before clearing the entry
cacheEntryIter++;
- // Delete the entry from our tracking
- size_t count = mEntryStats.erase(entryHash);
- if (count != 1) {
- ALOGE("LRU: Failed to remove entryHash (%u) from mEntryStats", entryHash);
+ // Delete the entry from our tracking and update the overall cache size
+ if (!removeEntry(entryHash)) {
+ ALOGE("LRU: Failed to remove entryHash %u", entryHash);
return false;
}
@@ -795,11 +923,6 @@
return true;
}
-// When removing files, what fraction of the overall limit should be reached when removing files
-// A divisor of two will decrease the cache to 50%, four to 25% and so on
-// We use the same limit to manage size and entry count
-constexpr uint32_t kCacheLimitDivisor = 2;
-
// Calculate the cache size and remove old entries until under the limit
void MultifileBlobCache::trimCache() {
// Wait for all deferred writes to complete
@@ -807,8 +930,10 @@
waitForWorkComplete();
ALOGV("TRIM: Reducing multifile cache size to %zu, entries %zu",
- mMaxTotalSize / kCacheLimitDivisor, mMaxTotalEntries / kCacheLimitDivisor);
- if (!applyLRU(mMaxTotalSize / kCacheLimitDivisor, mMaxTotalEntries / kCacheLimitDivisor)) {
+ mMaxTotalSize / mTotalCacheSizeDivisor, mMaxTotalEntries / mTotalCacheSizeDivisor);
+
+ if (!applyLRU(mMaxTotalSize / mTotalCacheSizeDivisor,
+ mMaxTotalEntries / mTotalCacheSizeDivisor)) {
ALOGE("Error when clearing multifile shader cache");
return;
}
@@ -831,17 +956,44 @@
// Create the file or reset it if already present, read+write for user only
int fd = open(fullPath.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (fd == -1) {
- ALOGE("Cache error in SET - failed to open fullPath: %s, error: %s",
- fullPath.c_str(), std::strerror(errno));
- return;
+ if (flags::multifile_blobcache_advanced_usage()) {
+ struct stat st;
+ if (stat(mMultifileDirName.c_str(), &st) == -1) {
+ ALOGW("Cache directory missing (app's cache cleared?). Recreating...");
+
+ // Restore the multifile directory
+ if (mkdir(mMultifileDirName.c_str(), 0755) != 0 && (errno != EEXIST)) {
+ ALOGE("Cache error in SET - Unable to create directory (%s), errno "
+ "(%i)",
+ mMultifileDirName.c_str(), errno);
+ return;
+ }
+
+ // Create new status file
+ if (!createStatus(mMultifileDirName.c_str())) {
+ ALOGE("Cache error in SET - Failed to create status file!");
+ return;
+ }
+
+ // Try to open the file again
+ fd = open(fullPath.c_str(), O_WRONLY | O_CREAT | O_TRUNC,
+ S_IRUSR | S_IWUSR);
+ }
+ }
+
+ if (fd == -1) {
+ ALOGE("Cache error in SET - failed to open fullPath: %s, error: %s",
+ fullPath.c_str(), std::strerror(errno));
+ return;
+ }
}
ALOGV("DEFERRED: Opened fd %i from %s", fd, fullPath.c_str());
// Add CRC check to the header (always do this last!)
MultifileHeader* header = reinterpret_cast<MultifileHeader*>(buffer);
- header->crc =
- crc32c(buffer + sizeof(MultifileHeader), bufferSize - sizeof(MultifileHeader));
+ header->crc = GenerateCRC32(buffer + sizeof(MultifileHeader),
+ bufferSize - sizeof(MultifileHeader));
ssize_t result = write(fd, buffer, bufferSize);
if (result != bufferSize) {
@@ -850,6 +1002,14 @@
return;
}
+ if (flags::multifile_blobcache_advanced_usage()) {
+ // Update last access time and last modify time
+ struct timespec times[2];
+ times[0].tv_nsec = UTIME_NOW;
+ times[1].tv_nsec = UTIME_NOW;
+ futimens(fd, times);
+ }
+
ALOGV("DEFERRED: Completed write for: %s", fullPath.c_str());
close(fd);
diff --git a/opengl/libs/EGL/MultifileBlobCache.h b/opengl/libs/EGL/MultifileBlobCache.h
index 18566c2..3bd393f 100644
--- a/opengl/libs/EGL/MultifileBlobCache.h
+++ b/opengl/libs/EGL/MultifileBlobCache.h
@@ -32,9 +32,13 @@
#include "FileBlobCache.h"
+#include <com_android_graphics_egl_flags.h>
+
+using namespace com::android::graphics::egl;
+
namespace android {
-constexpr uint32_t kMultifileBlobCacheVersion = 1;
+constexpr uint32_t kMultifileBlobCacheVersion = 2;
constexpr char kMultifileBlobCacheStatusFile[] = "cache.status";
struct MultifileHeader {
@@ -45,9 +49,9 @@
};
struct MultifileEntryStats {
+ uint32_t entryHash;
EGLsizeiANDROID valueSize;
size_t fileSize;
- time_t accessTime;
};
struct MultifileStatus {
@@ -100,6 +104,26 @@
size_t mBufferSize;
};
+#if COM_ANDROID_GRAPHICS_EGL_FLAGS(MULTIFILE_BLOBCACHE_ADVANCED_USAGE)
+struct MultifileTimeLess {
+ bool operator()(const struct timespec& t1, const struct timespec& t2) const {
+ if (t1.tv_sec == t2.tv_sec) {
+ // If seconds are equal, check nanoseconds
+ return t1.tv_nsec < t2.tv_nsec;
+ } else {
+ // Otherwise, compare seconds
+ return t1.tv_sec < t2.tv_sec;
+ }
+ }
+};
+
+// The third parameter here causes all entries to be sorted by access time,
+// so oldest will be accessed first in applyLRU
+using MultifileEntryStatsMap =
+ std::multimap<struct timespec, MultifileEntryStats, MultifileTimeLess>;
+using MultifileEntryStatsMapIter = MultifileEntryStatsMap::iterator;
+#endif // COM_ANDROID_GRAPHICS_EGL_FLAGS(MULTIFILE_BLOBCACHE_ADVANCED_USAGE)
+
class MultifileBlobCache {
public:
MultifileBlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize,
@@ -115,6 +139,7 @@
size_t getTotalSize() const { return mTotalCacheSize; }
size_t getTotalEntries() const { return mTotalCacheEntries; }
+ size_t getTotalCacheSizeDivisor() const { return mTotalCacheSizeDivisor; }
const std::string& getCurrentBuildId() const { return mBuildId; }
void setCurrentBuildId(const std::string& buildId) { mBuildId = buildId; }
@@ -124,10 +149,11 @@
private:
void trackEntry(uint32_t entryHash, EGLsizeiANDROID valueSize, size_t fileSize,
- time_t accessTime);
+ const timespec& accessTime);
bool contains(uint32_t entryHash) const;
bool removeEntry(uint32_t entryHash);
MultifileEntryStats getEntryStats(uint32_t entryHash);
+ void updateEntryTime(uint32_t entryHash, const timespec& newTime);
bool createStatus(const std::string& baseDir);
bool checkStatus(const std::string& baseDir);
@@ -151,8 +177,14 @@
std::string mBuildId;
uint32_t mCacheVersion;
+#if COM_ANDROID_GRAPHICS_EGL_FLAGS(MULTIFILE_BLOBCACHE_ADVANCED_USAGE)
+ std::unordered_map<uint32_t, MultifileEntryStatsMapIter> mEntries;
+ MultifileEntryStatsMap mEntryStats;
+#else
std::unordered_set<uint32_t> mEntries;
std::unordered_map<uint32_t, MultifileEntryStats> mEntryStats;
+#endif // COM_ANDROID_GRAPHICS_EGL_FLAGS(MULTIFILE_BLOBCACHE_ADVANCED_USAGE)
+
std::unordered_map<uint32_t, MultifileHotCache> mHotCache;
size_t mMaxKeySize;
@@ -161,6 +193,7 @@
size_t mMaxTotalEntries;
size_t mTotalCacheSize;
size_t mTotalCacheEntries;
+ size_t mTotalCacheSizeDivisor;
size_t mHotCacheLimit;
size_t mHotCacheEntryLimit;
size_t mHotCacheSize;
diff --git a/opengl/libs/EGL/MultifileBlobCache_test.cpp b/opengl/libs/EGL/MultifileBlobCache_test.cpp
index 90a0f1e..85fb29e 100644
--- a/opengl/libs/EGL/MultifileBlobCache_test.cpp
+++ b/opengl/libs/EGL/MultifileBlobCache_test.cpp
@@ -21,10 +21,15 @@
#include <fcntl.h>
#include <gtest/gtest.h>
#include <stdio.h>
+#include <utils/JenkinsHash.h>
#include <fstream>
#include <memory>
+#include <com_android_graphics_egl_flags.h>
+
+using namespace com::android::graphics::egl;
+
using namespace std::literals;
namespace android {
@@ -55,6 +60,7 @@
std::vector<std::string> getCacheEntries();
void clearProperties();
+ bool clearCache();
std::unique_ptr<TemporaryFile> mTempFile;
std::unique_ptr<MultifileBlobCache> mMBC;
@@ -314,7 +320,7 @@
struct stat info;
if (stat(multifileDirName.c_str(), &info) == 0) {
- // We have a multifile dir. Skip the status file and return the only entry.
+ // We have a multifile dir. Skip the status file and return the entries.
DIR* dir;
struct dirent* entry;
if ((dir = opendir(multifileDirName.c_str())) != nullptr) {
@@ -325,6 +331,7 @@
if (strcmp(entry->d_name, kMultifileBlobCacheStatusFile) == 0) {
continue;
}
+ // printf("Found entry: %s\n", entry->d_name);
cacheEntries.push_back(multifileDirName + "/" + entry->d_name);
}
} else {
@@ -458,6 +465,8 @@
// Set one entry
mMBC->set("abcd", 4, "efgh", 4);
+ uint32_t initialCacheVersion = mMBC->getCurrentCacheVersion();
+
// Close the cache so everything writes out
mMBC->finish();
mMBC.reset();
@@ -466,7 +475,7 @@
ASSERT_EQ(getCacheEntries().size(), 1);
// Set a debug cacheVersion
- std::string newCacheVersion = std::to_string(kMultifileBlobCacheVersion + 1);
+ std::string newCacheVersion = std::to_string(initialCacheVersion + 1);
ASSERT_TRUE(base::SetProperty("debug.egl.blobcache.cache_version", newCacheVersion.c_str()));
ASSERT_TRUE(
base::WaitForProperty("debug.egl.blobcache.cache_version", newCacheVersion.c_str()));
@@ -503,4 +512,404 @@
ASSERT_EQ(getCacheEntries().size(), 0);
}
+// Ensure cache is correct when a key is reused
+TEST_F(MultifileBlobCacheTest, SameKeyDifferentValues) {
+ if (!flags::multifile_blobcache_advanced_usage()) {
+ GTEST_SKIP() << "Skipping test that requires multifile_blobcache_advanced_usage flag";
+ }
+
+ unsigned char buf[4] = {0xee, 0xee, 0xee, 0xee};
+
+ size_t startingSize = mMBC->getTotalSize();
+
+ // New cache should be empty
+ ASSERT_EQ(startingSize, 0);
+
+ // Set an initial value
+ mMBC->set("ab", 2, "cdef", 4);
+
+ // Grab the new size
+ size_t firstSize = mMBC->getTotalSize();
+
+ // Ensure the size went up
+ // Note: Checking for an exact size is challenging, as the
+ // file size can differ between platforms.
+ ASSERT_GT(firstSize, startingSize);
+
+ // Verify the cache is correct
+ ASSERT_EQ(size_t(4), mMBC->get("ab", 2, buf, 4));
+ ASSERT_EQ('c', buf[0]);
+ ASSERT_EQ('d', buf[1]);
+ ASSERT_EQ('e', buf[2]);
+ ASSERT_EQ('f', buf[3]);
+
+ // Now reuse the key with a smaller value
+ mMBC->set("ab", 2, "gh", 2);
+
+ // Grab the new size
+ size_t secondSize = mMBC->getTotalSize();
+
+ // Ensure it decreased in size
+ ASSERT_LT(secondSize, firstSize);
+
+ // Verify the cache is correct
+ ASSERT_EQ(size_t(2), mMBC->get("ab", 2, buf, 2));
+ ASSERT_EQ('g', buf[0]);
+ ASSERT_EQ('h', buf[1]);
+
+ // Now put back the original value
+ mMBC->set("ab", 2, "cdef", 4);
+
+ // And we should get back a stable size
+ size_t finalSize = mMBC->getTotalSize();
+ ASSERT_EQ(firstSize, finalSize);
+}
+
+// Ensure cache is correct when a key is reused with large value size
+TEST_F(MultifileBlobCacheTest, SameKeyLargeValues) {
+ if (!flags::multifile_blobcache_advanced_usage()) {
+ GTEST_SKIP() << "Skipping test that requires multifile_blobcache_advanced_usage flag";
+ }
+
+ // Create the cache with larger limits to stress test reuse
+ constexpr uint32_t kLocalMaxKeySize = 1 * 1024 * 1024;
+ constexpr uint32_t kLocalMaxValueSize = 4 * 1024 * 1024;
+ constexpr uint32_t kLocalMaxTotalSize = 32 * 1024 * 1024;
+ mMBC.reset(new MultifileBlobCache(kLocalMaxKeySize, kLocalMaxValueSize, kLocalMaxTotalSize,
+ kMaxTotalEntries, &mTempFile->path[0]));
+
+ constexpr uint32_t kLargeValueCount = 8;
+ constexpr uint32_t kLargeValueSize = 64 * 1024;
+
+ // Create a several really large values
+ unsigned char largeValue[kLargeValueCount][kLargeValueSize];
+ for (int i = 0; i < kLargeValueCount; i++) {
+ for (int j = 0; j < kLargeValueSize; j++) {
+ // Fill the value with the index for uniqueness
+ largeValue[i][j] = i;
+ }
+ }
+
+ size_t startingSize = mMBC->getTotalSize();
+
+ // New cache should be empty
+ ASSERT_EQ(startingSize, 0);
+
+ // Cycle through the values and set them all in sequence
+ for (int i = 0; i < kLargeValueCount; i++) {
+ mMBC->set("abcd", 4, largeValue[i], kLargeValueSize);
+ }
+
+ // Ensure we get the last one back
+ unsigned char outBuf[kLargeValueSize];
+ mMBC->get("abcd", 4, outBuf, kLargeValueSize);
+
+ for (int i = 0; i < kLargeValueSize; i++) {
+ // Buffer should contain highest index value
+ ASSERT_EQ(kLargeValueCount - 1, outBuf[i]);
+ }
+}
+
+// Ensure cache eviction is LRU
+TEST_F(MultifileBlobCacheTest, CacheEvictionIsLRU) {
+ if (!flags::multifile_blobcache_advanced_usage()) {
+ GTEST_SKIP() << "Skipping test that requires multifile_blobcache_advanced_usage flag";
+ }
+
+ // Fill the cache with exactly how much it can hold
+ int entry = 0;
+ for (entry = 0; entry < kMaxTotalEntries; entry++) {
+ // Use the index as the key and value
+ mMBC->set(&entry, sizeof(entry), &entry, sizeof(entry));
+
+ int result = 0;
+ ASSERT_EQ(sizeof(entry), mMBC->get(&entry, sizeof(entry), &result, sizeof(result)));
+ ASSERT_EQ(entry, result);
+ }
+
+ // Ensure the cache is full
+ ASSERT_EQ(mMBC->getTotalEntries(), kMaxTotalEntries);
+
+ // Add one more entry to trigger eviction
+ size_t overflowEntry = kMaxTotalEntries;
+ mMBC->set(&overflowEntry, sizeof(overflowEntry), &overflowEntry, sizeof(overflowEntry));
+
+ // Verify it contains the right amount, which will be one more than reduced size
+ // because we evict the cache before adding a new entry
+ size_t evictionLimit = kMaxTotalEntries / mMBC->getTotalCacheSizeDivisor();
+ ASSERT_EQ(mMBC->getTotalEntries(), evictionLimit + 1);
+
+ // Ensure cache is as expected, with old entries removed, newer entries remaining
+ for (entry = 0; entry < kMaxTotalEntries; entry++) {
+ int result = 0;
+ mMBC->get(&entry, sizeof(entry), &result, sizeof(result));
+
+ if (entry < evictionLimit) {
+ // We should get no hits on evicted entries, i.e. the first added
+ ASSERT_EQ(result, 0);
+ } else {
+ // Above the limit should still be present
+ ASSERT_EQ(result, entry);
+ }
+ }
+}
+
+// Ensure calling GET on an entry updates its access time, even if already in hotcache
+TEST_F(MultifileBlobCacheTest, GetUpdatesAccessTime) {
+ if (!flags::multifile_blobcache_advanced_usage()) {
+ GTEST_SKIP() << "Skipping test that requires multifile_blobcache_advanced_usage flag";
+ }
+
+ // Fill the cache with exactly how much it can hold
+ int entry = 0;
+ int result = 0;
+ for (entry = 0; entry < kMaxTotalEntries; entry++) {
+ // Use the index as the key and value
+ mMBC->set(&entry, sizeof(entry), &entry, sizeof(entry));
+ ASSERT_EQ(sizeof(entry), mMBC->get(&entry, sizeof(entry), &result, sizeof(result)));
+ ASSERT_EQ(entry, result);
+ }
+
+ // Ensure the cache is full
+ ASSERT_EQ(mMBC->getTotalEntries(), kMaxTotalEntries);
+
+ // GET the first few entries to update their access time
+ std::vector<int> accessedEntries = {1, 2, 3};
+ for (int i = 0; i < accessedEntries.size(); i++) {
+ entry = accessedEntries[i];
+ ASSERT_EQ(sizeof(entry), mMBC->get(&entry, sizeof(entry), &result, sizeof(result)));
+ }
+
+ // Add one more entry to trigger eviction
+ size_t overflowEntry = kMaxTotalEntries;
+ mMBC->set(&overflowEntry, sizeof(overflowEntry), &overflowEntry, sizeof(overflowEntry));
+
+ size_t evictionLimit = kMaxTotalEntries / mMBC->getTotalCacheSizeDivisor();
+
+ // Ensure cache is as expected, with old entries removed, newer entries remaining
+ for (entry = 0; entry < kMaxTotalEntries; entry++) {
+ int result = 0;
+ mMBC->get(&entry, sizeof(entry), &result, sizeof(result));
+
+ if (std::find(accessedEntries.begin(), accessedEntries.end(), entry) !=
+ accessedEntries.end()) {
+ // If this is one of the handful we accessed after filling the cache,
+ // they should still be in the cache because LRU
+ ASSERT_EQ(result, entry);
+ } else if (entry >= (evictionLimit + accessedEntries.size())) {
+ // If they were above the eviction limit (plus three for our updated entries),
+ // they should still be present
+ ASSERT_EQ(result, entry);
+ } else {
+ // Otherwise, they shold be evicted and no longer present
+ ASSERT_EQ(result, 0);
+ }
+ }
+
+ // Close the cache so everything writes out
+ mMBC->finish();
+ mMBC.reset();
+
+ // Open the cache again
+ mMBC.reset(new MultifileBlobCache(kMaxKeySize, kMaxValueSize, kMaxTotalSize, kMaxTotalEntries,
+ &mTempFile->path[0]));
+
+ // Check the cache again, ensuring the updated access time made it to disk
+ for (entry = 0; entry < kMaxTotalEntries; entry++) {
+ int result = 0;
+ mMBC->get(&entry, sizeof(entry), &result, sizeof(result));
+ if (std::find(accessedEntries.begin(), accessedEntries.end(), entry) !=
+ accessedEntries.end()) {
+ ASSERT_EQ(result, entry);
+ } else if (entry >= (evictionLimit + accessedEntries.size())) {
+ ASSERT_EQ(result, entry);
+ } else {
+ ASSERT_EQ(result, 0);
+ }
+ }
+}
+
+bool MultifileBlobCacheTest::clearCache() {
+ std::string cachePath = &mTempFile->path[0];
+ std::string multifileDirName = cachePath + ".multifile";
+
+ DIR* dir = opendir(multifileDirName.c_str());
+ if (dir == nullptr) {
+ printf("Error opening directory: %s\n", multifileDirName.c_str());
+ return false;
+ }
+
+ struct dirent* entry;
+ while ((entry = readdir(dir)) != nullptr) {
+ // Skip "." and ".." entries
+ if (std::string(entry->d_name) == "." || std::string(entry->d_name) == "..") {
+ continue;
+ }
+
+ std::string entryPath = multifileDirName + "/" + entry->d_name;
+
+ // Delete the entry (we assert it's a file, nothing nested here)
+ if (unlink(entryPath.c_str()) != 0) {
+ printf("Error deleting file: %s\n", entryPath.c_str());
+ closedir(dir);
+ return false;
+ }
+ }
+
+ closedir(dir);
+
+ // Delete the empty directory itself
+ if (rmdir(multifileDirName.c_str()) != 0) {
+ printf("Error deleting directory %s, error %s\n", multifileDirName.c_str(),
+ std::strerror(errno));
+ return false;
+ }
+
+ return true;
+}
+
+// Recover from lost cache in the case of app clearing it
+TEST_F(MultifileBlobCacheTest, RecoverFromLostCache) {
+ if (!flags::multifile_blobcache_advanced_usage()) {
+ GTEST_SKIP() << "Skipping test that requires multifile_blobcache_advanced_usage flag";
+ }
+
+ int entry = 0;
+ int result = 0;
+
+ uint32_t kEntryCount = 10;
+
+ // Add some entries
+ for (entry = 0; entry < kEntryCount; entry++) {
+ mMBC->set(&entry, sizeof(entry), &entry, sizeof(entry));
+ ASSERT_EQ(sizeof(entry), mMBC->get(&entry, sizeof(entry), &result, sizeof(result)));
+ ASSERT_EQ(entry, result);
+ }
+
+ // For testing, wait until the entries have completed writing
+ mMBC->finish();
+
+ // Manually delete the cache!
+ ASSERT_TRUE(clearCache());
+
+ // Cache should not contain any entries
+ for (entry = 0; entry < kEntryCount; entry++) {
+ ASSERT_EQ(size_t(0), mMBC->get(&entry, sizeof(entry), &result, sizeof(result)));
+ }
+
+ // Ensure we can still add new ones
+ for (entry = kEntryCount; entry < kEntryCount * 2; entry++) {
+ mMBC->set(&entry, sizeof(entry), &entry, sizeof(entry));
+ ASSERT_EQ(sizeof(entry), mMBC->get(&entry, sizeof(entry), &result, sizeof(result)));
+ ASSERT_EQ(entry, result);
+ }
+
+ // Close the cache so everything writes out
+ mMBC->finish();
+ mMBC.reset();
+
+ // Open the cache again
+ mMBC.reset(new MultifileBlobCache(kMaxKeySize, kMaxValueSize, kMaxTotalSize, kMaxTotalEntries,
+ &mTempFile->path[0]));
+
+ // Before fixes, writing the second entries to disk should have failed due to missing
+ // cache dir. But now they should have survived our shutdown above.
+ for (entry = kEntryCount; entry < kEntryCount * 2; entry++) {
+ ASSERT_EQ(sizeof(entry), mMBC->get(&entry, sizeof(entry), &result, sizeof(result)));
+ ASSERT_EQ(entry, result);
+ }
+}
+
+// Ensure cache eviction succeeds if the cache is deleted
+TEST_F(MultifileBlobCacheTest, EvictAfterLostCache) {
+ if (!flags::multifile_blobcache_advanced_usage()) {
+ GTEST_SKIP() << "Skipping test that requires multifile_blobcache_advanced_usage flag";
+ }
+
+ int entry = 0;
+ int result = 0;
+
+ uint32_t kEntryCount = 10;
+
+ // Add some entries
+ for (entry = 0; entry < kEntryCount; entry++) {
+ mMBC->set(&entry, sizeof(entry), &entry, sizeof(entry));
+ ASSERT_EQ(sizeof(entry), mMBC->get(&entry, sizeof(entry), &result, sizeof(result)));
+ ASSERT_EQ(entry, result);
+ }
+
+ // For testing, wait until the entries have completed writing
+ mMBC->finish();
+
+ // Manually delete the cache!
+ ASSERT_TRUE(clearCache());
+
+ // Now start adding entries to trigger eviction, cache should survive
+ for (entry = kEntryCount; entry < 2 * kMaxTotalEntries; entry++) {
+ mMBC->set(&entry, sizeof(entry), &entry, sizeof(entry));
+ ASSERT_EQ(sizeof(entry), mMBC->get(&entry, sizeof(entry), &result, sizeof(result)));
+ ASSERT_EQ(entry, result);
+ }
+
+ // We should have triggered multiple evictions above and remain at or below the
+ // max amount of entries
+ ASSERT_LE(getCacheEntries().size(), kMaxTotalEntries);
+}
+
+// Remove from cache when size is zero
+TEST_F(MultifileBlobCacheTest, ZeroSizeRemovesEntry) {
+ if (!flags::multifile_blobcache_advanced_usage()) {
+ GTEST_SKIP() << "Skipping test that requires multifile_blobcache_advanced_usage flag";
+ }
+
+ // Put some entries in
+ int entry = 0;
+ int result = 0;
+
+ uint32_t kEntryCount = 20;
+
+ // Add some entries
+ for (entry = 0; entry < kEntryCount; entry++) {
+ mMBC->set(&entry, sizeof(entry), &entry, sizeof(entry));
+ ASSERT_EQ(sizeof(entry), mMBC->get(&entry, sizeof(entry), &result, sizeof(result)));
+ ASSERT_EQ(entry, result);
+ }
+
+ // Send some of them again with size zero
+ std::vector<int> removedEntries = {5, 10, 18};
+ for (int i = 0; i < removedEntries.size(); i++) {
+ entry = removedEntries[i];
+ mMBC->set(&entry, sizeof(entry), nullptr, 0);
+ }
+
+ // Ensure they do not get a hit
+ for (int i = 0; i < removedEntries.size(); i++) {
+ entry = removedEntries[i];
+ ASSERT_EQ(size_t(0), mMBC->get(&entry, sizeof(entry), &result, sizeof(result)));
+ }
+
+ // And have been removed from disk
+ std::vector<std::string> diskEntries = getCacheEntries();
+ ASSERT_EQ(diskEntries.size(), kEntryCount - removedEntries.size());
+ for (int i = 0; i < removedEntries.size(); i++) {
+ entry = removedEntries[i];
+ // Generate a hash for our removed entries and ensure they are not contained
+ // Note our entry and key and the same here, so we're hashing the key just like
+ // the multifile blobcache does.
+ uint32_t entryHash =
+ android::JenkinsHashMixBytes(0, reinterpret_cast<uint8_t*>(&entry), sizeof(entry));
+ ASSERT_EQ(std::find(diskEntries.begin(), diskEntries.end(), std::to_string(entryHash)),
+ diskEntries.end());
+ }
+
+ // Ensure the others are still present
+ for (entry = 0; entry < kEntryCount; entry++) {
+ if (std::find(removedEntries.begin(), removedEntries.end(), entry) ==
+ removedEntries.end()) {
+ ASSERT_EQ(sizeof(entry), mMBC->get(&entry, sizeof(entry), &result, sizeof(result)));
+ ASSERT_EQ(result, entry);
+ }
+ }
+}
+
} // namespace android
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index b1a287f..0dd9f19 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -22,6 +22,7 @@
#include <android-base/properties.h>
#include <android/dlext.h>
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <com_android_graphics_graphicsenv_flags.h>
#include <configstore/Utils.h>
#include <dlfcn.h>
#include <graphicsenv/GraphicsEnv.h>
@@ -37,6 +38,7 @@
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
+namespace graphicsenv_flags = com::android::graphics::graphicsenv::flags;
namespace android {
@@ -132,21 +134,47 @@
if (cnx->egl.eglGetPlatformDisplay) {
std::vector<EGLAttrib> attrs;
+ // These must have the same lifetime as |attrs|, because |attrs| contains pointers to these
+ // variables.
+ std::vector<const char*> enabled; // ANGLE features to enable
+ std::vector<const char*> disabled; // ANGLE features to disable
+
if (attrib_list) {
for (const EGLAttrib* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
attrs.push_back(attr[0]);
attrs.push_back(attr[1]);
}
}
- const auto& eglFeatures = GraphicsEnv::getInstance().getAngleEglFeatures();
- std::vector<const char*> features;
- if (eglFeatures.size() > 0) {
+
+ if (graphicsenv_flags::feature_overrides()) {
+ // Get the list of ANGLE features to enable from Global.Settings.
+ const auto& eglFeatures = GraphicsEnv::getInstance().getAngleEglFeatures();
for (const std::string& eglFeature : eglFeatures) {
- features.push_back(eglFeature.c_str());
+ enabled.push_back(eglFeature.c_str());
}
- features.push_back(0);
- attrs.push_back(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE);
- attrs.push_back(reinterpret_cast<EGLAttrib>(features.data()));
+
+ // Get the list of ANGLE features to enable/disable from gpuservice.
+ GraphicsEnv::getInstance().getAngleFeatureOverrides(enabled, disabled);
+ if (!enabled.empty()) {
+ enabled.push_back(nullptr);
+ attrs.push_back(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE);
+ attrs.push_back(reinterpret_cast<EGLAttrib>(enabled.data()));
+ }
+ if (!disabled.empty()) {
+ disabled.push_back(nullptr);
+ attrs.push_back(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE);
+ attrs.push_back(reinterpret_cast<EGLAttrib>(disabled.data()));
+ }
+ } else {
+ const auto& eglFeatures = GraphicsEnv::getInstance().getAngleEglFeatures();
+ if (!eglFeatures.empty()) {
+ for (const std::string& eglFeature : eglFeatures) {
+ enabled.push_back(eglFeature.c_str());
+ }
+ enabled.push_back(nullptr);
+ attrs.push_back(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE);
+ attrs.push_back(reinterpret_cast<EGLAttrib>(enabled.data()));
+ }
}
attrs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
diff --git a/opengl/libs/EGL/egl_flags.aconfig b/opengl/libs/EGL/egl_flags.aconfig
new file mode 100644
index 0000000..1157970
--- /dev/null
+++ b/opengl/libs/EGL/egl_flags.aconfig
@@ -0,0 +1,13 @@
+package: "com.android.graphics.egl.flags"
+container: "system"
+
+flag {
+ name: "multifile_blobcache_advanced_usage"
+ namespace: "gpu"
+ description: "This flag controls new behaviors to address bugs found via advanced usage"
+ bug: "380483358"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/opengl/libs/EGL/fuzzer/Android.bp b/opengl/libs/EGL/fuzzer/Android.bp
index 022a2a3..fe5f2a6 100644
--- a/opengl/libs/EGL/fuzzer/Android.bp
+++ b/opengl/libs/EGL/fuzzer/Android.bp
@@ -36,6 +36,11 @@
"libutils",
],
+ shared_libs: [
+ "libegl_flags",
+ "libz",
+ ],
+
srcs: [
"MultifileBlobCache_fuzzer.cpp",
],
diff --git a/opengl/tests/EGLTest/Android.bp b/opengl/tests/EGLTest/Android.bp
index aebd3f2..ed46efd 100644
--- a/opengl/tests/EGLTest/Android.bp
+++ b/opengl/tests/EGLTest/Android.bp
@@ -26,6 +26,7 @@
"android.hardware.configstore@1.0",
"android.hardware.configstore-utils",
"libEGL",
+ "libegl_flags",
"libbase",
"libcutils",
"libbinder",
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index 503d7df..ebdc629 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -141,7 +141,7 @@
};
EXPECT_TRUE(eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs));
- struct MockConsumer : public BnConsumerListener {
+ struct MockConsumer : public IConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -261,7 +261,7 @@
EXPECT_EQ(components[2], 8);
EXPECT_EQ(components[3], 8);
- struct MockConsumer : public BnConsumerListener {
+ struct MockConsumer : public IConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -309,7 +309,7 @@
get8BitConfig(config);
- struct MockConsumer : public BnConsumerListener {
+ struct MockConsumer : public IConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -406,7 +406,7 @@
EXPECT_EQ(components[2], 10);
EXPECT_EQ(components[3], 2);
- struct MockConsumer : public BnConsumerListener {
+ struct MockConsumer : public IConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -578,7 +578,7 @@
ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
- struct MockConsumer : public BnConsumerListener {
+ struct MockConsumer : public IConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -630,7 +630,7 @@
ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
- struct MockConsumer : public BnConsumerListener {
+ struct MockConsumer : public IConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -713,7 +713,7 @@
EXPECT_GE(components[2], 16);
EXPECT_GE(components[3], 16);
- struct MockConsumer : public BnConsumerListener {
+ struct MockConsumer : public IConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -742,7 +742,7 @@
ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_KHR_no_config_context"));
- struct MockConsumer : public BnConsumerListener {
+ struct MockConsumer : public IConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -765,6 +765,30 @@
}
}
+// Verify that eglCreateContext works when EGL_TELEMETRY_HINT_ANDROID is used with
+// NO_HINT = 0, SKIP_TELEMETRY = 1 and an invalid of value of 2
+TEST_F(EGLTest, EGLContextTelemetryHintExt) {
+ for (int i = 0; i < 3; i++) {
+ EGLConfig config;
+ get8BitConfig(config);
+ std::vector<EGLint> contextAttributes;
+ contextAttributes.reserve(4);
+ contextAttributes.push_back(EGL_TELEMETRY_HINT_ANDROID);
+ contextAttributes.push_back(i);
+ contextAttributes.push_back(EGL_NONE);
+ contextAttributes.push_back(EGL_NONE);
+
+ EGLContext eglContext = eglCreateContext(mEglDisplay, config, EGL_NO_CONTEXT,
+ contextAttributes.data());
+ EXPECT_NE(EGL_NO_CONTEXT, eglContext);
+ EXPECT_EQ(EGL_SUCCESS, eglGetError());
+
+ if (eglContext != EGL_NO_CONTEXT) {
+ eglDestroyContext(mEglDisplay, eglContext);
+ }
+ }
+}
+
// Emulate what a native application would do to create a
// 10:10:10:2 surface.
TEST_F(EGLTest, EGLConfig1010102) {
@@ -817,7 +841,7 @@
EXPECT_EQ(components[2], 10);
EXPECT_EQ(components[3], 2);
- struct MockConsumer : public BnConsumerListener {
+ struct MockConsumer : public IConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -843,7 +867,7 @@
ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
- struct MockConsumer : public BnConsumerListener {
+ struct MockConsumer : public IConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -896,7 +920,7 @@
ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
ASSERT_EQ(1, numConfigs);
- struct MockConsumer : public BnConsumerListener {
+ struct MockConsumer : public IConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -927,7 +951,7 @@
ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
- struct MockConsumer : public BnConsumerListener {
+ struct MockConsumer : public IConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
@@ -973,7 +997,7 @@
ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
- struct MockConsumer : public BnConsumerListener {
+ struct MockConsumer : public IConsumerListener {
void onFrameAvailable(const BufferItem& /* item */) override {}
void onBuffersReleased() override {}
void onSidebandStreamChanged() override {}
diff --git a/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.cpp b/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.cpp
index 7c255ed..5ba72af 100644
--- a/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.cpp
+++ b/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.cpp
@@ -113,7 +113,7 @@
if (producer == NULL)
goto not_valid_surface;
- window = new android::Surface(producer, true);
+ window = android::sp<android::Surface>::make(producer, true);
if (window == NULL)
goto not_valid_surface;
diff --git a/services/audiomanager/Android.bp b/services/audiomanager/Android.bp
index d11631b..afcdf74 100644
--- a/services/audiomanager/Android.bp
+++ b/services/audiomanager/Android.bp
@@ -15,6 +15,7 @@
],
shared_libs: [
+ "av-types-aidl-cpp",
"libutils",
"libbinder",
"liblog",
diff --git a/services/audiomanager/IAudioManager.cpp b/services/audiomanager/IAudioManager.cpp
index da1aae2..8db9a78 100644
--- a/services/audiomanager/IAudioManager.cpp
+++ b/services/audiomanager/IAudioManager.cpp
@@ -35,6 +35,24 @@
{
}
+ virtual sp<media::IAudioManagerNative> getNativeInterface() {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
+ const status_t res = remote()->transact(GET_NATIVE_INTERFACE, data, &reply, 0);
+ if (res == DEAD_OBJECT) return nullptr;
+ LOG_ALWAYS_FATAL_IF(res != OK, "%s failed with result %d", __func__, res);
+ const int ex = reply.readExceptionCode();
+ LOG_ALWAYS_FATAL_IF(ex != binder::Status::EX_NONE, "%s failed with exception %d",
+ __func__,
+ ex);
+ sp<IBinder> binder;
+ const status_t err = reply.readNullableStrongBinder(&binder);
+ LOG_ALWAYS_FATAL_IF(binder == nullptr, "%s failed unexpected nullptr %d", __func__, err);
+ const auto iface = checked_interface_cast<media::IAudioManagerNative>(binder);
+ LOG_ALWAYS_FATAL_IF(iface == nullptr, "%s failed unexpected interface", __func__);
+ return iface;
+ }
+
virtual audio_unique_id_t trackPlayer(player_type_t playerType, audio_usage_t usage,
audio_content_type_t content, const sp<IBinder>& player, audio_session_t sessionId) {
Parcel data, reply;
@@ -87,12 +105,15 @@
}
virtual status_t playerEvent(audio_unique_id_t piid, player_state_t event,
- audio_port_handle_t eventId) {
+ const std::vector<audio_port_handle_t>& eventIds) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeInt32((int32_t) piid);
data.writeInt32((int32_t) event);
- data.writeInt32((int32_t) eventId);
+ data.writeInt32((int32_t) eventIds.size());
+ for (auto eventId: eventIds) {
+ data.writeInt32((int32_t) eventId);
+ }
return remote()->transact(PLAYER_EVENT, data, &reply, IBinder::FLAG_ONEWAY);
}
diff --git a/services/automotive/display/Android.bp b/services/automotive/display/Android.bp
index 72bd292..b63e919 100644
--- a/services/automotive/display/Android.bp
+++ b/services/automotive/display/Android.bp
@@ -23,6 +23,11 @@
default_applicable_licenses: ["frameworks_native_license"],
}
+vintf_fragment {
+ name: "manifest_android.frameworks.automotive.display@1.0.xml",
+ src: "manifest_android.frameworks.automotive.display@1.0.xml",
+}
+
cc_binary {
name: "android.frameworks.automotive.display@1.0-service",
defaults: ["hidl_defaults"],
@@ -50,7 +55,7 @@
"-DLOG_TAG=\"AutomotiveDisplayService\""
],
- vintf_fragments: [
+ vintf_fragment_modules: [
"manifest_android.frameworks.automotive.display@1.0.xml",
],
}
diff --git a/services/automotive/display/AutomotiveDisplayProxyService.cpp b/services/automotive/display/AutomotiveDisplayProxyService.cpp
index d205231..afa6233 100644
--- a/services/automotive/display/AutomotiveDisplayProxyService.cpp
+++ b/services/automotive/display/AutomotiveDisplayProxyService.cpp
@@ -34,10 +34,8 @@
sp<IBinder> displayToken = nullptr;
sp<SurfaceControl> surfaceControl = nullptr;
if (it == mDisplays.end()) {
- if (const auto displayId = DisplayId::fromValue<PhysicalDisplayId>(id)) {
- displayToken = SurfaceComposerClient::getPhysicalDisplayToken(*displayId);
- }
-
+ displayToken =
+ SurfaceComposerClient::getPhysicalDisplayToken(PhysicalDisplayId::fromValue(id));
if (displayToken == nullptr) {
ALOGE("Given display id, 0x%lX, is invalid.", (unsigned long)id);
return nullptr;
@@ -160,11 +158,8 @@
HwDisplayConfig activeConfig;
HwDisplayState activeState;
- sp<IBinder> displayToken;
- if (const auto displayId = DisplayId::fromValue<PhysicalDisplayId>(id)) {
- displayToken = SurfaceComposerClient::getPhysicalDisplayToken(*displayId);
- }
-
+ sp<IBinder> displayToken =
+ SurfaceComposerClient::getPhysicalDisplayToken(PhysicalDisplayId::fromValue(id));
if (displayToken == nullptr) {
ALOGE("Given display id, 0x%lX, is invalid.", (unsigned long)id);
} else {
@@ -197,4 +192,3 @@
} // namespace automotive
} // namespace frameworks
} // namespace android
-
diff --git a/services/automotive/display/android.frameworks.automotive.display@1.0-service.rc b/services/automotive/display/android.frameworks.automotive.display@1.0-service.rc
index 5c7f344..e96b17a 100644
--- a/services/automotive/display/android.frameworks.automotive.display@1.0-service.rc
+++ b/services/automotive/display/android.frameworks.automotive.display@1.0-service.rc
@@ -2,3 +2,4 @@
class hal
user graphics
group automotive_evs
+ disabled
diff --git a/services/displayservice/DisplayEventReceiver.cpp b/services/displayservice/DisplayEventReceiver.cpp
index 2bb74c2..9927fb6 100644
--- a/services/displayservice/DisplayEventReceiver.cpp
+++ b/services/displayservice/DisplayEventReceiver.cpp
@@ -22,6 +22,7 @@
#include <android/frameworks/displayservice/1.0/BpHwEventCallback.h>
#include <thread>
+#include <ftl/enum.h>
namespace android {
namespace frameworks {
@@ -97,11 +98,11 @@
for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
const FwkReceiver::Event &event = buf[i];
- uint32_t type = event.header.type;
+ android::DisplayEventType type = event.header.type;
uint64_t timestamp = event.header.timestamp;
switch(buf[i].header.type) {
- case FwkReceiver::DISPLAY_EVENT_VSYNC: {
+ case DisplayEventType::DISPLAY_EVENT_VSYNC: {
auto ret = mCallback->onVsync(timestamp, event.vsync.count);
if (!ret.isOk()) {
LOG(ERROR) << "AttachedEvent handleEvent fails on onVsync callback"
@@ -109,7 +110,7 @@
return 0; // remove the callback
}
} break;
- case FwkReceiver::DISPLAY_EVENT_HOTPLUG: {
+ case DisplayEventType::DISPLAY_EVENT_HOTPLUG: {
auto ret = mCallback->onHotplug(timestamp, event.hotplug.connected);
if (!ret.isOk()) {
LOG(ERROR) << "AttachedEvent handleEvent fails on onHotplug callback"
@@ -118,7 +119,8 @@
}
} break;
default: {
- LOG(ERROR) << "AttachedEvent handleEvent unknown type: " << type;
+ LOG(ERROR) << "AttachedEvent handleEvent unknown type: "
+ << ftl::to_underlying(type);
}
}
}
diff --git a/services/displayservice/OWNERS b/services/displayservice/OWNERS
index 7a3e4c2..40164aa 100644
--- a/services/displayservice/OWNERS
+++ b/services/displayservice/OWNERS
@@ -1,2 +1 @@
smoreland@google.com
-lpy@google.com
diff --git a/services/gpuservice/Android.bp b/services/gpuservice/Android.bp
index ca9fe5e..74e354f 100644
--- a/services/gpuservice/Android.bp
+++ b/services/gpuservice/Android.bp
@@ -7,6 +7,13 @@
default_applicable_licenses: ["frameworks_native_license"],
}
+aconfig_declarations {
+ name: "gpuservice_flags",
+ package: "com.android.frameworks.gpuservice.flags",
+ container: "system",
+ srcs: ["gpuservice_flags.aconfig"],
+}
+
cc_defaults {
name: "gpuservice_defaults",
cflags: [
@@ -19,10 +26,22 @@
],
}
+cc_aconfig_library {
+ name: "gpuservice_multiuser_flags_c_lib",
+ aconfig_declarations: "gpuservice_flags",
+}
+
+cc_aconfig_library {
+ name: "gpuservice_flags_c_lib",
+ aconfig_declarations: "graphicsenv_flags",
+}
+
cc_defaults {
name: "libgpuservice_defaults",
defaults: [
+ "aconfig_lib_cc_static_link.defaults",
"gpuservice_defaults",
+ "libfeatureoverride_deps",
"libgfxstats_deps",
"libgpumem_deps",
"libgpumemtracer_deps",
@@ -40,8 +59,11 @@
"libgraphicsenv",
"liblog",
"libutils",
+ "server_configurable_flags",
],
static_libs: [
+ "gpuservice_flags_c_lib",
+ "libfeatureoverride",
"libgfxstats",
"libgpumem",
"libgpumemtracer",
@@ -83,6 +105,9 @@
srcs: [
":libgpuservice_sources",
],
+ shared_libs: [
+ "gpuservice_multiuser_flags_c_lib",
+ ],
}
cc_defaults {
@@ -117,4 +142,7 @@
static_libs: [
"libgpuservice",
],
+ shared_libs: [
+ "gpuservice_multiuser_flags_c_lib",
+ ],
}
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index fadb1fd..25ee21f 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -24,7 +24,11 @@
#include <binder/IResultReceiver.h>
#include <binder/Parcel.h>
#include <binder/PermissionCache.h>
+#include <com_android_frameworks_gpuservice_flags.h>
+#include <com_android_graphics_graphicsenv_flags.h>
#include <cutils/properties.h>
+#include <cutils/multiuser.h>
+#include <feature_override/FeatureOverrideParser.h>
#include <gpumem/GpuMem.h>
#include <gpuwork/GpuWork.h>
#include <gpustats/GpuStats.h>
@@ -38,6 +42,9 @@
#include <thread>
#include <memory>
+namespace gpuservice_flags = com::android::frameworks::gpuservice::flags;
+namespace graphicsenv_flags = com::android::graphics::graphicsenv::flags;
+
namespace android {
using base::StringAppendF;
@@ -113,11 +120,22 @@
// only system_server with the ACCESS_GPU_SERVICE permission is allowed to set
// persist.graphics.egl
- if (uid != AID_SYSTEM ||
- !PermissionCache::checkPermission(sAccessGpuServicePermission, pid, uid)) {
- ALOGE("Permission Denial: can't set persist.graphics.egl from setAngleAsSystemDriver() "
+ if (gpuservice_flags::multiuser_permission_check()) {
+ // retrieve the appid of Settings app on multiuser builds
+ const int multiuserappid = multiuser_get_app_id(uid);
+ if (multiuserappid != AID_SYSTEM ||
+ !PermissionCache::checkPermission(sAccessGpuServicePermission, pid, uid)) {
+ ALOGE("Permission Denial: can't set persist.graphics.egl from setAngleAsSystemDriver() "
+ "pid=%d, uid=%d\n, multiuserappid=%d", pid, uid, multiuserappid);
+ return;
+ }
+ } else {
+ if (uid != AID_SYSTEM ||
+ !PermissionCache::checkPermission(sAccessGpuServicePermission, pid, uid)) {
+ ALOGE("Permission Denial: can't set persist.graphics.egl from setAngleAsSystemDriver() "
"pid=%d, uid=%d\n", pid, uid);
- return;
+ return;
+ }
}
std::lock_guard<std::mutex> lock(mLock);
@@ -128,6 +146,14 @@
}
}
+FeatureOverrides GpuService::getFeatureOverrides() {
+ if (!graphicsenv_flags::feature_overrides()) {
+ FeatureOverrides featureOverrides;
+ return featureOverrides;
+ }
+
+ return mFeatureOverrideParser.getFeatureOverrides();
+}
void GpuService::setUpdatableDriverPath(const std::string& driverPath) {
IPCThreadState* ipc = IPCThreadState::self();
@@ -156,7 +182,11 @@
for (size_t i = 0, n = args.size(); i < n; i++)
ALOGV(" arg[%zu]: '%s'", i, String8(args[i]).c_str());
- if (args.size() >= 1) {
+ if (!args.empty()) {
+ if (graphicsenv_flags::feature_overrides()) {
+ if (args[0] == String16("featureOverrides"))
+ return cmdFeatureOverrides(out, err);
+ }
if (args[0] == String16("vkjson")) return cmdVkjson(out, err);
if (args[0] == String16("vkprofiles")) return cmdVkprofiles(out, err);
if (args[0] == String16("help")) return cmdHelp(out);
@@ -220,6 +250,11 @@
return NO_ERROR;
}
+status_t GpuService::cmdFeatureOverrides(int out, int /*err*/) {
+ dprintf(out, "%s\n", mFeatureOverrideParser.getFeatureOverrides().toString().c_str());
+ return NO_ERROR;
+}
+
namespace {
status_t cmdHelp(int out) {
@@ -232,6 +267,10 @@
"GPU Service commands:\n"
" vkjson dump Vulkan properties as JSON\n"
" vkprofiles print support for select Vulkan profiles\n");
+ if (graphicsenv_flags::feature_overrides()) {
+ fprintf(outs,
+ " featureOverrides update and output gpuservice's feature overrides\n");
+ }
fclose(outs);
return NO_ERROR;
}
diff --git a/services/gpuservice/OWNERS b/services/gpuservice/OWNERS
index 07c681f..a3afca5 100644
--- a/services/gpuservice/OWNERS
+++ b/services/gpuservice/OWNERS
@@ -1,7 +1,4 @@
chrisforbes@google.com
-lpy@google.com
-alecmouri@google.com
-lfy@google.com
-paulthomson@google.com
-pbaiget@google.com
-kocdemir@google.com
+tomnom@google.com
+
+alecmouri@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/services/gpuservice/feature_override/Android.bp b/services/gpuservice/feature_override/Android.bp
new file mode 100644
index 0000000..3b5407b
--- /dev/null
+++ b/services/gpuservice/feature_override/Android.bp
@@ -0,0 +1,96 @@
+// Copyright 2024 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.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
+cc_defaults {
+ name: "libfeatureoverride_deps",
+ include_dirs: [
+ "external/protobuf",
+ "external/protobuf/src",
+ ],
+ header_libs: [
+ "libbase_headers",
+ ],
+ shared_libs: [
+ "libbase",
+ "libgraphicsenv",
+ "liblog",
+ "libprotobuf-cpp-lite",
+ ],
+}
+
+filegroup {
+ name: "feature_config_proto_definitions",
+ srcs: [
+ "proto/feature_config.proto",
+ ],
+}
+
+genrule {
+ name: "feature_config_proto_lite_gen_headers",
+ srcs: [
+ ":feature_config_proto_definitions",
+ ],
+ tools: [
+ "aprotoc",
+ ],
+ cmd: "$(location aprotoc) " +
+ "--proto_path=frameworks/native/services/gpuservice/feature_override " +
+ "--cpp_out=lite=true:$(genDir)/frameworks/native/services/gpuservice/feature_override " +
+ "$(locations :feature_config_proto_definitions)",
+ out: [
+ "frameworks/native/services/gpuservice/feature_override/proto/feature_config.pb.h",
+ ],
+ export_include_dirs: [
+ "frameworks/native/services/gpuservice/feature_override/proto/",
+ ],
+}
+
+cc_library_static {
+ name: "libfeatureoverride",
+ defaults: [
+ "libfeatureoverride_deps",
+ ],
+ srcs: [
+ ":feature_config_proto_definitions",
+ "FeatureOverrideParser.cpp",
+ ],
+ local_include_dirs: [
+ "include",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wimplicit-fallthrough",
+ ],
+ cppflags: [
+ "-Wno-sign-compare",
+ ],
+ export_include_dirs: ["include"],
+ proto: {
+ type: "lite",
+ static: true,
+ },
+ generated_headers: [
+ "feature_config_proto_lite_gen_headers",
+ ],
+}
diff --git a/services/gpuservice/feature_override/FeatureOverrideParser.cpp b/services/gpuservice/feature_override/FeatureOverrideParser.cpp
new file mode 100644
index 0000000..a16bfa8
--- /dev/null
+++ b/services/gpuservice/feature_override/FeatureOverrideParser.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2025 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 <feature_override/FeatureOverrideParser.h>
+
+#include <chrono>
+#include <fstream>
+#include <sstream>
+#include <string>
+#include <sys/stat.h>
+#include <vector>
+
+#include <graphicsenv/FeatureOverrides.h>
+#include <log/log.h>
+
+#include "feature_config.pb.h"
+
+namespace {
+
+void resetFeatureOverrides(android::FeatureOverrides &featureOverrides) {
+ featureOverrides.mGlobalFeatures.clear();
+ featureOverrides.mPackageFeatures.clear();
+}
+
+void initFeatureConfig(android::FeatureConfig &featureConfig,
+ const feature_override::FeatureConfig &featureConfigProto) {
+ featureConfig.mFeatureName = featureConfigProto.feature_name();
+ featureConfig.mEnabled = featureConfigProto.enabled();
+}
+
+feature_override::FeatureOverrideProtos readFeatureConfigProtos(std::string configFilePath) {
+ feature_override::FeatureOverrideProtos overridesProtos;
+
+ std::ifstream protobufBinaryFile(configFilePath.c_str());
+ if (protobufBinaryFile.fail()) {
+ ALOGE("Failed to open feature config file: `%s`.", configFilePath.c_str());
+ return overridesProtos;
+ }
+
+ std::stringstream buffer;
+ buffer << protobufBinaryFile.rdbuf();
+ std::string serializedConfig = buffer.str();
+ std::vector<uint8_t> serialized(
+ reinterpret_cast<const uint8_t *>(serializedConfig.data()),
+ reinterpret_cast<const uint8_t *>(serializedConfig.data()) +
+ serializedConfig.size());
+
+ if (!overridesProtos.ParseFromArray(serialized.data(),
+ static_cast<int>(serialized.size()))) {
+ ALOGE("Failed to parse GpuConfig protobuf data.");
+ }
+
+ return overridesProtos;
+}
+
+} // namespace
+
+namespace android {
+
+std::string FeatureOverrideParser::getFeatureOverrideFilePath() const {
+ const std::string kConfigFilePath = "/system/etc/angle/feature_config_vk.binarypb";
+
+ return kConfigFilePath;
+}
+
+bool FeatureOverrideParser::shouldReloadFeatureOverrides() const {
+ std::string configFilePath = getFeatureOverrideFilePath();
+ struct stat fileStat{};
+ if (stat(getFeatureOverrideFilePath().c_str(), &fileStat) != 0) {
+ ALOGE("Error getting file information for '%s': %s", getFeatureOverrideFilePath().c_str(),
+ strerror(errno));
+ // stat'ing the file failed, so return false since reading it will also likely fail.
+ return false;
+ }
+
+ return fileStat.st_mtime > mLastProtobufReadTime;
+}
+
+void FeatureOverrideParser::forceFileRead() {
+ mLastProtobufReadTime = 0;
+}
+
+void FeatureOverrideParser::parseFeatureOverrides() {
+ const feature_override::FeatureOverrideProtos overridesProtos = readFeatureConfigProtos(
+ getFeatureOverrideFilePath());
+
+ // Clear out the stale values before adding the newly parsed data.
+ resetFeatureOverrides(mFeatureOverrides);
+
+ // Global feature overrides.
+ for (const auto &featureConfigProto: overridesProtos.global_features()) {
+ FeatureConfig featureConfig;
+ initFeatureConfig(featureConfig, featureConfigProto);
+
+ mFeatureOverrides.mGlobalFeatures.emplace_back(featureConfig);
+ }
+
+ // App-specific feature overrides.
+ for (auto const &pkgConfigProto: overridesProtos.package_features()) {
+ const std::string &packageName = pkgConfigProto.package_name();
+
+ if (mFeatureOverrides.mPackageFeatures.count(packageName)) {
+ ALOGE("Package already has feature overrides! Skipping.");
+ continue;
+ }
+
+ std::vector<FeatureConfig> featureConfigs;
+ for (const auto &featureConfigProto: pkgConfigProto.feature_configs()) {
+ FeatureConfig featureConfig;
+ initFeatureConfig(featureConfig, featureConfigProto);
+
+ featureConfigs.emplace_back(featureConfig);
+ }
+
+ mFeatureOverrides.mPackageFeatures[packageName] = featureConfigs;
+ }
+
+ mLastProtobufReadTime = std::chrono::system_clock::to_time_t(
+ std::chrono::system_clock::now());
+}
+
+FeatureOverrides FeatureOverrideParser::getFeatureOverrides() {
+ if (shouldReloadFeatureOverrides()) {
+ parseFeatureOverrides();
+ }
+
+ return mFeatureOverrides;
+}
+
+} // namespace android
diff --git a/services/gpuservice/feature_override/include/feature_override/FeatureOverrideParser.h b/services/gpuservice/feature_override/include/feature_override/FeatureOverrideParser.h
new file mode 100644
index 0000000..b1f1867
--- /dev/null
+++ b/services/gpuservice/feature_override/include/feature_override/FeatureOverrideParser.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2024 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 FEATURE_OVERRIDE_PARSER_H_
+#define FEATURE_OVERRIDE_PARSER_H_
+
+#include <ctime>
+#include <string>
+#include <vector>
+
+#include <graphicsenv/FeatureOverrides.h>
+
+namespace android {
+
+class FeatureOverrideParser {
+public:
+ FeatureOverrideParser() = default;
+ FeatureOverrideParser(const FeatureOverrideParser &) = default;
+ virtual ~FeatureOverrideParser() = default;
+
+ FeatureOverrides getFeatureOverrides();
+ void forceFileRead();
+
+private:
+ bool shouldReloadFeatureOverrides() const;
+ void parseFeatureOverrides();
+ // Allow FeatureOverrideParserMock to override with the unit test file's path.
+ virtual std::string getFeatureOverrideFilePath() const;
+
+ std::time_t mLastProtobufReadTime = 0;
+ FeatureOverrides mFeatureOverrides;
+};
+
+} // namespace android
+
+#endif // FEATURE_OVERRIDE_PARSER_H_
diff --git a/services/gpuservice/feature_override/proto/feature_config.proto b/services/gpuservice/feature_override/proto/feature_config.proto
new file mode 100644
index 0000000..4d4bf28
--- /dev/null
+++ b/services/gpuservice/feature_override/proto/feature_config.proto
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2024 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 = "proto3";
+
+package feature_override;
+
+option optimize_for = LITE_RUNTIME;
+
+/**
+ * Feature Configuration
+ * feature_name: Feature name (see external/angle/include/platform/autogen/FeaturesVk_autogen.h).
+ * enabled: Either enable or disable the feature.
+ */
+message FeatureConfig
+{
+ string feature_name = 1;
+ bool enabled = 2;
+}
+
+/**
+ * Package Configuration
+ * feature_configs: List of features configs for the package.
+ */
+message PackageConfig
+{
+ string package_name = 1;
+ repeated FeatureConfig feature_configs = 2;
+}
+
+/**
+ * Feature Overrides
+ * global_features: Features to apply globally, for every package.
+ * package_features: Features to apply for individual packages.
+ */
+message FeatureOverrideProtos
+{
+ repeated FeatureConfig global_features = 1;
+ repeated PackageConfig package_features = 2;
+}
diff --git a/services/gpuservice/gpuservice_flags.aconfig b/services/gpuservice/gpuservice_flags.aconfig
new file mode 100644
index 0000000..be6a7bb
--- /dev/null
+++ b/services/gpuservice/gpuservice_flags.aconfig
@@ -0,0 +1,12 @@
+package: "com.android.frameworks.gpuservice.flags"
+container: "system"
+
+flag {
+ name: "multiuser_permission_check"
+ namespace: "gpu"
+ description: "Whether to consider headless system user mode/multiuser when checking toggleAngleAsSystemDriver permission."
+ bug: "389867658"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/services/gpuservice/gpuwork/bpfprogs/gpuWork.c b/services/gpuservice/gpuwork/bpfprogs/gpuWork.c
index f470189..94abc69 100644
--- a/services/gpuservice/gpuwork/bpfprogs/gpuWork.c
+++ b/services/gpuservice/gpuwork/bpfprogs/gpuWork.c
@@ -20,11 +20,7 @@
#include <stddef.h>
#include <stdint.h>
-#ifdef MOCK_BPF
-#include <test/mock_bpf_helpers.h>
-#else
#include <bpf_helpers.h>
-#endif
#define S_IN_NS (1000000000)
#define SMALL_TIME_GAP_LIMIT_NS (S_IN_NS)
diff --git a/services/gpuservice/include/gpuservice/GpuService.h b/services/gpuservice/include/gpuservice/GpuService.h
index 3072885..22be9a7 100644
--- a/services/gpuservice/include/gpuservice/GpuService.h
+++ b/services/gpuservice/include/gpuservice/GpuService.h
@@ -19,6 +19,8 @@
#include <binder/IInterface.h>
#include <cutils/compiler.h>
+#include <feature_override/FeatureOverrideParser.h>
+#include <graphicsenv/FeatureOverrides.h>
#include <graphicsenv/GpuStatsInfo.h>
#include <graphicsenv/IGpuService.h>
#include <serviceutils/PriorityDumper.h>
@@ -63,6 +65,7 @@
const uint64_t* values, const uint32_t valueCount) override;
void setUpdatableDriverPath(const std::string& driverPath) override;
std::string getUpdatableDriverPath() override;
+ FeatureOverrides getFeatureOverrides() override;
void toggleAngleAsSystemDriver(bool enabled) override;
void addVulkanEngineName(const std::string& appPackageName, const uint64_t driverVersionCode,
const char *engineName) override;
@@ -85,6 +88,8 @@
status_t doDump(int fd, const Vector<String16>& args, bool asProto);
+ status_t cmdFeatureOverrides(int out, int /*err*/);
+
/*
* Attributes
*/
@@ -96,6 +101,7 @@
std::string mDeveloperDriverPath;
std::unique_ptr<std::thread> mGpuMemAsyncInitThread;
std::unique_ptr<std::thread> mGpuWorkAsyncInitThread;
+ FeatureOverrideParser mFeatureOverrideParser;
};
} // namespace android
diff --git a/services/gpuservice/tests/fuzzers/Android.bp b/services/gpuservice/tests/fuzzers/Android.bp
index d4d48c4..7be3253 100644
--- a/services/gpuservice/tests/fuzzers/Android.bp
+++ b/services/gpuservice/tests/fuzzers/Android.bp
@@ -13,6 +13,9 @@
"libgpuservice",
"liblog",
],
+ shared_libs: [
+ "gpuservice_multiuser_flags_c_lib",
+ ],
fuzz_config: {
cc: [
"paulthomson@google.com",
diff --git a/services/gpuservice/tests/unittests/Android.bp b/services/gpuservice/tests/unittests/Android.bp
index 8056a2c..0dac24d 100644
--- a/services/gpuservice/tests/unittests/Android.bp
+++ b/services/gpuservice/tests/unittests/Android.bp
@@ -21,20 +21,75 @@
default_applicable_licenses: ["frameworks_native_license"],
}
+cc_aconfig_library {
+ name: "gpuservice_unittest_flags_c_lib",
+ aconfig_declarations: "graphicsenv_flags",
+}
+
+genrule_defaults {
+ name: "gpuservice_unittest_feature_config_pb_defaults",
+ tools: ["aprotoc"],
+ tool_files: [
+ ":feature_config_proto_definitions",
+ ],
+ cmd: "$(location aprotoc) " +
+ "--encode=feature_override.FeatureOverrideProtos " +
+ "$(locations :feature_config_proto_definitions) " +
+ "< $(in) " +
+ "> $(out) ",
+}
+
+// Main protobuf used by the unit tests.
+filegroup {
+ name: "gpuservice_unittest_feature_config_vk_prototext",
+ srcs: [
+ "data/feature_config_test.txtpb",
+ ],
+}
+
+genrule {
+ name: "gpuservice_unittest_feature_config_vk_binarypb",
+ defaults: ["gpuservice_unittest_feature_config_pb_defaults"],
+ srcs: [
+ ":gpuservice_unittest_feature_config_vk_prototext",
+ ],
+ out: ["gpuservice_unittest_feature_config_vk.binarypb"],
+}
+
+// "Updated" protobuf, used to validate forceFileRead().
+filegroup {
+ name: "gpuservice_unittest_feature_config_vk_force_read_prototext",
+ srcs: [
+ "data/feature_config_test_force_read.txtpb",
+ ],
+}
+
+genrule {
+ name: "gpuservice_unittest_feature_config_vk_force_read_binarypb",
+ defaults: ["gpuservice_unittest_feature_config_pb_defaults"],
+ srcs: [
+ ":gpuservice_unittest_feature_config_vk_force_read_prototext",
+ ],
+ out: ["gpuservice_unittest_feature_config_vk_force_read.binarypb"],
+}
+
cc_test {
name: "gpuservice_unittest",
test_suites: ["device-tests"],
defaults: [
+ "aconfig_lib_cc_static_link.defaults",
"libgpuservice_defaults",
],
srcs: [
+ "FeatureOverrideParserTest.cpp",
"GpuMemTest.cpp",
"GpuMemTracerTest.cpp",
- "GpuStatsTest.cpp",
"GpuServiceTest.cpp",
+ "GpuStatsTest.cpp",
],
header_libs: ["bpf_headers"],
shared_libs: [
+ "gpuservice_multiuser_flags_c_lib",
"libbase",
"libbinder",
"libbpf_bcc",
@@ -48,10 +103,15 @@
"libutils",
],
static_libs: [
+ "gpuservice_unittest_flags_c_lib",
"libgmock",
"libgpuservice",
"libperfetto_client_experimental",
"perfetto_trace_protos",
],
+ data: [
+ ":gpuservice_unittest_feature_config_vk_binarypb",
+ ":gpuservice_unittest_feature_config_vk_force_read_binarypb",
+ ],
require_root: true,
}
diff --git a/services/gpuservice/tests/unittests/FeatureOverrideParserTest.cpp b/services/gpuservice/tests/unittests/FeatureOverrideParserTest.cpp
new file mode 100644
index 0000000..65a1b58
--- /dev/null
+++ b/services/gpuservice/tests/unittests/FeatureOverrideParserTest.cpp
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2025 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 "gpuservice_unittest"
+
+#include <android-base/file.h>
+#include <log/log.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <com_android_graphics_graphicsenv_flags.h>
+#include <feature_override/FeatureOverrideParser.h>
+
+using ::testing::AtLeast;
+using ::testing::Return;
+
+namespace android {
+namespace {
+
+std::string getTestBinarypbPath(const std::string &filename) {
+ std::string path = android::base::GetExecutableDirectory();
+ path.append("/");
+ path.append(filename);
+
+ return path;
+}
+
+class FeatureOverrideParserMock : public FeatureOverrideParser {
+public:
+ MOCK_METHOD(std::string, getFeatureOverrideFilePath, (), (const, override));
+};
+
+class FeatureOverrideParserTest : public testing::Test {
+public:
+ FeatureOverrideParserTest() {
+ const ::testing::TestInfo *const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
+ }
+
+ ~FeatureOverrideParserTest() {
+ const ::testing::TestInfo *const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(),
+ test_info->name());
+ }
+
+ void SetUp() override {
+ const std::string filename = "gpuservice_unittest_feature_config_vk.binarypb";
+
+ EXPECT_CALL(mFeatureOverrideParser, getFeatureOverrideFilePath())
+ .WillRepeatedly(Return(getTestBinarypbPath(filename)));
+ }
+
+ FeatureOverrideParserMock mFeatureOverrideParser;
+};
+
+testing::AssertionResult validateFeatureConfigTestTxtpbSizes(FeatureOverrides overrides) {
+ size_t expectedGlobalFeaturesSize = 1;
+ if (overrides.mGlobalFeatures.size() != expectedGlobalFeaturesSize) {
+ return testing::AssertionFailure()
+ << "overrides.mGlobalFeatures.size(): " << overrides.mGlobalFeatures.size()
+ << ", expected: " << expectedGlobalFeaturesSize;
+ }
+
+ size_t expectedPackageFeaturesSize = 1;
+ if (overrides.mPackageFeatures.size() != expectedPackageFeaturesSize) {
+ return testing::AssertionFailure()
+ << "overrides.mPackageFeatures.size(): " << overrides.mPackageFeatures.size()
+ << ", expected: " << expectedPackageFeaturesSize;
+ }
+
+ return testing::AssertionSuccess();
+}
+
+testing::AssertionResult validateFeatureConfigTestForceReadTxtpbSizes(FeatureOverrides overrides) {
+ size_t expectedGlobalFeaturesSize = 1;
+ if (overrides.mGlobalFeatures.size() != expectedGlobalFeaturesSize) {
+ return testing::AssertionFailure()
+ << "overrides.mGlobalFeatures.size(): " << overrides.mGlobalFeatures.size()
+ << ", expected: " << expectedGlobalFeaturesSize;
+ }
+
+ size_t expectedPackageFeaturesSize = 0;
+ if (overrides.mPackageFeatures.size() != expectedPackageFeaturesSize) {
+ return testing::AssertionFailure()
+ << "overrides.mPackageFeatures.size(): " << overrides.mPackageFeatures.size()
+ << ", expected: " << expectedPackageFeaturesSize;
+ }
+
+ return testing::AssertionSuccess();
+}
+
+testing::AssertionResult validateGlobalOverrides1(FeatureOverrides overrides) {
+ const int kTestFeatureIndex = 0;
+ const std::string expectedFeatureName = "globalOverrides1";
+ const FeatureConfig &cfg = overrides.mGlobalFeatures[kTestFeatureIndex];
+
+ if (cfg.mFeatureName != expectedFeatureName) {
+ return testing::AssertionFailure()
+ << "cfg.mFeatureName: " << cfg.mFeatureName
+ << ", expected: " << expectedFeatureName;
+ }
+
+ bool expectedEnabled = false;
+ if (cfg.mEnabled != expectedEnabled) {
+ return testing::AssertionFailure()
+ << "cfg.mEnabled: " << cfg.mEnabled
+ << ", expected: " << expectedEnabled;
+ }
+
+ return testing::AssertionSuccess();
+}
+
+TEST_F(FeatureOverrideParserTest, globalOverrides1) {
+ FeatureOverrides overrides = mFeatureOverrideParser.getFeatureOverrides();
+
+ EXPECT_TRUE(validateFeatureConfigTestTxtpbSizes(overrides));
+ EXPECT_TRUE(validateGlobalOverrides1(overrides));
+}
+
+testing::AssertionResult validatePackageOverrides1(FeatureOverrides overrides) {
+ const std::string expectedTestPackageName = "com.gpuservice_unittest.packageOverrides1";
+
+ if (!overrides.mPackageFeatures.count(expectedTestPackageName)) {
+ return testing::AssertionFailure()
+ << "overrides.mPackageFeatures missing expected package: "
+ << expectedTestPackageName;
+ }
+
+ const std::vector<FeatureConfig>& features =
+ overrides.mPackageFeatures[expectedTestPackageName];
+
+ size_t expectedFeaturesSize = 1;
+ if (features.size() != expectedFeaturesSize) {
+ return testing::AssertionFailure()
+ << "features.size(): " << features.size()
+ << ", expectedFeaturesSize: " << expectedFeaturesSize;
+ }
+
+ const std::string expectedFeatureName = "packageOverrides1";
+ const FeatureConfig &cfg = features[0];
+
+ bool expectedEnabled = true;
+ if (cfg.mEnabled != expectedEnabled) {
+ return testing::AssertionFailure()
+ << "cfg.mEnabled: " << cfg.mEnabled
+ << ", expected: " << expectedEnabled;
+ }
+
+ return testing::AssertionSuccess();
+}
+
+TEST_F(FeatureOverrideParserTest, packageOverrides1) {
+ FeatureOverrides overrides = mFeatureOverrideParser.getFeatureOverrides();
+
+ EXPECT_TRUE(validateFeatureConfigTestTxtpbSizes(overrides));
+ EXPECT_TRUE(validatePackageOverrides1(overrides));
+}
+
+testing::AssertionResult validateForceFileRead(FeatureOverrides overrides) {
+ const int kTestFeatureIndex = 0;
+ const std::string expectedFeatureName = "forceFileRead";
+
+ const FeatureConfig &cfg = overrides.mGlobalFeatures[kTestFeatureIndex];
+ if (cfg.mFeatureName != expectedFeatureName) {
+ return testing::AssertionFailure()
+ << "cfg.mFeatureName: " << cfg.mFeatureName
+ << ", expected: " << expectedFeatureName;
+ }
+
+ bool expectedEnabled = false;
+ if (cfg.mEnabled != expectedEnabled) {
+ return testing::AssertionFailure()
+ << "cfg.mEnabled: " << cfg.mEnabled
+ << ", expected: " << expectedEnabled;
+ }
+
+ return testing::AssertionSuccess();
+}
+
+TEST_F(FeatureOverrideParserTest, forceFileRead) {
+ FeatureOverrides overrides = mFeatureOverrideParser.getFeatureOverrides();
+
+ // Validate the "original" contents are present.
+ EXPECT_TRUE(validateFeatureConfigTestTxtpbSizes(overrides));
+ EXPECT_TRUE(validateGlobalOverrides1(overrides));
+
+ // "Update" the config file.
+ const std::string filename = "gpuservice_unittest_feature_config_vk_force_read.binarypb";
+ EXPECT_CALL(mFeatureOverrideParser, getFeatureOverrideFilePath())
+ .WillRepeatedly(Return(getTestBinarypbPath(filename)));
+
+ mFeatureOverrideParser.forceFileRead();
+
+ overrides = mFeatureOverrideParser.getFeatureOverrides();
+
+ // Validate the new file contents were read and parsed.
+ EXPECT_TRUE(validateFeatureConfigTestForceReadTxtpbSizes(overrides));
+ EXPECT_TRUE(validateForceFileRead(overrides));
+}
+
+} // namespace
+} // namespace android
diff --git a/services/gpuservice/tests/unittests/data/feature_config_test.txtpb b/services/gpuservice/tests/unittests/data/feature_config_test.txtpb
new file mode 100644
index 0000000..726779e
--- /dev/null
+++ b/services/gpuservice/tests/unittests/data/feature_config_test.txtpb
@@ -0,0 +1,40 @@
+# Copyright (C) 2024 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.
+#
+# Feature Configuration Test Data
+#
+# proto-file: services/gpuservice/feature_override/proto/feature_config.proto
+# proto-message: FeatureOverrideProtos
+
+# The 'feature_name' entries correspond to the FeatureOverrideParserTest() unit test name.
+global_features [
+ {
+ feature_name: "globalOverrides1"
+ enabled: False
+ }
+]
+
+# The 'package_name' and 'feature_name' entries correspond to the
+# FeatureOverrideParserTest() unit test name.
+package_features [
+ {
+ package_name: "com.gpuservice_unittest.packageOverrides1"
+ feature_configs: [
+ {
+ feature_name: "packageOverrides1"
+ enabled: True
+ }
+ ]
+ }
+]
diff --git a/services/gpuservice/tests/unittests/data/feature_config_test_force_read.txtpb b/services/gpuservice/tests/unittests/data/feature_config_test_force_read.txtpb
new file mode 100644
index 0000000..cf6a67e
--- /dev/null
+++ b/services/gpuservice/tests/unittests/data/feature_config_test_force_read.txtpb
@@ -0,0 +1,26 @@
+# Copyright (C) 2024 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.
+#
+# Feature Configuration Test Data
+#
+# proto-file: services/gpuservice/feature_override/proto/feature_config.proto
+# proto-message: FeatureOverrideProtos
+
+# The 'feature_name' entries correspond to the FeatureOverrideParserTest() unit test name.
+global_features [
+ {
+ feature_name: "forceFileRead"
+ enabled: False
+ }
+]
diff --git a/services/gpuservice/vts/Android.bp b/services/gpuservice/vts/Android.bp
index a24822a..6e0a9f7 100644
--- a/services/gpuservice/vts/Android.bp
+++ b/services/gpuservice/vts/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_android_gpu",
default_applicable_licenses: ["frameworks_native_license"],
}
diff --git a/services/gpuservice/vts/OWNERS b/services/gpuservice/vts/OWNERS
index a63de1c..13a089f 100644
--- a/services/gpuservice/vts/OWNERS
+++ b/services/gpuservice/vts/OWNERS
@@ -1,8 +1,5 @@
# Bug component: 653544
kocdemir@google.com
paulthomson@google.com
-pbaiget@google.com
-lfy@google.com
chrisforbes@google.com
-lpy@google.com
alecmouri@google.com
diff --git a/services/gpuservice/vts/src/com/android/tests/gpuservice/GpuWorkTracepointTest.java b/services/gpuservice/vts/src/com/android/tests/gpuservice/GpuWorkTracepointTest.java
index 5c12323..fc0aef4 100644
--- a/services/gpuservice/vts/src/com/android/tests/gpuservice/GpuWorkTracepointTest.java
+++ b/services/gpuservice/vts/src/com/android/tests/gpuservice/GpuWorkTracepointTest.java
@@ -39,29 +39,9 @@
@RunWith(DeviceJUnit4ClassRunner.class)
public class GpuWorkTracepointTest extends BaseHostJUnit4Test {
- private static final String CPU_FREQUENCY_TRACEPOINT_FORMAT_PATH =
- "/sys/kernel/tracing/events/power/cpu_frequency/format";
private static final String GPU_WORK_PERIOD_TRACEPOINT_FORMAT_PATH =
"/sys/kernel/tracing/events/power/gpu_work_period/format";
- @Test
- public void testReadTracingEvents() throws Exception {
- // Test |testGpuWorkPeriodTracepointFormat| is dependent on whether certain tracepoint
- // paths exist. This means the test will vacuously pass if the tracepoint file system is
- // inaccessible. Thus, as a basic check, we make sure the CPU frequency tracepoint format
- // is accessible. If not, something is probably fundamentally broken about the tracing
- // file system.
- CommandResult commandResult = getDevice().executeShellV2Command(
- String.format("cat %s", CPU_FREQUENCY_TRACEPOINT_FORMAT_PATH));
-
- assertEquals(String.format(
- "Failed to read \"%s\". This probably means that the tracing file system "
- + "is fundamentally broken in some way, possibly due to bad "
- + "permissions.",
- CPU_FREQUENCY_TRACEPOINT_FORMAT_PATH),
- commandResult.getStatus(), CommandStatus.SUCCESS);
- }
-
@VsrTest(requirements={"VSR-3.3-004"})
@RequiresDevice
@Test
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index ca92ab5..107fd20 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -32,15 +32,15 @@
host_supported: true,
cpp_std: "c++20",
cflags: [
+ "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
"-Wall",
- "-Wextra",
"-Werror",
+ "-Wextra",
"-Wno-unused-parameter",
- "-Wthread-safety",
"-Wshadow",
"-Wshadow-field-in-constructor-modified",
"-Wshadow-uncaptured-local",
- "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
+ "-Wthread-safety",
],
sanitize: {
misc_undefined: [
@@ -62,8 +62,8 @@
memtag_heap: true,
undefined: true,
misc_undefined: [
- "bounds",
"all",
+ "bounds",
],
},
},
@@ -114,16 +114,16 @@
"liblog",
"libprotobuf-cpp-lite",
"libstatslog",
- "libutils",
"libstatspull",
"libstatssocket",
+ "libutils",
"packagemanager_aidl-cpp",
"server_configurable_flags",
],
static_libs: [
"libattestation",
- "libperfetto_client_experimental",
"libpalmrejection",
+ "libperfetto_client_experimental",
"libui-types",
],
generated_headers: [
@@ -161,10 +161,10 @@
shared_libs: [
// This should consist only of dependencies from inputflinger. Other dependencies should be
// in cc_defaults so that they are included in the tests.
+ "libPlatformProperties",
"libinputflinger_base",
"libinputreader",
"libinputreporter",
- "libPlatformProperties",
],
static_libs: [
"libinputdispatcher",
@@ -185,8 +185,8 @@
name: "libinputflinger_headers",
host_supported: true,
export_include_dirs: [
- "include",
".",
+ "include",
],
header_libs: [
"libchrome-gestures_headers",
@@ -247,49 +247,40 @@
phony {
name: "checkinput",
required: [
- // native targets
- "libgui_test",
- "libinput",
- "libinputreader_static",
- "libinputflinger",
- "inputflinger_tests",
- "inputflinger_benchmarks",
- "libinput_tests",
- "libpalmrejection_test",
- "libandroid_runtime",
- "libinputservice_test",
"Bug-115739809",
- "StructLayout_test",
-
- // jni
- "libservices.core",
-
- // rust targets
- "libinput_rust_test",
-
- // native fuzzers
- "inputflinger_latencytracker_fuzzer",
- "inputflinger_cursor_input_fuzzer",
- "inputflinger_keyboard_input_fuzzer",
- "inputflinger_multitouch_input_fuzzer",
- "inputflinger_switch_input_fuzzer",
- "inputflinger_touchpad_input_fuzzer",
- "inputflinger_input_reader_fuzzer",
- "inputflinger_blocking_queue_fuzzer",
- "inputflinger_input_classifier_fuzzer",
- "inputflinger_input_dispatcher_fuzzer",
-
- // Java/Kotlin targets
- "CtsWindowManagerDeviceWindow",
- "InputTests",
"CtsHardwareTestCases",
"CtsInputTestCases",
+ "CtsSecurityBulletinHostTestCases",
+ "CtsSecurityTestCases",
"CtsViewTestCases",
"CtsWidgetTestCases",
+ "CtsWindowManagerDeviceWindow",
"FrameworksCoreTests",
"FrameworksServicesTests",
- "CtsSecurityTestCases",
- "CtsSecurityBulletinHostTestCases",
+ "InputTests",
+ "StructLayout_test",
+ "inputflinger_benchmarks",
+ "inputflinger_blocking_queue_fuzzer",
+ "inputflinger_cursor_input_fuzzer",
+ "inputflinger_input_classifier_fuzzer",
+ "inputflinger_input_dispatcher_fuzzer",
+ "inputflinger_input_reader_fuzzer",
+ "inputflinger_keyboard_input_fuzzer",
+ "inputflinger_latencytracker_fuzzer",
+ "inputflinger_multitouch_input_fuzzer",
+ "inputflinger_switch_input_fuzzer",
+ "inputflinger_tests",
+ "inputflinger_touchpad_input_fuzzer",
+ "libandroid_runtime",
+ "libgui_test",
+ "libinput",
+ "libinput_rust_test",
+ "libinput_tests",
+ "libinputflinger",
+ "libinputreader_static",
+ "libinputservice_test",
+ "libpalmrejection_test",
+ "libservices.core",
"monkey_test",
],
}
diff --git a/services/inputflinger/InputDeviceMetricsSource.cpp b/services/inputflinger/InputDeviceMetricsSource.cpp
index dee4cb8..70262fb 100644
--- a/services/inputflinger/InputDeviceMetricsSource.cpp
+++ b/services/inputflinger/InputDeviceMetricsSource.cpp
@@ -50,6 +50,18 @@
return InputDeviceUsageSource::BUTTONS;
}
+std::set<InputDeviceUsageSource> getUsageSourcesForKeyArgs(
+ const NotifyKeyArgs& args, const std::vector<InputDeviceInfo>& inputDevices) {
+ int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NONE;
+ for (const InputDeviceInfo& inputDevice : inputDevices) {
+ if (args.deviceId == inputDevice.getId()) {
+ keyboardType = inputDevice.getKeyboardType();
+ break;
+ }
+ }
+ return std::set{getUsageSourceForKeyArgs(keyboardType, args)};
+}
+
std::set<InputDeviceUsageSource> getUsageSourcesForMotionArgs(const NotifyMotionArgs& motionArgs) {
LOG_ALWAYS_FATAL_IF(motionArgs.getPointerCount() < 1, "Received motion args without pointers");
std::set<InputDeviceUsageSource> sources;
diff --git a/services/inputflinger/InputDeviceMetricsSource.h b/services/inputflinger/InputDeviceMetricsSource.h
index a6be8f4..702badd 100644
--- a/services/inputflinger/InputDeviceMetricsSource.h
+++ b/services/inputflinger/InputDeviceMetricsSource.h
@@ -54,6 +54,10 @@
/** Returns the InputDeviceUsageSource that corresponds to the key event. */
InputDeviceUsageSource getUsageSourceForKeyArgs(int32_t keyboardType, const NotifyKeyArgs&);
+/** Returns the InputDeviceUsageSources that correspond to the key event. */
+std::set<InputDeviceUsageSource> getUsageSourcesForKeyArgs(
+ const NotifyKeyArgs&, const std::vector<InputDeviceInfo>& inputDevices);
+
/** Returns the InputDeviceUsageSources that correspond to the motion event. */
std::set<InputDeviceUsageSource> getUsageSourcesForMotionArgs(const NotifyMotionArgs&);
diff --git a/services/inputflinger/InputFilter.cpp b/services/inputflinger/InputFilter.cpp
index 2ef94fb..bb4e617 100644
--- a/services/inputflinger/InputFilter.cpp
+++ b/services/inputflinger/InputFilter.cpp
@@ -56,7 +56,7 @@
void InputFilter::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
mDeviceInfos.clear();
mDeviceInfos.reserve(args.inputDeviceInfos.size());
- for (auto info : args.inputDeviceInfos) {
+ for (const auto& info : args.inputDeviceInfos) {
AidlDeviceInfo& aidlInfo = mDeviceInfos.emplace_back();
aidlInfo.deviceId = info.getId();
aidlInfo.external = info.isExternal();
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index b155122..7d62ed9 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -41,8 +41,6 @@
const bool ENABLE_INPUT_DEVICE_USAGE_METRICS =
sysprop::InputProperties::enable_input_device_usage_metrics().value_or(true);
-const bool ENABLE_INPUT_FILTER_RUST = input_flags::enable_input_filter_rust_impl();
-
int32_t exceptionCodeFromStatusT(status_t status) {
switch (status) {
case OK:
@@ -134,12 +132,10 @@
mTracingStages.emplace_back(
std::make_unique<TracedInputListener>("InputDispatcher", *mDispatcher));
- if (ENABLE_INPUT_FILTER_RUST) {
- mInputFilter = std::make_unique<InputFilter>(*mTracingStages.back(), *mInputFlingerRust,
- inputFilterPolicy);
- mTracingStages.emplace_back(
- std::make_unique<TracedInputListener>("InputFilter", *mInputFilter));
- }
+ mInputFilter = std::make_unique<InputFilter>(*mTracingStages.back(), *mInputFlingerRust,
+ inputFilterPolicy);
+ mTracingStages.emplace_back(
+ std::make_unique<TracedInputListener>("InputFilter", *mInputFilter));
if (ENABLE_INPUT_DEVICE_USAGE_METRICS) {
mCollector = std::make_unique<InputDeviceMetricsCollector>(*mTracingStages.back());
@@ -250,10 +246,8 @@
mCollector->dump(dump);
dump += '\n';
}
- if (ENABLE_INPUT_FILTER_RUST) {
- mInputFilter->dump(dump);
- dump += '\n';
- }
+ mInputFilter->dump(dump);
+ dump += '\n';
mDispatcher->dump(dump);
dump += '\n';
}
diff --git a/services/inputflinger/NotifyArgs.cpp b/services/inputflinger/NotifyArgs.cpp
index b2680a2..3de639f 100644
--- a/services/inputflinger/NotifyArgs.cpp
+++ b/services/inputflinger/NotifyArgs.cpp
@@ -206,4 +206,9 @@
return std::visit(toStringVisitor, args);
}
+std::ostream& operator<<(std::ostream& out, const NotifyArgs& args) {
+ out << toString(args);
+ return out;
+}
+
} // namespace android
diff --git a/services/inputflinger/PointerChoreographer.cpp b/services/inputflinger/PointerChoreographer.cpp
index 006d507..98b514b 100644
--- a/services/inputflinger/PointerChoreographer.cpp
+++ b/services/inputflinger/PointerChoreographer.cpp
@@ -17,10 +17,13 @@
#define LOG_TAG "PointerChoreographer"
#include <android-base/logging.h>
+#include <android/configuration.h>
#include <com_android_input_flags.h>
+#include <algorithm>
#if defined(__ANDROID__)
#include <gui/SurfaceComposerClient.h>
#endif
+#include <input/InputFlags.h>
#include <input/Keyboard.h>
#include <input/PrintTools.h>
#include <unordered_set>
@@ -33,40 +36,8 @@
namespace {
-bool isFromMouse(const NotifyMotionArgs& args) {
- return isFromSource(args.source, AINPUT_SOURCE_MOUSE) &&
- args.pointerProperties[0].toolType == ToolType::MOUSE;
-}
-
-bool isFromTouchpad(const NotifyMotionArgs& args) {
- return isFromSource(args.source, AINPUT_SOURCE_MOUSE) &&
- args.pointerProperties[0].toolType == ToolType::FINGER;
-}
-
-bool isFromDrawingTablet(const NotifyMotionArgs& args) {
- return isFromSource(args.source, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS) &&
- isStylusToolType(args.pointerProperties[0].toolType);
-}
-
-bool isHoverAction(int32_t action) {
- return action == AMOTION_EVENT_ACTION_HOVER_ENTER ||
- action == AMOTION_EVENT_ACTION_HOVER_MOVE || action == AMOTION_EVENT_ACTION_HOVER_EXIT;
-}
-
-bool isStylusHoverEvent(const NotifyMotionArgs& args) {
- return isStylusEvent(args.source, args.pointerProperties) && isHoverAction(args.action);
-}
-
-bool isMouseOrTouchpad(uint32_t sources) {
- // Check if this is a mouse or touchpad, but not a drawing tablet.
- return isFromSource(sources, AINPUT_SOURCE_MOUSE_RELATIVE) ||
- (isFromSource(sources, AINPUT_SOURCE_MOUSE) &&
- !isFromSource(sources, AINPUT_SOURCE_STYLUS));
-}
-
-inline void notifyPointerDisplayChange(
- std::optional<std::tuple<ui::LogicalDisplayId, FloatPoint>> change,
- PointerChoreographerPolicyInterface& policy) {
+inline void notifyPointerDisplayChange(std::optional<std::tuple<ui::LogicalDisplayId, vec2>> change,
+ PointerChoreographerPolicyInterface& policy) {
if (!change) {
return;
}
@@ -99,6 +70,33 @@
return privacySensitiveDisplays;
}
+vec2 calculatePositionOnDestinationViewport(const DisplayViewport& destinationViewport,
+ float pointerOffset,
+ DisplayTopologyPosition sourceBoundary) {
+ // destination is opposite of the source boundary
+ switch (sourceBoundary) {
+ case DisplayTopologyPosition::RIGHT:
+ return {0, pointerOffset}; // left edge
+ case DisplayTopologyPosition::TOP:
+ return {pointerOffset, destinationViewport.logicalBottom}; // bottom edge
+ case DisplayTopologyPosition::LEFT:
+ return {destinationViewport.logicalRight, pointerOffset}; // right edge
+ case DisplayTopologyPosition::BOTTOM:
+ return {pointerOffset, 0}; // top edge
+ }
+}
+
+// The standardised medium display density for which 1 px = 1 dp
+constexpr int32_t DENSITY_MEDIUM = ACONFIGURATION_DENSITY_MEDIUM;
+
+inline float pxToDp(int px, int dpi) {
+ return static_cast<float>(px * DENSITY_MEDIUM) / static_cast<float>(dpi);
+}
+
+inline int dpToPx(float dp, int dpi) {
+ return static_cast<int>((dp * dpi) / DENSITY_MEDIUM);
+}
+
} // namespace
// --- PointerChoreographer ---
@@ -134,28 +132,30 @@
}),
mNextListener(listener),
mPolicy(policy),
- mDefaultMouseDisplayId(ui::LogicalDisplayId::DEFAULT),
+ mCurrentMouseDisplayId(ui::LogicalDisplayId::INVALID),
mNotifiedPointerDisplayId(ui::LogicalDisplayId::INVALID),
mShowTouchesEnabled(false),
mStylusPointerIconEnabled(false),
+ mPointerMotionFilterEnabled(false),
mCurrentFocusedDisplay(ui::LogicalDisplayId::DEFAULT),
+ mIsWindowInfoListenerRegistered(false),
+ mWindowInfoListener(sp<PointerChoreographerDisplayInfoListener>::make(this)),
mRegisterListener(registerListener),
mUnregisterListener(unregisterListener) {}
PointerChoreographer::~PointerChoreographer() {
- std::scoped_lock _l(mLock);
- if (mWindowInfoListener == nullptr) {
- return;
+ if (mIsWindowInfoListenerRegistered) {
+ mUnregisterListener(mWindowInfoListener);
+ mIsWindowInfoListenerRegistered = false;
}
mWindowInfoListener->onPointerChoreographerDestroyed();
- mUnregisterListener(mWindowInfoListener);
}
void PointerChoreographer::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
PointerDisplayChange pointerDisplayChange;
{ // acquire lock
- std::scoped_lock _l(mLock);
+ std::scoped_lock _l(getLock());
mInputDeviceInfos = args.inputDeviceInfos;
pointerDisplayChange = updatePointerControllersLocked();
@@ -191,7 +191,7 @@
return;
}
- std::scoped_lock _l(mLock);
+ std::scoped_lock _l(getLock());
ui::LogicalDisplayId targetDisplay = args.displayId;
if (targetDisplay == ui::LogicalDisplayId::INVALID) {
targetDisplay = mCurrentFocusedDisplay;
@@ -204,20 +204,31 @@
}
NotifyMotionArgs PointerChoreographer::processMotion(const NotifyMotionArgs& args) {
- std::scoped_lock _l(mLock);
+ NotifyMotionArgs newArgs(args);
+ PointerDisplayChange pointerDisplayChange;
+ { // acquire lock
+ std::scoped_lock _l(getLock());
+ if (isFromMouse(args.source, args.pointerProperties[0].toolType)) {
+ newArgs = processMouseEventLocked(args);
+ pointerDisplayChange = calculatePointerDisplayChangeToNotify();
+ } else if (isFromTouchpad(args.source, args.pointerProperties[0].toolType)) {
+ newArgs = processTouchpadEventLocked(args);
+ pointerDisplayChange = calculatePointerDisplayChangeToNotify();
+ } else if (isFromDrawingTablet(args.source, args.pointerProperties[0].toolType)) {
+ processDrawingTabletEventLocked(args);
+ } else if (mStylusPointerIconEnabled &&
+ isStylusHoverEvent(args.source, args.pointerProperties, args.action)) {
+ processStylusHoverEventLocked(args);
+ } else if (isFromSource(args.source, AINPUT_SOURCE_TOUCHSCREEN)) {
+ processTouchscreenAndStylusEventLocked(args);
+ }
+ } // release lock
- if (isFromMouse(args)) {
- return processMouseEventLocked(args);
- } else if (isFromTouchpad(args)) {
- return processTouchpadEventLocked(args);
- } else if (isFromDrawingTablet(args)) {
- processDrawingTabletEventLocked(args);
- } else if (mStylusPointerIconEnabled && isStylusHoverEvent(args)) {
- processStylusHoverEventLocked(args);
- } else if (isFromSource(args.source, AINPUT_SOURCE_TOUCHSCREEN)) {
- processTouchscreenAndStylusEventLocked(args);
+ if (pointerDisplayChange) {
+ // pointer display may have changed if mouse crossed display boundary
+ notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
}
- return args;
+ return newArgs;
}
NotifyMotionArgs PointerChoreographer::processMouseEventLocked(const NotifyMotionArgs& args) {
@@ -234,24 +245,18 @@
if (MotionEvent::isValidCursorPosition(args.xCursorPosition, args.yCursorPosition)) {
// This is an absolute mouse device that knows about the location of the cursor on the
// display, so set the cursor position to the specified location.
- const auto [x, y] = pc.getPosition();
- const float deltaX = args.xCursorPosition - x;
- const float deltaY = args.yCursorPosition - y;
+ const auto position = pc.getPosition();
+ const float deltaX = args.xCursorPosition - position.x;
+ const float deltaY = args.yCursorPosition - position.y;
newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
pc.setPosition(args.xCursorPosition, args.yCursorPosition);
} else {
// This is a relative mouse, so move the cursor by the specified amount.
- const float deltaX = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
- const float deltaY = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
- pc.move(deltaX, deltaY);
- const auto [x, y] = pc.getPosition();
- newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
- newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
- newArgs.xCursorPosition = x;
- newArgs.yCursorPosition = y;
+ processPointerDeviceMotionEventLocked(/*byref*/ newArgs, /*byref*/ pc);
}
- if (canUnfadeOnDisplay(displayId)) {
+ // Note displayId may have changed if the cursor moved to a different display
+ if (canUnfadeOnDisplay(newArgs.displayId)) {
pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
}
return newArgs;
@@ -265,37 +270,118 @@
newArgs.displayId = displayId;
if (args.getPointerCount() == 1 && args.classification == MotionClassification::NONE) {
// This is a movement of the mouse pointer.
- const float deltaX = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
- const float deltaY = args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
- pc.move(deltaX, deltaY);
- if (canUnfadeOnDisplay(displayId)) {
- pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
- }
-
- const auto [x, y] = pc.getPosition();
- newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
- newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
- newArgs.xCursorPosition = x;
- newArgs.yCursorPosition = y;
+ processPointerDeviceMotionEventLocked(/*byref*/ newArgs, /*byref*/ pc);
} else {
// This is a trackpad gesture with fake finger(s) that should not move the mouse pointer.
- if (canUnfadeOnDisplay(displayId)) {
- pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
- }
-
- const auto [x, y] = pc.getPosition();
+ const auto position = pc.getPosition();
for (uint32_t i = 0; i < newArgs.getPointerCount(); i++) {
newArgs.pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X,
- args.pointerCoords[i].getX() + x);
+ args.pointerCoords[i].getX() + position.x);
newArgs.pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y,
- args.pointerCoords[i].getY() + y);
+ args.pointerCoords[i].getY() + position.y);
}
- newArgs.xCursorPosition = x;
- newArgs.yCursorPosition = y;
+ newArgs.xCursorPosition = position.x;
+ newArgs.yCursorPosition = position.y;
+ }
+
+ // Note displayId may have changed if the cursor moved to a different display
+ if (canUnfadeOnDisplay(newArgs.displayId)) {
+ pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
}
return newArgs;
}
+void PointerChoreographer::processPointerDeviceMotionEventLocked(NotifyMotionArgs& newArgs,
+ PointerControllerInterface& pc) {
+ const float deltaX = newArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
+ const float deltaY = newArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
+ vec2 filteredDelta =
+ filterPointerMotionForAccessibilityLocked(pc.getPosition(), vec2{deltaX, deltaY},
+ newArgs.displayId);
+ vec2 unconsumedDelta = pc.move(filteredDelta.x, filteredDelta.y);
+ if (InputFlags::connectedDisplaysCursorEnabled() &&
+ (std::abs(unconsumedDelta.x) > 0 || std::abs(unconsumedDelta.y) > 0)) {
+ handleUnconsumedDeltaLocked(pc, unconsumedDelta);
+ // pointer may have moved to a different viewport
+ newArgs.displayId = pc.getDisplayId();
+ }
+
+ const auto position = pc.getPosition();
+ newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, position.x);
+ newArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, position.y);
+ newArgs.xCursorPosition = position.x;
+ newArgs.yCursorPosition = position.y;
+}
+
+void PointerChoreographer::handleUnconsumedDeltaLocked(PointerControllerInterface& pc,
+ const vec2& unconsumedDelta) {
+ // Display topology is in rotated coordinate space and Pointer controller returns and expects
+ // values in the un-rotated coordinate space. So we need to transform delta and cursor position
+ // back to the rotated coordinate space to lookup adjacent display in the display topology.
+ const auto& sourceDisplayTransform = pc.getDisplayTransform();
+ const vec2 rotatedUnconsumedDelta =
+ transformWithoutTranslation(sourceDisplayTransform, unconsumedDelta);
+ const vec2 cursorPosition = pc.getPosition();
+ const vec2 rotatedCursorPosition = sourceDisplayTransform.transform(cursorPosition);
+
+ // To find out the boundary that cursor is crossing we are checking delta in x and y direction
+ // respectively. This prioritizes x direction over y.
+ // In practise, majority of cases we only have non-zero values in either x or y coordinates,
+ // except sometimes near the corners.
+ // In these cases this behaviour is not noticeable. We also do not apply unconsumed delta on
+ // the destination display for the same reason.
+ DisplayTopologyPosition sourceBoundary;
+ float cursorOffset = 0.0f;
+ if (rotatedUnconsumedDelta.x > 0) {
+ sourceBoundary = DisplayTopologyPosition::RIGHT;
+ cursorOffset = rotatedCursorPosition.y;
+ } else if (rotatedUnconsumedDelta.x < 0) {
+ sourceBoundary = DisplayTopologyPosition::LEFT;
+ cursorOffset = rotatedCursorPosition.y;
+ } else if (rotatedUnconsumedDelta.y > 0) {
+ sourceBoundary = DisplayTopologyPosition::BOTTOM;
+ cursorOffset = rotatedCursorPosition.x;
+ } else {
+ sourceBoundary = DisplayTopologyPosition::TOP;
+ cursorOffset = rotatedCursorPosition.x;
+ }
+
+ const ui::LogicalDisplayId sourceDisplayId = pc.getDisplayId();
+ std::optional<std::pair<const DisplayViewport*, float /*offset*/>> destination =
+ findDestinationDisplayLocked(sourceDisplayId, sourceBoundary, cursorOffset);
+ if (!destination.has_value()) {
+ // No matching adjacent display
+ return;
+ }
+
+ const DisplayViewport& destinationViewport = *destination->first;
+ const float destinationOffset = destination->second;
+ if (mMousePointersByDisplay.find(destinationViewport.displayId) !=
+ mMousePointersByDisplay.end()) {
+ LOG(FATAL) << "A cursor already exists on destination display"
+ << destinationViewport.displayId;
+ }
+ mCurrentMouseDisplayId = destinationViewport.displayId;
+ auto pcNode = mMousePointersByDisplay.extract(sourceDisplayId);
+ pcNode.key() = destinationViewport.displayId;
+ mMousePointersByDisplay.insert(std::move(pcNode));
+
+ // Before updating the viewport and moving the cursor to appropriate location in the destination
+ // viewport, we need to temporarily hide the cursor. This will prevent it from appearing at the
+ // center of the display in any intermediate frames.
+ pc.fade(PointerControllerInterface::Transition::IMMEDIATE);
+ pc.setDisplayViewport(destinationViewport);
+ vec2 destinationPosition =
+ calculatePositionOnDestinationViewport(destinationViewport, destinationOffset,
+ sourceBoundary);
+
+ // Transform position back to un-rotated coordinate space before sending it to controller
+ destinationPosition = pc.getDisplayTransform().inverse().transform(destinationPosition.x,
+ destinationPosition.y);
+ pc.setPosition(destinationPosition.x, destinationPosition.y);
+ pc.unfade(PointerControllerInterface::Transition::IMMEDIATE);
+}
+
void PointerChoreographer::processDrawingTabletEventLocked(const android::NotifyMotionArgs& args) {
if (args.displayId == ui::LogicalDisplayId::INVALID) {
return;
@@ -390,6 +476,14 @@
<< args.dump();
}
+ // Fade the mouse pointer on the display if there is one when the stylus starts hovering.
+ if (args.action == AMOTION_EVENT_ACTION_HOVER_ENTER) {
+ if (const auto it = mMousePointersByDisplay.find(args.displayId);
+ it != mMousePointersByDisplay.end()) {
+ it->second->fade(PointerControllerInterface::Transition::GRADUAL);
+ }
+ }
+
// Get the stylus pointer controller for the device, or create one if it doesn't exist.
auto [it, controllerAdded] =
mStylusPointersByDevice.try_emplace(args.deviceId,
@@ -433,7 +527,7 @@
}
void PointerChoreographer::processDeviceReset(const NotifyDeviceResetArgs& args) {
- std::scoped_lock _l(mLock);
+ std::scoped_lock _l(getLock());
mTouchPointersByDevice.erase(args.deviceId);
mStylusPointersByDevice.erase(args.deviceId);
mDrawingTabletPointersByDevice.erase(args.deviceId);
@@ -447,17 +541,22 @@
bool requireListener = !mTouchPointersByDevice.empty() || !mMousePointersByDisplay.empty() ||
!mDrawingTabletPointersByDevice.empty() || !mStylusPointersByDevice.empty();
- if (requireListener && mWindowInfoListener == nullptr) {
- mWindowInfoListener = sp<PointerChoreographerDisplayInfoListener>::make(this);
- mWindowInfoListener->setInitialDisplayInfos(mRegisterListener(mWindowInfoListener));
- onPrivacySensitiveDisplaysChangedLocked(mWindowInfoListener->getPrivacySensitiveDisplays());
- } else if (!requireListener && mWindowInfoListener != nullptr) {
+ // PointerChoreographer uses Listener's lock which is already held by caller
+ base::ScopedLockAssertion assumeLocked(mWindowInfoListener->mLock);
+
+ if (requireListener && !mIsWindowInfoListenerRegistered) {
+ mIsWindowInfoListenerRegistered = true;
+ mWindowInfoListener->setInitialDisplayInfosLocked(mRegisterListener(mWindowInfoListener));
+ onPrivacySensitiveDisplaysChangedLocked(
+ mWindowInfoListener->getPrivacySensitiveDisplaysLocked());
+ } else if (!requireListener && mIsWindowInfoListenerRegistered) {
+ mIsWindowInfoListenerRegistered = false;
mUnregisterListener(mWindowInfoListener);
- mWindowInfoListener = nullptr;
- } else if (requireListener && mWindowInfoListener != nullptr) {
+ } else if (requireListener) {
// controller may have been added to an existing privacy sensitive display, we need to
// update all controllers again
- onPrivacySensitiveDisplaysChangedLocked(mWindowInfoListener->getPrivacySensitiveDisplays());
+ onPrivacySensitiveDisplaysChangedLocked(
+ mWindowInfoListener->getPrivacySensitiveDisplaysLocked());
}
}
@@ -494,7 +593,7 @@
void PointerChoreographer::notifyPointerCaptureChanged(
const NotifyPointerCaptureChangedArgs& args) {
if (args.request.isEnable()) {
- std::scoped_lock _l(mLock);
+ std::scoped_lock _l(getLock());
for (const auto& [_, mousePointerController] : mMousePointersByDisplay) {
mousePointerController->fade(PointerControllerInterface::Transition::IMMEDIATE);
}
@@ -502,20 +601,34 @@
mNextListener.notify(args);
}
-void PointerChoreographer::onPrivacySensitiveDisplaysChanged(
- const std::unordered_set<ui::LogicalDisplayId>& privacySensitiveDisplays) {
- std::scoped_lock _l(mLock);
- onPrivacySensitiveDisplaysChangedLocked(privacySensitiveDisplays);
+void PointerChoreographer::setDisplayTopology(const DisplayTopologyGraph& displayTopologyGraph) {
+ PointerDisplayChange pointerDisplayChange;
+ { // acquire lock
+ std::scoped_lock _l(getLock());
+ mTopology = displayTopologyGraph;
+
+ // make primary display default mouse display, if it was not set or
+ // the existing display was removed
+ if (mCurrentMouseDisplayId == ui::LogicalDisplayId::INVALID ||
+ mTopology.graph.find(mCurrentMouseDisplayId) == mTopology.graph.end()) {
+ mCurrentMouseDisplayId = mTopology.primaryDisplayId;
+ pointerDisplayChange = updatePointerControllersLocked();
+ }
+ } // release lock
+
+ notifyPointerDisplayChange(pointerDisplayChange, mPolicy);
}
void PointerChoreographer::dump(std::string& dump) {
- std::scoped_lock _l(mLock);
+ std::scoped_lock _l(getLock());
dump += "PointerChoreographer:\n";
dump += StringPrintf(INDENT "Show Touches Enabled: %s\n",
mShowTouchesEnabled ? "true" : "false");
dump += StringPrintf(INDENT "Stylus PointerIcon Enabled: %s\n",
mStylusPointerIconEnabled ? "true" : "false");
+ dump += StringPrintf(INDENT "Accessibility Pointer Motion Filter Enabled: %s\n",
+ mPointerMotionFilterEnabled ? "true" : "false");
dump += INDENT "MousePointerControllers:\n";
for (const auto& [displayId, mousePointerController] : mMousePointersByDisplay) {
@@ -552,7 +665,19 @@
ui::LogicalDisplayId PointerChoreographer::getTargetMouseDisplayLocked(
ui::LogicalDisplayId associatedDisplayId) const {
- return associatedDisplayId.isValid() ? associatedDisplayId : mDefaultMouseDisplayId;
+ if (!InputFlags::connectedDisplaysCursorAndAssociatedDisplayCursorBugfixEnabled()) {
+ if (associatedDisplayId.isValid()) {
+ return associatedDisplayId;
+ }
+ return mCurrentMouseDisplayId.isValid() ? mCurrentMouseDisplayId
+ : ui::LogicalDisplayId::DEFAULT;
+ }
+ // Associated display is not included in the topology, return this associated display.
+ if (associatedDisplayId.isValid() &&
+ mTopology.graph.find(associatedDisplayId) == mTopology.graph.end()) {
+ return associatedDisplayId;
+ }
+ return mCurrentMouseDisplayId.isValid() ? mCurrentMouseDisplayId : mTopology.primaryDisplayId;
}
std::pair<ui::LogicalDisplayId, PointerControllerInterface&>
@@ -579,6 +704,10 @@
return mDisplaysWithPointersHidden.find(displayId) == mDisplaysWithPointersHidden.end();
}
+std::mutex& PointerChoreographer::getLock() const {
+ return mWindowInfoListener->mLock;
+}
+
PointerChoreographer::PointerDisplayChange PointerChoreographer::updatePointerControllersLocked() {
std::set<ui::LogicalDisplayId /*displayId*/> mouseDisplaysToKeep;
std::set<DeviceId> touchDevicesToKeep;
@@ -641,7 +770,7 @@
std::erase_if(mDrawingTabletPointersByDevice, [&drawingTabletDevicesToKeep](const auto& pair) {
return drawingTabletDevicesToKeep.find(pair.first) == drawingTabletDevicesToKeep.end();
});
- std::erase_if(mMouseDevices, [&](DeviceId id) REQUIRES(mLock) {
+ std::erase_if(mMouseDevices, [&](DeviceId id) REQUIRES(getLock()) {
return std::find_if(mInputDeviceInfos.begin(), mInputDeviceInfos.end(),
[id](const auto& info) { return info.getId() == id; }) ==
mInputDeviceInfos.end();
@@ -656,8 +785,8 @@
PointerChoreographer::PointerDisplayChange
PointerChoreographer::calculatePointerDisplayChangeToNotify() {
ui::LogicalDisplayId displayIdToNotify = ui::LogicalDisplayId::INVALID;
- FloatPoint cursorPosition = {0, 0};
- if (const auto it = mMousePointersByDisplay.find(mDefaultMouseDisplayId);
+ vec2 cursorPosition = {0, 0};
+ if (const auto it = mMousePointersByDisplay.find(mCurrentMouseDisplayId);
it != mMousePointersByDisplay.end()) {
const auto& pointerController = it->second;
// Use the displayId from the pointerController, because it accurately reflects whether
@@ -674,12 +803,16 @@
}
void PointerChoreographer::setDefaultMouseDisplayId(ui::LogicalDisplayId displayId) {
+ if (InputFlags::connectedDisplaysCursorEnabled()) {
+ // In connected displays scenario, default mouse display will only be updated from topology.
+ return;
+ }
PointerDisplayChange pointerDisplayChange;
{ // acquire lock
- std::scoped_lock _l(mLock);
+ std::scoped_lock _l(getLock());
- mDefaultMouseDisplayId = displayId;
+ mCurrentMouseDisplayId = displayId;
pointerDisplayChange = updatePointerControllersLocked();
} // release lock
@@ -690,7 +823,7 @@
PointerDisplayChange pointerDisplayChange;
{ // acquire lock
- std::scoped_lock _l(mLock);
+ std::scoped_lock _l(getLock());
for (const auto& viewport : viewports) {
const ui::LogicalDisplayId displayId = viewport.displayId;
if (const auto it = mMousePointersByDisplay.find(displayId);
@@ -719,7 +852,7 @@
std::optional<DisplayViewport> PointerChoreographer::getViewportForPointerDevice(
ui::LogicalDisplayId associatedDisplayId) {
- std::scoped_lock _l(mLock);
+ std::scoped_lock _l(getLock());
const ui::LogicalDisplayId resolvedDisplayId = getTargetMouseDisplayLocked(associatedDisplayId);
if (const auto viewport = findViewportByIdLocked(resolvedDisplayId); viewport) {
return *viewport;
@@ -727,8 +860,8 @@
return std::nullopt;
}
-FloatPoint PointerChoreographer::getMouseCursorPosition(ui::LogicalDisplayId displayId) {
- std::scoped_lock _l(mLock);
+vec2 PointerChoreographer::getMouseCursorPosition(ui::LogicalDisplayId displayId) {
+ std::scoped_lock _l(getLock());
const ui::LogicalDisplayId resolvedDisplayId = getTargetMouseDisplayLocked(displayId);
if (auto it = mMousePointersByDisplay.find(resolvedDisplayId);
it != mMousePointersByDisplay.end()) {
@@ -741,7 +874,7 @@
PointerDisplayChange pointerDisplayChange;
{ // acquire lock
- std::scoped_lock _l(mLock);
+ std::scoped_lock _l(getLock());
if (mShowTouchesEnabled == enabled) {
return;
}
@@ -756,7 +889,7 @@
PointerDisplayChange pointerDisplayChange;
{ // acquire lock
- std::scoped_lock _l(mLock);
+ std::scoped_lock _l(getLock());
if (mStylusPointerIconEnabled == enabled) {
return;
}
@@ -770,7 +903,7 @@
bool PointerChoreographer::setPointerIcon(
std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon,
ui::LogicalDisplayId displayId, DeviceId deviceId) {
- std::scoped_lock _l(mLock);
+ std::scoped_lock _l(getLock());
if (deviceId < 0) {
LOG(WARNING) << "Invalid device id " << deviceId << ". Cannot set pointer icon.";
return false;
@@ -821,7 +954,7 @@
}
void PointerChoreographer::setPointerIconVisibility(ui::LogicalDisplayId displayId, bool visible) {
- std::scoped_lock lock(mLock);
+ std::scoped_lock lock(getLock());
if (visible) {
mDisplaysWithPointersHidden.erase(displayId);
// We do not unfade the icons here, because we don't know when the last event happened.
@@ -843,14 +976,19 @@
}
void PointerChoreographer::setFocusedDisplay(ui::LogicalDisplayId displayId) {
- std::scoped_lock lock(mLock);
+ std::scoped_lock lock(getLock());
mCurrentFocusedDisplay = displayId;
}
+void PointerChoreographer::setAccessibilityPointerMotionFilterEnabled(bool enabled) {
+ std::scoped_lock _l(getLock());
+ mPointerMotionFilterEnabled = enabled;
+}
+
PointerChoreographer::ControllerConstructor PointerChoreographer::getMouseControllerConstructor(
ui::LogicalDisplayId displayId) {
std::function<std::shared_ptr<PointerControllerInterface>()> ctor =
- [this, displayId]() REQUIRES(mLock) {
+ [this, displayId]() REQUIRES(getLock()) {
auto pc = mPolicy.createPointerController(
PointerControllerInterface::ControllerType::MOUSE);
if (const auto viewport = findViewportByIdLocked(displayId); viewport) {
@@ -864,7 +1002,7 @@
PointerChoreographer::ControllerConstructor PointerChoreographer::getStylusControllerConstructor(
ui::LogicalDisplayId displayId) {
std::function<std::shared_ptr<PointerControllerInterface>()> ctor =
- [this, displayId]() REQUIRES(mLock) {
+ [this, displayId]() REQUIRES(getLock()) {
auto pc = mPolicy.createPointerController(
PointerControllerInterface::ControllerType::STYLUS);
if (const auto viewport = findViewportByIdLocked(displayId); viewport) {
@@ -875,35 +1013,98 @@
return ConstructorDelegate(std::move(ctor));
}
+std::optional<std::pair<const DisplayViewport*, float /*offsetPx*/>>
+PointerChoreographer::findDestinationDisplayLocked(const ui::LogicalDisplayId sourceDisplayId,
+ const DisplayTopologyPosition sourceBoundary,
+ int32_t sourceCursorOffsetPx) const {
+ const auto& sourceNode = mTopology.graph.find(sourceDisplayId);
+ if (sourceNode == mTopology.graph.end()) {
+ // Topology is likely out of sync with viewport info, wait for it to be updated
+ LOG(WARNING) << "Source display missing from topology " << sourceDisplayId;
+ return std::nullopt;
+ }
+ for (const DisplayTopologyAdjacentDisplay& adjacentDisplay : sourceNode->second) {
+ if (adjacentDisplay.position != sourceBoundary) {
+ continue;
+ }
+ const DisplayViewport* adjacentViewport = findViewportByIdLocked(adjacentDisplay.displayId);
+ if (adjacentViewport == nullptr) {
+ // Topology is likely out of sync with viewport info, wait for them to be updated
+ LOG(WARNING) << "Cannot find viewport for adjacent display "
+ << adjacentDisplay.displayId << "of source display " << sourceDisplayId;
+ continue;
+ }
+ // As displays can have different densities we need to do all calculations in
+ // density-independent-pixels a.k.a. dp values.
+ const int sourceDensity = mTopology.displaysDensity.at(sourceDisplayId);
+ const int adjacentDisplayDensity = mTopology.displaysDensity.at(adjacentDisplay.displayId);
+ const float sourceCursorOffsetDp = pxToDp(sourceCursorOffsetPx, sourceDensity);
+ const int32_t edgeSizePx = sourceBoundary == DisplayTopologyPosition::TOP ||
+ sourceBoundary == DisplayTopologyPosition::BOTTOM
+ ? (adjacentViewport->logicalRight - adjacentViewport->logicalLeft)
+ : (adjacentViewport->logicalBottom - adjacentViewport->logicalTop);
+ const float adjacentEdgeSizeDp = pxToDp(edgeSizePx, adjacentDisplayDensity);
+ // Target position must be within target display boundary.
+ // Cursor should also be able to cross displays when only display corners are touching and
+ // there may be zero overlapping pixels. To accommodate this we have margin of one pixel
+ // around the end of the overlapping edge.
+ if (sourceCursorOffsetDp >= adjacentDisplay.offsetDp &&
+ sourceCursorOffsetDp <= adjacentDisplay.offsetDp + adjacentEdgeSizeDp) {
+ const int destinationOffsetPx =
+ dpToPx(sourceCursorOffsetDp - adjacentDisplay.offsetDp, adjacentDisplayDensity);
+ return std::make_pair(adjacentViewport, destinationOffsetPx);
+ }
+ }
+ return std::nullopt;
+}
+
+vec2 PointerChoreographer::filterPointerMotionForAccessibilityLocked(
+ const vec2& current, const vec2& delta, const ui::LogicalDisplayId& displayId) {
+ if (!mPointerMotionFilterEnabled) {
+ return delta;
+ }
+ std::optional<vec2> filterResult =
+ mPolicy.filterPointerMotionForAccessibility(current, delta, displayId);
+ if (!filterResult.has_value()) {
+ // Disable filter when there's any error.
+ mPointerMotionFilterEnabled = false;
+ return delta;
+ }
+ return *filterResult;
+}
+
+// --- PointerChoreographer::PointerChoreographerDisplayInfoListener ---
+
void PointerChoreographer::PointerChoreographerDisplayInfoListener::onWindowInfosChanged(
const gui::WindowInfosUpdate& windowInfosUpdate) {
- std::scoped_lock _l(mListenerLock);
+ std::scoped_lock _l(mLock);
if (mPointerChoreographer == nullptr) {
return;
}
auto newPrivacySensitiveDisplays =
getPrivacySensitiveDisplaysFromWindowInfos(windowInfosUpdate.windowInfos);
+
+ // PointerChoreographer uses Listener's lock.
+ base::ScopedLockAssertion assumeLocked(mPointerChoreographer->getLock());
if (newPrivacySensitiveDisplays != mPrivacySensitiveDisplays) {
mPrivacySensitiveDisplays = std::move(newPrivacySensitiveDisplays);
- mPointerChoreographer->onPrivacySensitiveDisplaysChanged(mPrivacySensitiveDisplays);
+ mPointerChoreographer->onPrivacySensitiveDisplaysChangedLocked(mPrivacySensitiveDisplays);
}
}
-void PointerChoreographer::PointerChoreographerDisplayInfoListener::setInitialDisplayInfos(
+void PointerChoreographer::PointerChoreographerDisplayInfoListener::setInitialDisplayInfosLocked(
const std::vector<gui::WindowInfo>& windowInfos) {
- std::scoped_lock _l(mListenerLock);
mPrivacySensitiveDisplays = getPrivacySensitiveDisplaysFromWindowInfos(windowInfos);
}
std::unordered_set<ui::LogicalDisplayId /*displayId*/>
-PointerChoreographer::PointerChoreographerDisplayInfoListener::getPrivacySensitiveDisplays() {
- std::scoped_lock _l(mListenerLock);
+PointerChoreographer::PointerChoreographerDisplayInfoListener::getPrivacySensitiveDisplaysLocked() {
return mPrivacySensitiveDisplays;
}
void PointerChoreographer::PointerChoreographerDisplayInfoListener::
onPointerChoreographerDestroyed() {
- std::scoped_lock _l(mListenerLock);
+ std::scoped_lock _l(mLock);
mPointerChoreographer = nullptr;
}
diff --git a/services/inputflinger/PointerChoreographer.h b/services/inputflinger/PointerChoreographer.h
index 635487b..67bdca1 100644
--- a/services/inputflinger/PointerChoreographer.h
+++ b/services/inputflinger/PointerChoreographer.h
@@ -22,6 +22,7 @@
#include <android-base/thread_annotations.h>
#include <gui/WindowInfosListener.h>
+#include <input/DisplayTopologyGraph.h>
#include <type_traits>
#include <unordered_set>
@@ -59,7 +60,7 @@
virtual void setDisplayViewports(const std::vector<DisplayViewport>& viewports) = 0;
virtual std::optional<DisplayViewport> getViewportForPointerDevice(
ui::LogicalDisplayId associatedDisplayId = ui::LogicalDisplayId::INVALID) = 0;
- virtual FloatPoint getMouseCursorPosition(ui::LogicalDisplayId displayId) = 0;
+ virtual vec2 getMouseCursorPosition(ui::LogicalDisplayId displayId) = 0;
virtual void setShowTouchesEnabled(bool enabled) = 0;
virtual void setStylusPointerIconEnabled(bool enabled) = 0;
/**
@@ -80,10 +81,20 @@
*/
virtual void setFocusedDisplay(ui::LogicalDisplayId displayId) = 0;
+ /*
+ * Used by InputManager to notify changes in the DisplayTopology
+ */
+ virtual void setDisplayTopology(const DisplayTopologyGraph& displayTopologyGraph) = 0;
+
/**
* This method may be called on any thread (usually by the input manager on a binder thread).
*/
virtual void dump(std::string& dump) = 0;
+
+ /**
+ * Enables motion event filter before pointer coordinates are determined.
+ */
+ virtual void setAccessibilityPointerMotionFilterEnabled(bool enabled) = 0;
};
class PointerChoreographer : public PointerChoreographerInterface {
@@ -96,13 +107,15 @@
void setDisplayViewports(const std::vector<DisplayViewport>& viewports) override;
std::optional<DisplayViewport> getViewportForPointerDevice(
ui::LogicalDisplayId associatedDisplayId) override;
- FloatPoint getMouseCursorPosition(ui::LogicalDisplayId displayId) override;
+ vec2 getMouseCursorPosition(ui::LogicalDisplayId displayId) override;
void setShowTouchesEnabled(bool enabled) override;
void setStylusPointerIconEnabled(bool enabled) override;
bool setPointerIcon(std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon,
ui::LogicalDisplayId displayId, DeviceId deviceId) override;
void setPointerIconVisibility(ui::LogicalDisplayId displayId, bool visible) override;
void setFocusedDisplay(ui::LogicalDisplayId displayId) override;
+ void setDisplayTopology(const DisplayTopologyGraph& displayTopologyGraph);
+ void setAccessibilityPointerMotionFilterEnabled(bool enabled) override;
void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
void notifyKey(const NotifyKeyArgs& args) override;
@@ -116,33 +129,60 @@
void dump(std::string& dump) override;
private:
- using PointerDisplayChange = std::optional<
- std::tuple<ui::LogicalDisplayId /*displayId*/, FloatPoint /*cursorPosition*/>>;
- [[nodiscard]] PointerDisplayChange updatePointerControllersLocked() REQUIRES(mLock);
- [[nodiscard]] PointerDisplayChange calculatePointerDisplayChangeToNotify() REQUIRES(mLock);
+ using PointerDisplayChange =
+ std::optional<std::tuple<ui::LogicalDisplayId /*displayId*/, vec2 /*cursorPosition*/>>;
+
+ // PointerChoreographer's DisplayInfoListener can outlive the PointerChoreographer because when
+ // the listener is registered and called from display thread, a strong pointer to the listener
+ // (which can extend its lifecycle) is given away.
+ // If we use two locks it can also cause deadlocks due to race in acquiring them between the
+ // display and reader thread.
+ // To avoid these problems we use DisplayInfoListener's lock in PointerChoreographer.
+ std::mutex& getLock() const;
+
+ [[nodiscard]] PointerDisplayChange updatePointerControllersLocked() REQUIRES(getLock());
+ [[nodiscard]] PointerDisplayChange calculatePointerDisplayChangeToNotify() REQUIRES(getLock());
const DisplayViewport* findViewportByIdLocked(ui::LogicalDisplayId displayId) const
- REQUIRES(mLock);
+ REQUIRES(getLock());
ui::LogicalDisplayId getTargetMouseDisplayLocked(ui::LogicalDisplayId associatedDisplayId) const
- REQUIRES(mLock);
+ REQUIRES(getLock());
std::pair<ui::LogicalDisplayId /*displayId*/, PointerControllerInterface&>
- ensureMouseControllerLocked(ui::LogicalDisplayId associatedDisplayId) REQUIRES(mLock);
- InputDeviceInfo* findInputDeviceLocked(DeviceId deviceId) REQUIRES(mLock);
- bool canUnfadeOnDisplay(ui::LogicalDisplayId displayId) REQUIRES(mLock);
+ ensureMouseControllerLocked(ui::LogicalDisplayId associatedDisplayId) REQUIRES(getLock());
+ InputDeviceInfo* findInputDeviceLocked(DeviceId deviceId) REQUIRES(getLock());
+ bool canUnfadeOnDisplay(ui::LogicalDisplayId displayId) REQUIRES(getLock());
void fadeMouseCursorOnKeyPress(const NotifyKeyArgs& args);
NotifyMotionArgs processMotion(const NotifyMotionArgs& args);
- NotifyMotionArgs processMouseEventLocked(const NotifyMotionArgs& args) REQUIRES(mLock);
- NotifyMotionArgs processTouchpadEventLocked(const NotifyMotionArgs& args) REQUIRES(mLock);
- void processDrawingTabletEventLocked(const NotifyMotionArgs& args) REQUIRES(mLock);
- void processTouchscreenAndStylusEventLocked(const NotifyMotionArgs& args) REQUIRES(mLock);
- void processStylusHoverEventLocked(const NotifyMotionArgs& args) REQUIRES(mLock);
+ NotifyMotionArgs processMouseEventLocked(const NotifyMotionArgs& args) REQUIRES(getLock());
+ NotifyMotionArgs processTouchpadEventLocked(const NotifyMotionArgs& args) REQUIRES(getLock());
+ void processDrawingTabletEventLocked(const NotifyMotionArgs& args) REQUIRES(getLock());
+ void processTouchscreenAndStylusEventLocked(const NotifyMotionArgs& args) REQUIRES(getLock());
+ void processStylusHoverEventLocked(const NotifyMotionArgs& args) REQUIRES(getLock());
+ void processPointerDeviceMotionEventLocked(NotifyMotionArgs& newArgs,
+ PointerControllerInterface& pc) REQUIRES(getLock());
void processDeviceReset(const NotifyDeviceResetArgs& args);
- void onControllerAddedOrRemovedLocked() REQUIRES(mLock);
+ void onControllerAddedOrRemovedLocked() REQUIRES(getLock());
void onPrivacySensitiveDisplaysChangedLocked(
const std::unordered_set<ui::LogicalDisplayId>& privacySensitiveDisplays)
- REQUIRES(mLock);
- void onPrivacySensitiveDisplaysChanged(
- const std::unordered_set<ui::LogicalDisplayId>& privacySensitiveDisplays);
+ REQUIRES(getLock());
+
+ void handleUnconsumedDeltaLocked(PointerControllerInterface& pc, const vec2& unconsumedDelta)
+ REQUIRES(getLock());
+
+ std::optional<std::pair<const DisplayViewport*, float /*offsetPx*/>>
+ findDestinationDisplayLocked(const ui::LogicalDisplayId sourceDisplayId,
+ const DisplayTopologyPosition sourceBoundary,
+ int32_t sourceCursorOffsetPx) const REQUIRES(getLock());
+
+ vec2 filterPointerMotionForAccessibilityLocked(const vec2& current, const vec2& delta,
+ const ui::LogicalDisplayId& displayId)
+ REQUIRES(getLock());
+
+ /* Topology is initialized with default-constructed value, which is an empty topology. Till we
+ * receive setDisplayTopology call.
+ * Meanwhile Choreographer will treat every display as independent disconnected display.
+ */
+ DisplayTopologyGraph mTopology GUARDED_BY(getLock());
/* This listener keeps tracks of visible privacy sensitive displays and updates the
* choreographer if there are any changes.
@@ -156,49 +196,56 @@
explicit PointerChoreographerDisplayInfoListener(PointerChoreographer* pc)
: mPointerChoreographer(pc){};
void onWindowInfosChanged(const gui::WindowInfosUpdate&) override;
- void setInitialDisplayInfos(const std::vector<gui::WindowInfo>& windowInfos);
- std::unordered_set<ui::LogicalDisplayId /*displayId*/> getPrivacySensitiveDisplays();
+ void setInitialDisplayInfosLocked(const std::vector<gui::WindowInfo>& windowInfos)
+ REQUIRES(mLock);
+ std::unordered_set<ui::LogicalDisplayId> getPrivacySensitiveDisplaysLocked()
+ REQUIRES(mLock);
void onPointerChoreographerDestroyed();
+ // This lock is also used by PointerChoreographer. See PointerChoreographer::getLock().
+ std::mutex mLock;
+
private:
- std::mutex mListenerLock;
- PointerChoreographer* mPointerChoreographer GUARDED_BY(mListenerLock);
+ PointerChoreographer* mPointerChoreographer GUARDED_BY(mLock);
std::unordered_set<ui::LogicalDisplayId /*displayId*/> mPrivacySensitiveDisplays
- GUARDED_BY(mListenerLock);
+ GUARDED_BY(mLock);
};
- sp<PointerChoreographerDisplayInfoListener> mWindowInfoListener GUARDED_BY(mLock);
using ControllerConstructor =
ConstructorDelegate<std::function<std::shared_ptr<PointerControllerInterface>()>>;
- ControllerConstructor mTouchControllerConstructor GUARDED_BY(mLock);
+ ControllerConstructor mTouchControllerConstructor GUARDED_BY(getLock());
ControllerConstructor getMouseControllerConstructor(ui::LogicalDisplayId displayId)
- REQUIRES(mLock);
+ REQUIRES(getLock());
ControllerConstructor getStylusControllerConstructor(ui::LogicalDisplayId displayId)
- REQUIRES(mLock);
-
- std::mutex mLock;
+ REQUIRES(getLock());
InputListenerInterface& mNextListener;
PointerChoreographerPolicyInterface& mPolicy;
std::map<ui::LogicalDisplayId, std::shared_ptr<PointerControllerInterface>>
- mMousePointersByDisplay GUARDED_BY(mLock);
+ mMousePointersByDisplay GUARDED_BY(getLock());
std::map<DeviceId, std::shared_ptr<PointerControllerInterface>> mTouchPointersByDevice
- GUARDED_BY(mLock);
+ GUARDED_BY(getLock());
std::map<DeviceId, std::shared_ptr<PointerControllerInterface>> mStylusPointersByDevice
- GUARDED_BY(mLock);
+ GUARDED_BY(getLock());
std::map<DeviceId, std::shared_ptr<PointerControllerInterface>> mDrawingTabletPointersByDevice
- GUARDED_BY(mLock);
+ GUARDED_BY(getLock());
- ui::LogicalDisplayId mDefaultMouseDisplayId GUARDED_BY(mLock);
- ui::LogicalDisplayId mNotifiedPointerDisplayId GUARDED_BY(mLock);
- std::vector<InputDeviceInfo> mInputDeviceInfos GUARDED_BY(mLock);
- std::set<DeviceId> mMouseDevices GUARDED_BY(mLock);
- std::vector<DisplayViewport> mViewports GUARDED_BY(mLock);
- bool mShowTouchesEnabled GUARDED_BY(mLock);
- bool mStylusPointerIconEnabled GUARDED_BY(mLock);
+ // In connected displays scenario, this tracks the latest display the cursor is at, within the
+ // DisplayTopology. By default, this will be set to topology primary display, and updated when
+ // mouse crossed to another display.
+ // In non-connected displays scenario, this will be treated as the default display cursor
+ // will be on, when mouse doesn't have associated display.
+ ui::LogicalDisplayId mCurrentMouseDisplayId GUARDED_BY(getLock());
+ ui::LogicalDisplayId mNotifiedPointerDisplayId GUARDED_BY(getLock());
+ std::vector<InputDeviceInfo> mInputDeviceInfos GUARDED_BY(getLock());
+ std::set<DeviceId> mMouseDevices GUARDED_BY(getLock());
+ std::vector<DisplayViewport> mViewports GUARDED_BY(getLock());
+ bool mShowTouchesEnabled GUARDED_BY(getLock());
+ bool mStylusPointerIconEnabled GUARDED_BY(getLock());
+ bool mPointerMotionFilterEnabled GUARDED_BY(getLock());
std::set<ui::LogicalDisplayId /*displayId*/> mDisplaysWithPointersHidden;
- ui::LogicalDisplayId mCurrentFocusedDisplay GUARDED_BY(mLock);
+ ui::LogicalDisplayId mCurrentFocusedDisplay GUARDED_BY(getLock());
protected:
using WindowListenerRegisterConsumer = std::function<std::vector<gui::WindowInfo>(
@@ -211,6 +258,10 @@
const WindowListenerUnregisterConsumer& unregisterListener);
private:
+ // WindowInfoListener object should always exist while PointerChoreographer exists, because we
+ // need to use the lock from it. But we don't always need to register the listener.
+ bool mIsWindowInfoListenerRegistered GUARDED_BY(getLock());
+ const sp<PointerChoreographerDisplayInfoListener> mWindowInfoListener;
const WindowListenerRegisterConsumer mRegisterListener;
const WindowListenerUnregisterConsumer mUnregisterListener;
};
diff --git a/services/inputflinger/PreferStylusOverTouchBlocker.cpp b/services/inputflinger/PreferStylusOverTouchBlocker.cpp
index d9d0450..6864947 100644
--- a/services/inputflinger/PreferStylusOverTouchBlocker.cpp
+++ b/services/inputflinger/PreferStylusOverTouchBlocker.cpp
@@ -216,10 +216,10 @@
std::string PreferStylusOverTouchBlocker::dump() const {
std::string out;
- out += "mActiveStyli: " + dumpSet(mActiveStyli) + "\n";
+ out += "mActiveStyli: " + dumpContainer(mActiveStyli) + "\n";
out += "mLastTouchEvents: " + dumpMap(mLastTouchEvents, constToString, dumpArgs) + "\n";
- out += "mDevicesWithMixedToolType: " + dumpSet(mDevicesWithMixedToolType) + "\n";
- out += "mCanceledDevices: " + dumpSet(mCanceledDevices) + "\n";
+ out += "mDevicesWithMixedToolType: " + dumpContainer(mDevicesWithMixedToolType) + "\n";
+ out += "mCanceledDevices: " + dumpContainer(mCanceledDevices) + "\n";
return out;
}
diff --git a/services/inputflinger/TEST_MAPPING b/services/inputflinger/TEST_MAPPING
index 10fec74..43eaf67 100644
--- a/services/inputflinger/TEST_MAPPING
+++ b/services/inputflinger/TEST_MAPPING
@@ -35,109 +35,34 @@
]
},
{
- "name": "CtsHardwareTestCases",
- "options": [
- {
- "include-filter": "android.hardware.input.cts.tests"
- },
- {
- "exclude-annotation": "androidx.test.filters.FlakyTest"
- }
- ]
+ "name": "CtsHardwareTestCases_cts_tests"
},
{
"name": "CtsInputTestCases"
},
{
- "name": "CtsViewTestCases",
- "options": [
- {
- "include-filter": "android.view.cts.input"
- }
- ]
+ "name": "CtsViewTestCases_cts_input"
},
{
- "name": "CtsViewTestCases",
- "options": [
- {
- "include-filter": "android.view.cts.HoverTest"
- },
- {
- "include-filter": "android.view.cts.MotionEventTest"
- },
- {
- "include-filter": "android.view.cts.PointerCaptureTest"
- },
- {
- "include-filter": "android.view.cts.TooltipTest"
- },
- {
- "include-filter": "android.view.cts.TouchDelegateTest"
- },
- {
- "include-filter": "android.view.cts.VerifyInputEventTest"
- },
- {
- "include-filter": "android.view.cts.ViewTest"
- },
- {
- "include-filter": "android.view.cts.ViewUnbufferedTest"
- }
- ]
+ "name": "CtsViewTestCases_input_related"
},
{
- "name": "CtsWidgetTestCases",
- "options": [
- {
- "include-filter": "android.widget.cts.NumberPickerTest"
- },
- {
- "include-filter": "android.widget.cts.SeekBarTest"
- }
- ]
+ "name": "CtsWidgetTestCases_seekbar_and_numberpicker"
},
{
- "name": "FrameworksCoreTests",
- "options": [
- {
- "include-filter": "android.hardware.input"
- }
- ]
+ "name": "FrameworksCoreTests_hardware_input"
},
{
- "name": "FrameworksCoreTests",
- "options": [
- {
- "include-filter": "android.view.VerifiedKeyEventTest"
- },
- {
- "include-filter": "android.view.VerifiedMotionEventTest"
- }
- ]
+ "name": "FrameworksCoreTests_view_verified"
},
{
- "name": "CtsAppTestCases",
- "options": [
- {
- "include-filter": "android.app.cts.ToolbarActionBarTest"
- }
- ]
+ "name": "CtsAppTestCases_cts_toolbaractionbartest"
},
{
- "name": "FrameworksServicesTests",
- "options": [
- {
- "include-filter": "com.android.server.input"
- }
- ]
+ "name": "FrameworksServicesTests_android_server_input"
},
{
- "name": "CtsSecurityTestCases",
- "options": [
- {
- "include-filter": "android.security.cts.MotionEventTest"
- }
- ]
+ "name": "CtsSecurityTestCases_cts_motioneventtest"
},
{
"name": "CtsSecurityBulletinHostTestCases",
@@ -156,12 +81,7 @@
],
"postsubmit": [
{
- "name": "CtsWindowManagerDeviceWindow",
- "options": [
- {
- "include-filter": "android.server.wm.window.WindowInputTests"
- }
- ]
+ "name": "CtsWindowManagerDeviceWindow_window_windowinputtests"
},
{
"name": "libinput_tests"
@@ -187,98 +107,31 @@
]
},
{
- "name": "CtsHardwareTestCases",
- "options": [
- {
- "include-filter": "android.hardware.input.cts.tests"
- }
- ]
+ "name": "CtsHardwareTestCases_cts_tests"
},
{
"name": "CtsInputTestCases"
},
{
- "name": "CtsViewTestCases",
- "options": [
- {
- "include-filter": "android.view.cts.input"
- }
- ]
+ "name": "CtsViewTestCases_cts_input"
},
{
- "name": "CtsViewTestCases",
- "options": [
- {
- "include-filter": "android.view.cts.HoverTest"
- },
- {
- "include-filter": "android.view.cts.MotionEventTest"
- },
- {
- "include-filter": "android.view.cts.PointerCaptureTest"
- },
- {
- "include-filter": "android.view.cts.TooltipTest"
- },
- {
- "include-filter": "android.view.cts.TouchDelegateTest"
- },
- {
- "include-filter": "android.view.cts.VerifyInputEventTest"
- },
- {
- "include-filter": "android.view.cts.ViewTest"
- },
- {
- "include-filter": "android.view.cts.ViewUnbufferedTest"
- }
- ]
+ "name": "CtsViewTestCases_input_related"
},
{
- "name": "CtsWidgetTestCases",
- "options": [
- {
- "include-filter": "android.widget.cts.NumberPickerTest"
- },
- {
- "include-filter": "android.widget.cts.SeekBarTest"
- }
- ]
+ "name": "CtsWidgetTestCases_seekbar_and_numberpicker"
},
{
- "name": "FrameworksCoreTests",
- "options": [
- {
- "include-filter": "android.view.VerifiedKeyEventTest"
- },
- {
- "include-filter": "android.view.VerifiedMotionEventTest"
- }
- ]
+ "name": "FrameworksCoreTests_view_verified"
},
{
- "name": "CtsAppTestCases",
- "options": [
- {
- "include-filter": "android.app.cts.ToolbarActionBarTest"
- }
- ]
+ "name": "CtsAppTestCases_cts_toolbaractionbartest"
},
{
- "name": "FrameworksServicesTests",
- "options": [
- {
- "include-filter": "com.android.server.input"
- }
- ]
+ "name": "FrameworksServicesTests_server_input"
},
{
- "name": "CtsSecurityTestCases",
- "options": [
- {
- "include-filter": "android.security.cts.MotionEventTest"
- }
- ]
+ "name": "CtsSecurityTestCases_cts_motioneventtest"
},
{
"name": "CtsSecurityBulletinHostTestCases",
diff --git a/services/inputflinger/UnwantedInteractionBlocker.cpp b/services/inputflinger/UnwantedInteractionBlocker.cpp
index 0e9ec91..29de635 100644
--- a/services/inputflinger/UnwantedInteractionBlocker.cpp
+++ b/services/inputflinger/UnwantedInteractionBlocker.cpp
@@ -727,7 +727,7 @@
if (!std::includes(oldSuppressedIds.begin(), oldSuppressedIds.end(),
mSuppressedPointerIds.begin(), mSuppressedPointerIds.end())) {
ALOGI("Palm detected, removing pointer ids %s after %" PRId64 "ms from %s",
- dumpSet(mSuppressedPointerIds).c_str(), ns2ms(args.eventTime - args.downTime),
+ dumpContainer(mSuppressedPointerIds).c_str(), ns2ms(args.eventTime - args.downTime),
args.dump().c_str());
}
@@ -748,7 +748,7 @@
out += "mSlotState:\n";
out += addLinePrefix(mSlotState.dump(), " ");
out += "mSuppressedPointerIds: ";
- out += dumpSet(mSuppressedPointerIds) + "\n";
+ out += dumpContainer(mSuppressedPointerIds) + "\n";
std::stringstream state;
state << *mSharedPalmState;
out += "mSharedPalmState: " + state.str() + "\n";
diff --git a/services/inputflinger/dispatcher/Android.bp b/services/inputflinger/dispatcher/Android.bp
index 8b2b843..1aa8b2b 100644
--- a/services/inputflinger/dispatcher/Android.bp
+++ b/services/inputflinger/dispatcher/Android.bp
@@ -49,8 +49,8 @@
"LatencyAggregatorWithHistograms.cpp",
"LatencyTracker.cpp",
"Monitor.cpp",
- "TouchedWindow.cpp",
"TouchState.cpp",
+ "TouchedWindow.cpp",
"trace/*.cpp",
],
}
@@ -71,9 +71,9 @@
"liblog",
"libprotobuf-cpp-lite",
"libstatslog",
- "libutils",
"libstatspull",
"libstatssocket",
+ "libutils",
"packagemanager_aidl-cpp",
"server_configurable_flags",
],
diff --git a/services/inputflinger/dispatcher/EventLogTags.logtags b/services/inputflinger/dispatcher/EventLogTags.logtags
index 2c5fe21..4dd6073 100644
--- a/services/inputflinger/dispatcher/EventLogTags.logtags
+++ b/services/inputflinger/dispatcher/EventLogTags.logtags
@@ -31,7 +31,7 @@
# 6: Percent
# Default value for data of type int/long is 2 (bytes).
#
-# See system/core/logcat/event.logtags for the master copy of the tags.
+# See system/logging/logcat/event.logtags for the master copy of the tags.
# 62000 - 62199 reserved for inputflinger
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 602904f..ef50fc0 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -32,6 +32,7 @@
#include <gui/SurfaceComposerClient.h>
#endif
#include <input/InputDevice.h>
+#include <input/InputFlags.h>
#include <input/PrintTools.h>
#include <input/TraceTools.h>
#include <openssl/mem.h>
@@ -46,6 +47,7 @@
#include <ctime>
#include <queue>
#include <sstream>
+#include <variant>
#include "../InputDeviceMetricsSource.h"
@@ -417,7 +419,7 @@
if (inputTarget.useDefaultPointerTransform() && !zeroCoords) {
const ui::Transform& transform = inputTarget.getDefaultPointerTransform();
return std::make_unique<DispatchEntry>(eventEntry, inputTargetFlags, transform,
- inputTarget.displayTransform,
+ inputTarget.rawTransform,
inputTarget.globalScaleFactor, uid, vsyncId,
windowId);
}
@@ -438,7 +440,7 @@
transform =
&inputTarget.getTransformForPointer(firstMarkedBit(inputTarget.getPointerIds()));
const ui::Transform inverseTransform = transform->inverse();
- displayTransform = &inputTarget.displayTransform;
+ displayTransform = &inputTarget.rawTransform;
// Iterate through all pointers in the event to normalize against the first.
for (size_t i = 0; i < motionEntry.getPointerCount(); i++) {
@@ -787,62 +789,20 @@
});
}
-/**
- * In general, touch should be always split between windows. Some exceptions:
- * 1. Don't split touch if all of the below is true:
- * (a) we have an active pointer down *and*
- * (b) a new pointer is going down that's from the same device *and*
- * (c) the window that's receiving the current pointer does not support split touch.
- * 2. Don't split mouse events
- */
-bool shouldSplitTouch(const TouchState& touchState, const MotionEntry& entry) {
- if (isFromSource(entry.source, AINPUT_SOURCE_MOUSE)) {
- // We should never split mouse events
- return false;
- }
- for (const TouchedWindow& touchedWindow : touchState.windows) {
- if (touchedWindow.windowHandle->getInfo()->isSpy()) {
- // Spy windows should not affect whether or not touch is split.
- continue;
- }
- if (touchedWindow.windowHandle->getInfo()->supportsSplitTouch()) {
- continue;
- }
- if (touchedWindow.windowHandle->getInfo()->inputConfig.test(
- gui::WindowInfo::InputConfig::IS_WALLPAPER)) {
- // Wallpaper window should not affect whether or not touch is split
- continue;
- }
-
- if (touchedWindow.hasTouchingPointers(entry.deviceId)) {
- return false;
- }
- }
- return true;
-}
-
-/**
- * Return true if stylus is currently down anywhere on the specified display, and false otherwise.
- */
-bool isStylusActiveInDisplay(ui::LogicalDisplayId displayId,
- const std::unordered_map<ui::LogicalDisplayId /*displayId*/,
- TouchState>& touchStatesByDisplay) {
- const auto it = touchStatesByDisplay.find(displayId);
- if (it == touchStatesByDisplay.end()) {
- return false;
- }
- const TouchState& state = it->second;
- return state.hasActiveStylus();
+bool shouldSplitTouch(int32_t source) {
+ // We should never split mouse events. This is because the events that are produced by touchpad
+ // are sent to InputDispatcher as two fingers (for example, pinch zoom), but they need to be
+ // dispatched to the same window. In those cases, the behaviour is also slightly different from
+ // default because the events should be sent to the cursor position rather than the x,y values
+ // of each of the fingers.
+ // The "normal" (uncaptured) events produced by touchpad and by mouse have SOURCE_MOUSE.
+ return !isFromSource(source, AINPUT_SOURCE_MOUSE);
}
Result<void> validateWindowInfosUpdate(const gui::WindowInfosUpdate& update) {
- struct HashFunction {
- size_t operator()(const WindowInfo& info) const { return info.id; }
- };
-
- std::unordered_set<WindowInfo, HashFunction> windowSet;
+ std::unordered_set<int32_t> windowIds;
for (const WindowInfo& info : update.windowInfos) {
- const auto [_, inserted] = windowSet.insert(info);
+ const auto [_, inserted] = windowIds.insert(info.id);
if (!inserted) {
return Error() << "Duplicate entry for " << info;
}
@@ -928,6 +888,38 @@
std::forward<InputEventInjectionResult>(e));
}
+InputTarget createInputTarget(const std::shared_ptr<Connection>& connection,
+ const sp<android::gui::WindowInfoHandle>& windowHandle,
+ InputTarget::DispatchMode dispatchMode,
+ ftl::Flags<InputTarget::Flags> targetFlags,
+ const ui::Transform& rawTransform,
+ std::optional<nsecs_t> firstDownTimeInTarget) {
+ LOG_ALWAYS_FATAL_IF(connection == nullptr);
+ InputTarget inputTarget{connection};
+ inputTarget.windowHandle = windowHandle;
+ inputTarget.dispatchMode = dispatchMode;
+ inputTarget.flags = targetFlags;
+ inputTarget.globalScaleFactor = windowHandle->getInfo()->globalScaleFactor;
+ inputTarget.rawTransform = rawTransform;
+ inputTarget.firstDownTimeInTarget = firstDownTimeInTarget;
+ return inputTarget;
+}
+
+std::string dumpWindowForTouchOcclusion(const WindowInfo& info, bool isTouchedWindow) {
+ return StringPrintf(INDENT2 "* %spackage=%s/%s, id=%" PRId32 ", mode=%s, alpha=%.2f, "
+ "frame=[%" PRId32 ",%" PRId32 "][%" PRId32 ",%" PRId32
+ "], touchableRegion=%s, window={%s}, inputConfig={%s}, "
+ "hasToken=%s, applicationInfo.name=%s, applicationInfo.token=%s\n",
+ isTouchedWindow ? "[TOUCHED] " : "", info.packageName.c_str(),
+ info.ownerUid.toString().c_str(), info.id,
+ toString(info.touchOcclusionMode).c_str(), info.alpha, info.frame.left,
+ info.frame.top, info.frame.right, info.frame.bottom,
+ dumpRegion(info.touchableRegion).c_str(), info.name.c_str(),
+ info.inputConfig.string().c_str(), toString(info.token != nullptr),
+ info.applicationInfo.name.c_str(),
+ binderToString(info.applicationInfo.token).c_str());
+}
+
} // namespace
// --- InputDispatcher ---
@@ -938,16 +930,18 @@
InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy,
std::unique_ptr<trace::InputTracingBackendInterface> traceBackend)
: mPolicy(policy),
+ mLooper(sp<Looper>::make(false)),
mPendingEvent(nullptr),
mLastDropReason(DropReason::NOT_DROPPED),
mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER),
mMinTimeBetweenUserActivityPokes(DEFAULT_USER_ACTIVITY_POKE_INTERVAL),
+ mConnectionManager(mLooper),
+ mTouchStates(mWindowInfos, mConnectionManager),
mNextUnblockedEvent(nullptr),
mMonitorDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT),
mDispatchEnabled(false),
mDispatchFrozen(false),
mInputFilterEnabled(false),
- mMaximumObscuringOpacityForTouch(1.0f),
mFocusedDisplayId(ui::LogicalDisplayId::DEFAULT),
mWindowTokenWithPointerCapture(nullptr),
mAwaitedApplicationDisplayId(ui::LogicalDisplayId::INVALID),
@@ -958,7 +952,6 @@
: std::move(std::unique_ptr<InputEventTimelineProcessor>(
new LatencyAggregator()))),
mLatencyTracker(*mInputEventTimelineProcessor) {
- mLooper = sp<Looper>::make(false);
mReporter = createInputReporter();
mWindowInfoListener = sp<DispatcherWindowListener>::make(*this);
@@ -980,12 +973,10 @@
resetKeyRepeatLocked();
releasePendingEventLocked();
drainInboundQueueLocked();
+#if defined(__ANDROID__)
+ SurfaceComposerClient::getDefault()->removeWindowInfosListener(mWindowInfoListener);
+#endif
mCommandQueue.clear();
-
- while (!mConnectionsByToken.empty()) {
- std::shared_ptr<Connection> connection = mConnectionsByToken.begin()->second;
- removeInputChannelLocked(connection->getToken(), /*notify=*/false);
- }
}
status_t InputDispatcher::start() {
@@ -1102,9 +1093,13 @@
}
// If we reached here, we have an unresponsive connection.
- std::shared_ptr<Connection> connection = getConnectionLocked(mAnrTracker.firstToken());
+ std::shared_ptr<Connection> connection =
+ mConnectionManager.getConnection(mAnrTracker.firstToken());
if (connection == nullptr) {
ALOGE("Could not find connection for entry %" PRId64, mAnrTracker.firstTimeout());
+ // As we no longer have entry for this connection, remove it form Anr tracker to prevent
+ // samme error being logged multiple times.
+ mAnrTracker.eraseToken(mAnrTracker.firstToken());
return nextAnrCheck;
}
connection->responsive = false;
@@ -1132,7 +1127,7 @@
if (connection->monitor) {
return mMonitorDispatchingTimeout;
}
- const sp<WindowInfoHandle> window = getWindowHandleLocked(connection->getToken());
+ const sp<WindowInfoHandle> window = mWindowInfos.findWindowHandle(connection->getToken());
if (window != nullptr) {
return window->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
}
@@ -1151,9 +1146,7 @@
// If dispatching is frozen, do not process timeouts or try to deliver any new events.
if (mDispatchFrozen) {
- if (DEBUG_FOCUS) {
- ALOGD("Dispatch frozen. Waiting some more.");
- }
+ LOG_IF(INFO, DEBUG_FOCUS) << "Dispatch frozen. Waiting some more.";
return;
}
@@ -1263,13 +1256,9 @@
if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *motionEntry)) {
// The event is stale. However, only drop stale events if there isn't an ongoing
// gesture. That would allow us to complete the processing of the current stroke.
- const auto touchStateIt = mTouchStatesByDisplay.find(motionEntry->displayId);
- if (touchStateIt != mTouchStatesByDisplay.end()) {
- const TouchState& touchState = touchStateIt->second;
- if (!touchState.hasTouchingPointers(motionEntry->deviceId) &&
- !touchState.hasHoveringPointers(motionEntry->deviceId)) {
- dropReason = DropReason::STALE;
- }
+ if (!mTouchStates.hasTouchingOrHoveringPointers(motionEntry->displayId,
+ motionEntry->deviceId)) {
+ dropReason = DropReason::STALE;
}
}
if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
@@ -1337,7 +1326,7 @@
const bool isStylus = isPointerFromStylus(motionEntry, /*pointerIndex=*/0);
sp<WindowInfoHandle> touchedWindowHandle =
- findTouchedWindowAtLocked(displayId, x, y, isStylus);
+ mWindowInfos.findTouchedWindowAt(displayId, x, y, isStylus);
if (touchedWindowHandle != nullptr &&
touchedWindowHandle->getApplicationToken() !=
mAwaitedFocusedApplication->getApplicationToken()) {
@@ -1350,10 +1339,11 @@
// Alternatively, maybe there's a spy window that could handle this event.
const std::vector<sp<WindowInfoHandle>> touchedSpies =
- findTouchedSpyWindowsAtLocked(displayId, x, y, isStylus, motionEntry.deviceId);
+ findTouchedSpyWindowsAt(displayId, x, y, isStylus, motionEntry.deviceId,
+ mWindowInfos);
for (const auto& windowHandle : touchedSpies) {
const std::shared_ptr<Connection> connection =
- getConnectionLocked(windowHandle->getToken());
+ mConnectionManager.getConnection(windowHandle->getToken());
if (connection != nullptr && connection->responsive) {
// This spy window could take more input. Drop all events preceding this
// event, so that the spy window can get a chance to receive the stream.
@@ -1456,34 +1446,34 @@
}
}
-sp<WindowInfoHandle> InputDispatcher::findTouchedWindowAtLocked(ui::LogicalDisplayId displayId,
- float x, float y, bool isStylus,
- bool ignoreDragWindow) const {
+sp<WindowInfoHandle> InputDispatcher::DispatcherWindowInfo::findTouchedWindowAt(
+ ui::LogicalDisplayId displayId, float x, float y, bool isStylus,
+ const sp<android::gui::WindowInfoHandle> ignoreWindow) const {
// Traverse windows from front to back to find touched window.
- const auto& windowHandles = getWindowHandlesLocked(displayId);
+ const auto& windowHandles = getWindowHandlesForDisplay(displayId);
for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {
- if (ignoreDragWindow && haveSameToken(windowHandle, mDragState->dragWindow)) {
+ if (ignoreWindow && haveSameToken(windowHandle, ignoreWindow)) {
continue;
}
const WindowInfo& info = *windowHandle->getInfo();
if (!info.isSpy() &&
- windowAcceptsTouchAt(info, displayId, x, y, isStylus, getTransformLocked(displayId))) {
+ windowAcceptsTouchAt(info, displayId, x, y, isStylus, getDisplayTransform(displayId))) {
return windowHandle;
}
}
return nullptr;
}
-std::vector<InputTarget> InputDispatcher::findOutsideTargetsLocked(
- ui::LogicalDisplayId displayId, const sp<WindowInfoHandle>& touchedWindow,
- int32_t pointerId) const {
+std::vector<InputTarget> InputDispatcher::DispatcherTouchState::findOutsideTargets(
+ ui::LogicalDisplayId displayId, const sp<gui::WindowInfoHandle>& touchedWindow,
+ int32_t pointerId, std::function<void()> dump) {
if (touchedWindow == nullptr) {
return {};
}
// Traverse windows from front to back until we encounter the touched window.
std::vector<InputTarget> outsideTargets;
- const auto& windowHandles = getWindowHandlesLocked(displayId);
+ const auto& windowHandles = mWindowInfos.getWindowHandlesForDisplay(displayId);
for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {
if (windowHandle == touchedWindow) {
// Stop iterating once we found a touched window. Any WATCH_OUTSIDE_TOUCH window
@@ -1495,36 +1485,27 @@
if (info.inputConfig.test(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH)) {
std::bitset<MAX_POINTER_ID + 1> pointerIds;
pointerIds.set(pointerId);
- addPointerWindowTargetLocked(windowHandle, InputTarget::DispatchMode::OUTSIDE,
- ftl::Flags<InputTarget::Flags>(), pointerIds,
- /*firstDownTimeInTarget=*/std::nullopt, outsideTargets);
+ addPointerWindowTarget(windowHandle, InputTarget::DispatchMode::OUTSIDE,
+ ftl::Flags<InputTarget::Flags>(), pointerIds,
+ /*firstDownTimeInTarget=*/std::nullopt,
+ /*pointerDisplayId=*/std::nullopt, dump, outsideTargets);
}
}
return outsideTargets;
}
-std::vector<sp<WindowInfoHandle>> InputDispatcher::findTouchedSpyWindowsAtLocked(
- ui::LogicalDisplayId displayId, float x, float y, bool isStylus, DeviceId deviceId) const {
+std::vector<sp<WindowInfoHandle>> InputDispatcher::findTouchedSpyWindowsAt(
+ ui::LogicalDisplayId displayId, float x, float y, bool isStylus, DeviceId deviceId,
+ const DispatcherWindowInfo& windowInfos) {
// Traverse windows from front to back and gather the touched spy windows.
std::vector<sp<WindowInfoHandle>> spyWindows;
- const auto& windowHandles = getWindowHandlesLocked(displayId);
+ const ui::Transform displayTransform = windowInfos.getDisplayTransform(displayId);
+ const auto& windowHandles = windowInfos.getWindowHandlesForDisplay(displayId);
for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {
const WindowInfo& info = *windowHandle->getInfo();
- if (!windowAcceptsTouchAt(info, displayId, x, y, isStylus, getTransformLocked(displayId))) {
- // Generally, we would skip any pointer that's outside of the window. However, if the
- // spy prevents splitting, and already has some of the pointers from this device, then
- // it should get more pointers from the same device, even if they are outside of that
- // window
- if (info.supportsSplitTouch()) {
- continue;
- }
-
- // We know that split touch is not supported. Skip this window only if it doesn't have
- // any touching pointers for this device already.
- if (!windowHasTouchingPointersLocked(windowHandle, deviceId)) {
- continue;
- }
- // If it already has pointers down for this device, then give it this pointer, too.
+ if (!windowAcceptsTouchAt(info, displayId, x, y, isStylus, displayTransform)) {
+ // Skip if the pointer is outside of the window.
+ continue;
}
if (!info.isSpy()) {
// The first touched non-spy window was found, so return the spy windows touched so far.
@@ -1539,9 +1520,7 @@
const char* reason;
switch (dropReason) {
case DropReason::POLICY:
- if (debugInboundEventDetails()) {
- ALOGD("Dropped event because policy consumed it.");
- }
+ LOG_IF(INFO, debugInboundEventDetails()) << "Dropped event because policy consumed it.";
reason = "inbound event was dropped because the policy consumed it";
break;
case DropReason::DISABLED:
@@ -1655,9 +1634,7 @@
void InputDispatcher::releaseInboundEventLocked(std::shared_ptr<const EventEntry> entry) {
const std::shared_ptr<InjectionState>& injectionState = entry->injectionState;
if (injectionState && injectionState->injectionResult == InputEventInjectionResult::PENDING) {
- if (DEBUG_DISPATCH_CYCLE) {
- ALOGD("Injected inbound event was dropped.");
- }
+ LOG_IF(INFO, DEBUG_DISPATCH_CYCLE) << "Injected inbound event was dropped.";
setInjectionResult(*entry, InputEventInjectionResult::FAILED);
}
if (entry == mNextUnblockedEvent) {
@@ -1697,10 +1674,9 @@
bool InputDispatcher::dispatchDeviceResetLocked(nsecs_t currentTime,
const DeviceResetEntry& entry) {
- if (DEBUG_OUTBOUND_EVENT_DETAILS) {
- ALOGD("dispatchDeviceReset - eventTime=%" PRId64 ", deviceId=%d", entry.eventTime,
- entry.deviceId);
- }
+ LOG_IF(INFO, DEBUG_OUTBOUND_EVENT_DETAILS)
+ << "dispatchDeviceReset - eventTime=" << entry.eventTime
+ << ", deviceId=" << entry.deviceId;
// Reset key repeating in case a keyboard device was disabled or enabled.
if (mKeyRepeatState.lastKeyEntry && mKeyRepeatState.lastKeyEntry->deviceId == entry.deviceId) {
@@ -1714,9 +1690,7 @@
synthesizeCancelationEventsForAllConnectionsLocked(options);
// Remove all active pointers from this device
- for (auto& [_, touchState] : mTouchStatesByDisplay) {
- touchState.removeAllPointersForDevice(entry.deviceId);
- }
+ mTouchStates.removeAllPointersForDevice(entry.deviceId);
return true;
}
@@ -1746,7 +1720,8 @@
void InputDispatcher::dispatchFocusLocked(nsecs_t currentTime,
std::shared_ptr<const FocusEntry> entry) {
- std::shared_ptr<Connection> connection = getConnectionLocked(entry->connectionToken);
+ std::shared_ptr<Connection> connection =
+ mConnectionManager.getConnection(entry->connectionToken);
if (connection == nullptr) {
return; // Connection has gone away
}
@@ -1814,7 +1789,7 @@
}
}
- auto connection = getConnectionLocked(token);
+ auto connection = mConnectionManager.getConnection(token);
if (connection == nullptr) {
// Window has gone away, clean up Pointer Capture state.
mWindowTokenWithPointerCapture = nullptr;
@@ -1832,7 +1807,7 @@
void InputDispatcher::dispatchTouchModeChangeLocked(
nsecs_t currentTime, const std::shared_ptr<const TouchModeEntry>& entry) {
const std::vector<sp<WindowInfoHandle>>& windowHandles =
- getWindowHandlesLocked(entry->displayId);
+ mWindowInfos.getWindowHandlesForDisplay(entry->displayId);
if (windowHandles.empty()) {
return;
}
@@ -1853,7 +1828,7 @@
if (token == nullptr) {
continue;
}
- std::shared_ptr<Connection> connection = getConnectionLocked(token);
+ std::shared_ptr<Connection> connection = mConnectionManager.getConnection(token);
if (connection == nullptr) {
continue; // Connection has gone away
}
@@ -1893,9 +1868,8 @@
} else if (entry->action == AKEY_EVENT_ACTION_UP && mKeyRepeatState.lastKeyEntry &&
mKeyRepeatState.lastKeyEntry->deviceId != entry->deviceId) {
// The key on device 'deviceId' is still down, do not stop key repeat
- if (debugInboundEventDetails()) {
- ALOGD("deviceId=%d got KEY_UP as stale", entry->deviceId);
- }
+ LOG_IF(INFO, debugInboundEventDetails())
+ << "deviceId=" << entry->deviceId << " got KEY_UP as stale";
} else if (!entry->syntheticRepeat) {
resetKeyRepeatLocked();
}
@@ -1992,25 +1966,24 @@
}
void InputDispatcher::logOutboundKeyDetails(const char* prefix, const KeyEntry& entry) {
- if (DEBUG_OUTBOUND_EVENT_DETAILS) {
- ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%s, "
- "policyFlags=0x%x, action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, "
- "metaState=0x%x, repeatCount=%d, downTime=%" PRId64,
- prefix, entry.eventTime, entry.deviceId, entry.source,
- entry.displayId.toString().c_str(), entry.policyFlags, entry.action, entry.flags,
- entry.keyCode, entry.scanCode, entry.metaState, entry.repeatCount, entry.downTime);
- }
+ LOG_IF(INFO, DEBUG_OUTBOUND_EVENT_DETAILS)
+ << prefix << "eventTime=" << entry.eventTime << ", deviceId=" << entry.deviceId
+ << ", source=0x" << std::hex << entry.source
+ << ", displayId=" << entry.displayId.toString() << ", policyFlags=0x"
+ << entry.policyFlags << ", action=0x" << entry.action << ", flags=0x" << entry.flags
+ << ", keyCode=0x" << entry.keyCode << ", scanCode=0x" << entry.scanCode
+ << ", metaState=0x" << entry.metaState << ", repeatCount=" << std::dec
+ << entry.repeatCount << ", downTime=" << entry.downTime;
}
void InputDispatcher::dispatchSensorLocked(nsecs_t currentTime,
const std::shared_ptr<const SensorEntry>& entry,
DropReason* dropReason, nsecs_t& nextWakeupTime) {
- if (DEBUG_OUTBOUND_EVENT_DETAILS) {
- ALOGD("notifySensorEvent eventTime=%" PRId64 ", hwTimestamp=%" PRId64 ", deviceId=%d, "
- "source=0x%x, sensorType=%s",
- entry->eventTime, entry->hwTimestamp, entry->deviceId, entry->source,
- ftl::enum_string(entry->sensorType).c_str());
- }
+ LOG_IF(INFO, DEBUG_OUTBOUND_EVENT_DETAILS)
+ << "notifySensorEvent eventTime=" << entry->eventTime
+ << ", hwTimestamp=" << entry->hwTimestamp << ", deviceId=" << entry->deviceId
+ << ", source=0x" << std::hex << entry->source << std::dec
+ << ", sensorType=" << ftl::enum_string(entry->sensorType);
auto command = [this, entry]() REQUIRES(mLock) {
scoped_unlock unlock(mLock);
@@ -2024,10 +1997,9 @@
}
bool InputDispatcher::flushSensor(int deviceId, InputDeviceSensorType sensorType) {
- if (DEBUG_OUTBOUND_EVENT_DETAILS) {
- ALOGD("flushSensor deviceId=%d, sensorType=%s", deviceId,
- ftl::enum_string(sensorType).c_str());
- }
+ LOG_IF(INFO, DEBUG_OUTBOUND_EVENT_DETAILS)
+ << "flushSensor deviceId=" << deviceId
+ << ", sensorType=" << ftl::enum_string(sensorType).c_str();
{ // acquire lock
std::scoped_lock _l(mLock);
@@ -2077,7 +2049,15 @@
}
Result<std::vector<InputTarget>, InputEventInjectionResult> result =
- findTouchedWindowTargetsLocked(currentTime, *entry);
+ mTouchStates
+ .findTouchedWindowTargets(currentTime, *entry,
+ mDragState ? mDragState->dragWindow : nullptr,
+ std::bind_front(&InputDispatcher::
+ addDragEventLocked,
+ this),
+ std::bind_front(&InputDispatcher::
+ logDispatchStateLocked,
+ this));
if (result.ok()) {
inputTargets = std::move(*result);
@@ -2146,7 +2126,8 @@
void InputDispatcher::dispatchDragLocked(nsecs_t currentTime,
std::shared_ptr<const DragEntry> entry) {
- std::shared_ptr<Connection> connection = getConnectionLocked(entry->connectionToken);
+ std::shared_ptr<Connection> connection =
+ mConnectionManager.getConnection(entry->connectionToken);
if (connection == nullptr) {
return; // Connection has gone away
}
@@ -2187,9 +2168,7 @@
std::shared_ptr<const EventEntry> eventEntry,
const std::vector<InputTarget>& inputTargets) {
ATRACE_CALL();
- if (DEBUG_DISPATCH_CYCLE) {
- ALOGD("dispatchEventToCurrentInputTargets");
- }
+ LOG_IF(INFO, DEBUG_DISPATCH_CYCLE) << "dispatchEventToCurrentInputTargets";
processInteractionsLocked(*eventEntry, inputTargets);
@@ -2220,7 +2199,7 @@
sp<WindowInfoHandle> windowHandle;
if (!connection->monitor) {
- windowHandle = getWindowHandleLocked(connection->getToken());
+ windowHandle = mWindowInfos.findWindowHandle(connection->getToken());
if (windowHandle == nullptr) {
// The window that is receiving this ANR was removed, so there is no need to generate
// cancellations, because the cancellations would have already been generated when
@@ -2232,9 +2211,7 @@
}
void InputDispatcher::resetNoFocusedWindowTimeoutLocked() {
- if (DEBUG_FOCUS) {
- ALOGD("Resetting ANR timeouts.");
- }
+ LOG_IF(INFO, DEBUG_FOCUS) << "Resetting ANR timeouts.";
// Reset input target wait timeout.
mNoFocusedWindowTimeoutTime = std::nullopt;
@@ -2321,7 +2298,8 @@
}
// Drop key events if requested by input feature
- if (focusedWindowHandle != nullptr && shouldDropInput(entry, focusedWindowHandle)) {
+ if (focusedWindowHandle != nullptr &&
+ shouldDropInput(entry, focusedWindowHandle, mWindowInfos)) {
return injectionError(InputEventInjectionResult::FAILED);
}
@@ -2390,28 +2368,11 @@
return focusedWindowHandle;
}
-/**
- * Given a list of monitors, remove the ones we cannot find a connection for, and the ones
- * that are currently unresponsive.
- */
-std::vector<Monitor> InputDispatcher::selectResponsiveMonitorsLocked(
- const std::vector<Monitor>& monitors) const {
- std::vector<Monitor> responsiveMonitors;
- std::copy_if(monitors.begin(), monitors.end(), std::back_inserter(responsiveMonitors),
- [](const Monitor& monitor) REQUIRES(mLock) {
- std::shared_ptr<Connection> connection = monitor.connection;
- if (!connection->responsive) {
- ALOGW("Unresponsive monitor %s will not get the new gesture",
- connection->getInputChannelName().c_str());
- return false;
- }
- return true;
- });
- return responsiveMonitors;
-}
-
-base::Result<std::vector<InputTarget>, android::os::InputEventInjectionResult>
-InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry& entry) {
+base::Result<std::vector<InputTarget>, os::InputEventInjectionResult>
+InputDispatcher::DispatcherTouchState::findTouchedWindowTargets(
+ nsecs_t currentTime, const MotionEntry& entry,
+ const sp<android::gui::WindowInfoHandle> dragWindow,
+ std::function<void(const MotionEntry&)> addDragEvent, std::function<void()> dump) {
ATRACE_CALL();
std::vector<InputTarget> targets;
@@ -2422,16 +2383,15 @@
const int32_t maskedAction = MotionEvent::getActionMasked(action);
// Copy current touch state into tempTouchState.
- // This state will be used to update mTouchStatesByDisplay at the end of this function.
+ // This state will be used to update saved touch state at the end of this function.
// If no state for the specified display exists, then our initial state will be empty.
- const TouchState* oldState = nullptr;
+ const TouchState* oldState = getTouchStateForMotionEntry(entry);
TouchState tempTouchState;
- if (const auto it = mTouchStatesByDisplay.find(displayId); it != mTouchStatesByDisplay.end()) {
- oldState = &(it->second);
+ if (oldState != nullptr) {
tempTouchState = *oldState;
}
- bool isSplit = shouldSplitTouch(tempTouchState, entry);
+ const bool isSplit = shouldSplitTouch(entry.source);
const bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE ||
maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
@@ -2444,11 +2404,6 @@
const bool newGesture = isDown || maskedAction == AMOTION_EVENT_ACTION_SCROLL ||
maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE;
- const bool isFromMouse = isFromSource(entry.source, AINPUT_SOURCE_MOUSE);
-
- if (newGesture) {
- isSplit = false;
- }
if (isDown && tempTouchState.hasHoveringPointers(entry.deviceId)) {
// Compatibility behaviour: ACTION_DOWN causes HOVER_EXIT to get generated.
@@ -2476,25 +2431,14 @@
// be a pointer that would generate ACTION_DOWN, *and* touch should not already be down.
const bool isStylus = isPointerFromStylus(entry, pointerIndex);
sp<WindowInfoHandle> newTouchedWindowHandle =
- findTouchedWindowAtLocked(displayId, x, y, isStylus);
+ mWindowInfos.findTouchedWindowAt(displayId, x, y, isStylus);
if (isDown) {
- targets += findOutsideTargetsLocked(displayId, newTouchedWindowHandle, pointer.id);
+ targets += findOutsideTargets(displayId, newTouchedWindowHandle, pointer.id, dump);
}
LOG_IF(INFO, newTouchedWindowHandle == nullptr)
<< "No new touched window at (" << std::format("{:.1f}, {:.1f}", x, y)
<< ") in display " << displayId;
- // Handle the case where we did not find a window.
- if (!input_flags::split_all_touches()) {
- // If we are force splitting all touches, then touches outside of the window should
- // be dropped, even if this device already has pointers down in another window.
- if (newTouchedWindowHandle == nullptr) {
- // Try to assign the pointer to the first foreground window we find, if there is
- // one.
- newTouchedWindowHandle =
- tempTouchState.getFirstForegroundWindowHandle(entry.deviceId);
- }
- }
// Verify targeted injection.
if (const auto err = verifyTargetedInjection(newTouchedWindowHandle, entry); err) {
@@ -2502,27 +2446,8 @@
return injectionError(InputEventInjectionResult::TARGET_MISMATCH);
}
- // Figure out whether splitting will be allowed for this window.
- if (newTouchedWindowHandle != nullptr) {
- if (newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
- // New window supports splitting, but we should never split mouse events.
- isSplit = !isFromMouse;
- } else if (isSplit) {
- // New window does not support splitting but we have already split events.
- // Ignore the new window.
- LOG(INFO) << "Skipping " << newTouchedWindowHandle->getName()
- << " because it doesn't support split touch";
- newTouchedWindowHandle = nullptr;
- }
- } else {
- // No window is touched, so set split to true. This will allow the next pointer down to
- // be delivered to a new window which supports split touch. Pointers from a mouse device
- // should never be split.
- isSplit = !isFromMouse;
- }
-
std::vector<sp<WindowInfoHandle>> newTouchedWindows =
- findTouchedSpyWindowsAtLocked(displayId, x, y, isStylus, entry.deviceId);
+ findTouchedSpyWindowsAt(displayId, x, y, isStylus, entry.deviceId, mWindowInfos);
if (newTouchedWindowHandle != nullptr) {
// Process the foreground window first so that it is the first to receive the event.
newTouchedWindows.insert(newTouchedWindows.begin(), newTouchedWindowHandle);
@@ -2535,7 +2460,7 @@
}
for (const sp<WindowInfoHandle>& windowHandle : newTouchedWindows) {
- if (!canWindowReceiveMotionLocked(windowHandle, entry)) {
+ if (!canWindowReceiveMotion(windowHandle, entry)) {
continue;
}
@@ -2546,21 +2471,8 @@
}
// Set target flags.
- ftl::Flags<InputTarget::Flags> targetFlags;
-
- if (canReceiveForegroundTouches(*windowHandle->getInfo())) {
- // There should only be one touched window that can be "foreground" for the pointer.
- targetFlags |= InputTarget::Flags::FOREGROUND;
- }
-
- if (isSplit) {
- targetFlags |= InputTarget::Flags::SPLIT;
- }
- if (isWindowObscuredAtPointLocked(windowHandle, x, y)) {
- targetFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED;
- } else if (isWindowObscuredLocked(windowHandle)) {
- targetFlags |= InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
- }
+ ftl::Flags<InputTarget::Flags> targetFlags =
+ getTargetFlags(windowHandle, {x, y}, isSplit);
// Update the temporary touch state.
@@ -2578,7 +2490,7 @@
if (!addResult.ok()) {
LOG(ERROR) << "Error while processing " << entry << " for "
<< windowHandle->getName();
- logDispatchStateLocked();
+ dump();
}
// If this is the pointer going down and the touched window has a wallpaper
// then also add the touched wallpaper windows so they are locked in for the
@@ -2589,7 +2501,8 @@
if (isDownOrPointerDown && targetFlags.test(InputTarget::Flags::FOREGROUND) &&
windowHandle->getInfo()->inputConfig.test(
gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
- sp<WindowInfoHandle> wallpaper = findWallpaperWindowBelow(windowHandle);
+ sp<WindowInfoHandle> wallpaper =
+ mWindowInfos.findWallpaperWindowBelow(windowHandle);
if (wallpaper != nullptr) {
ftl::Flags<InputTarget::Flags> wallpaperFlags =
InputTarget::Flags::WINDOW_IS_OBSCURED |
@@ -2627,11 +2540,10 @@
// If the pointer is not currently down, then ignore the event.
if (!tempTouchState.isDown(entry.deviceId) &&
maskedAction != AMOTION_EVENT_ACTION_HOVER_EXIT) {
- if (DEBUG_DROPPED_EVENTS_VERBOSE) {
- LOG(INFO) << "Dropping event because the pointer for device " << entry.deviceId
- << " is not down or we previously dropped the pointer down event in "
- << "display " << displayId << ": " << entry.getDescription();
- }
+ LOG_IF(INFO, DEBUG_DROPPED_EVENTS_VERBOSE)
+ << "Dropping event because the pointer for device " << entry.deviceId
+ << " is not down or we previously dropped the pointer down event in display "
+ << displayId << ": " << entry.getDescription();
return injectionError(InputEventInjectionResult::FAILED);
}
@@ -2648,7 +2560,7 @@
tempTouchState.removeHoveringPointer(entry.deviceId, pointerId);
}
- addDragEventLocked(entry);
+ addDragEvent(entry);
// Check whether touches should slip outside of the current foreground window.
if (maskedAction == AMOTION_EVENT_ACTION_MOVE && entry.getPointerCount() == 1 &&
@@ -2659,7 +2571,7 @@
tempTouchState.getFirstForegroundWindowHandle(entry.deviceId);
LOG_ALWAYS_FATAL_IF(oldTouchedWindowHandle == nullptr);
sp<WindowInfoHandle> newTouchedWindowHandle =
- findTouchedWindowAtLocked(displayId, x, y, isStylus);
+ mWindowInfos.findTouchedWindowAt(displayId, x, y, isStylus);
// Verify targeted injection.
if (const auto err = verifyTargetedInjection(newTouchedWindowHandle, entry); err) {
@@ -2669,7 +2581,7 @@
// Do not slide events to the window which can not receive motion event
if (newTouchedWindowHandle != nullptr &&
- !canWindowReceiveMotionLocked(newTouchedWindowHandle, entry)) {
+ !canWindowReceiveMotion(newTouchedWindowHandle, entry)) {
newTouchedWindowHandle = nullptr;
}
@@ -2686,29 +2598,16 @@
const TouchedWindow& touchedWindow =
tempTouchState.getTouchedWindow(oldTouchedWindowHandle);
- addPointerWindowTargetLocked(oldTouchedWindowHandle,
- InputTarget::DispatchMode::SLIPPERY_EXIT,
- ftl::Flags<InputTarget::Flags>(), pointerIds,
- touchedWindow.getDownTimeInTarget(entry.deviceId),
- targets);
+ addPointerWindowTarget(oldTouchedWindowHandle,
+ InputTarget::DispatchMode::SLIPPERY_EXIT,
+ ftl::Flags<InputTarget::Flags>(), pointerIds,
+ touchedWindow.getDownTimeInTarget(entry.deviceId),
+ /*pointerDisplayId=*/std::nullopt, dump, targets);
// Make a slippery entrance into the new window.
- if (newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
- isSplit = !isFromMouse;
- }
- ftl::Flags<InputTarget::Flags> targetFlags;
- if (canReceiveForegroundTouches(*newTouchedWindowHandle->getInfo())) {
- targetFlags |= InputTarget::Flags::FOREGROUND;
- }
- if (isSplit) {
- targetFlags |= InputTarget::Flags::SPLIT;
- }
- if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
- targetFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED;
- } else if (isWindowObscuredLocked(newTouchedWindowHandle)) {
- targetFlags |= InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
- }
+ ftl::Flags<InputTarget::Flags> targetFlags =
+ getTargetFlags(newTouchedWindowHandle, {x, y}, isSplit);
tempTouchState.addOrUpdateWindow(newTouchedWindowHandle,
InputTarget::DispatchMode::SLIPPERY_ENTER,
@@ -2717,7 +2616,7 @@
// Check if the wallpaper window should deliver the corresponding event.
slipWallpaperTouch(targetFlags, oldTouchedWindowHandle, newTouchedWindowHandle,
- tempTouchState, entry, targets);
+ tempTouchState, entry, targets, dump);
tempTouchState.removeTouchingPointerFromWindow(entry.deviceId, pointer.id,
oldTouchedWindowHandle);
}
@@ -2730,7 +2629,7 @@
std::vector<PointerProperties> touchingPointers{entry.pointerProperties[pointerIndex]};
for (TouchedWindow& touchedWindow : tempTouchState.windows) {
// Ignore drag window for it should just track one pointer.
- if (mDragState && mDragState->dragWindow == touchedWindow.windowHandle) {
+ if (dragWindow == touchedWindow.windowHandle) {
continue;
}
if (!touchedWindow.hasTouchingPointers(entry.deviceId)) {
@@ -2744,17 +2643,15 @@
// Update dispatching for hover enter and exit.
{
std::vector<TouchedWindow> hoveringWindows =
- getHoveringWindowsLocked(oldState, tempTouchState, entry,
- std::bind_front(&InputDispatcher::logDispatchStateLocked,
- this));
+ getHoveringWindowsLocked(oldState, tempTouchState, entry, dump);
// Hardcode to single hovering pointer for now.
std::bitset<MAX_POINTER_ID + 1> pointerIds;
pointerIds.set(entry.pointerProperties[0].id);
for (const TouchedWindow& touchedWindow : hoveringWindows) {
- addPointerWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.dispatchMode,
- touchedWindow.targetFlags, pointerIds,
- touchedWindow.getDownTimeInTarget(entry.deviceId),
- targets);
+ addPointerWindowTarget(touchedWindow.windowHandle, touchedWindow.dispatchMode,
+ touchedWindow.targetFlags, pointerIds,
+ touchedWindow.getDownTimeInTarget(entry.deviceId),
+ /*pointerDisplayId=*/std::nullopt, dump, targets);
}
}
@@ -2783,7 +2680,7 @@
for (InputTarget& target : targets) {
if (target.dispatchMode == InputTarget::DispatchMode::OUTSIDE) {
sp<WindowInfoHandle> targetWindow =
- getWindowHandleLocked(target.connection->getToken());
+ mWindowInfos.findWindowHandle(target.connection->getToken());
if (targetWindow->getInfo()->ownerUid != foregroundWindowUid) {
target.flags |= InputTarget::Flags::ZERO_COORDS;
}
@@ -2807,9 +2704,10 @@
if (touchingPointers.empty()) {
continue;
}
- addPointerWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.dispatchMode,
- touchedWindow.targetFlags, getPointerIds(touchingPointers),
- touchedWindow.getDownTimeInTarget(entry.deviceId), targets);
+ addPointerWindowTarget(touchedWindow.windowHandle, touchedWindow.dispatchMode,
+ touchedWindow.targetFlags, getPointerIds(touchingPointers),
+ touchedWindow.getDownTimeInTarget(entry.deviceId),
+ /*pointerDisplayId=*/displayId, dump, targets);
}
// During targeted injection, only allow owned targets to receive events
@@ -2864,16 +2762,12 @@
if (maskedAction != AMOTION_EVENT_ACTION_SCROLL) {
if (displayId >= ui::LogicalDisplayId::DEFAULT) {
tempTouchState.clearWindowsWithoutPointers();
- mTouchStatesByDisplay[displayId] = tempTouchState;
+ saveTouchStateForMotionEntry(entry, std::move(tempTouchState));
} else {
- mTouchStatesByDisplay.erase(displayId);
+ eraseTouchStateForMotionEntry(entry);
}
}
- if (tempTouchState.windows.empty()) {
- mTouchStatesByDisplay.erase(displayId);
- }
-
return targets;
}
@@ -2883,7 +2777,8 @@
constexpr bool isStylus = false;
sp<WindowInfoHandle> dropWindow =
- findTouchedWindowAtLocked(displayId, x, y, isStylus, /*ignoreDragWindow=*/true);
+ mWindowInfos.findTouchedWindowAt(displayId, x, y, isStylus, /*ignoreWindow=*/
+ mDragState->dragWindow);
if (dropWindow) {
vec2 local = dropWindow->getInfo()->transform.transform(x, y);
sendDropWindowCommandLocked(dropWindow->getToken(), local.x, local.y);
@@ -2895,8 +2790,9 @@
}
void InputDispatcher::addDragEventLocked(const MotionEntry& entry) {
- if (!mDragState || mDragState->dragWindow->getInfo()->displayId != entry.displayId ||
- mDragState->deviceId != entry.deviceId) {
+ if (!mDragState || mDragState->deviceId != entry.deviceId ||
+ !mWindowInfos.areDisplaysConnected(mDragState->dragWindow->getInfo()->displayId,
+ entry.displayId)) {
return;
}
@@ -2938,8 +2834,8 @@
constexpr bool isStylus = false;
sp<WindowInfoHandle> hoverWindowHandle =
- findTouchedWindowAtLocked(entry.displayId, x, y, isStylus,
- /*ignoreDragWindow=*/true);
+ mWindowInfos.findTouchedWindowAt(entry.displayId, x, y, isStylus,
+ /*ignoreWindow=*/mDragState->dragWindow);
// enqueue drag exit if needed.
if (hoverWindowHandle != mDragState->dragHoverWindowHandle &&
!haveSameToken(hoverWindowHandle, mDragState->dragHoverWindowHandle)) {
@@ -2974,31 +2870,6 @@
}
}
-std::optional<InputTarget> InputDispatcher::createInputTargetLocked(
- const sp<android::gui::WindowInfoHandle>& windowHandle,
- InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags,
- std::optional<nsecs_t> firstDownTimeInTarget) const {
- std::shared_ptr<Connection> connection = getConnectionLocked(windowHandle->getToken());
- if (connection == nullptr) {
- ALOGW("Not creating InputTarget for %s, no input channel", windowHandle->getName().c_str());
- return {};
- }
- InputTarget inputTarget{connection};
- inputTarget.windowHandle = windowHandle;
- inputTarget.dispatchMode = dispatchMode;
- inputTarget.flags = targetFlags;
- inputTarget.globalScaleFactor = windowHandle->getInfo()->globalScaleFactor;
- inputTarget.firstDownTimeInTarget = firstDownTimeInTarget;
- const auto& displayInfoIt = mDisplayInfos.find(windowHandle->getInfo()->displayId);
- if (displayInfoIt != mDisplayInfos.end()) {
- inputTarget.displayTransform = displayInfoIt->second.transform;
- } else {
- // DisplayInfo not found for this window on display windowHandle->getInfo()->displayId.
- // TODO(b/198444055): Make this an error message after 'setInputWindows' API is removed.
- }
- return inputTarget;
-}
-
void InputDispatcher::addWindowTargetLocked(const sp<WindowInfoHandle>& windowHandle,
InputTarget::DispatchMode dispatchMode,
ftl::Flags<InputTarget::Flags> targetFlags,
@@ -3013,13 +2884,17 @@
const WindowInfo* windowInfo = windowHandle->getInfo();
if (it == inputTargets.end()) {
- std::optional<InputTarget> target =
- createInputTargetLocked(windowHandle, dispatchMode, targetFlags,
- firstDownTimeInTarget);
- if (!target) {
+ std::shared_ptr<Connection> connection =
+ mConnectionManager.getConnection(windowHandle->getToken());
+ if (connection == nullptr) {
+ ALOGW("Not creating InputTarget for %s, no input channel",
+ windowHandle->getName().c_str());
return;
}
- inputTargets.push_back(*target);
+ inputTargets.push_back(
+ createInputTarget(connection, windowHandle, dispatchMode, targetFlags,
+ mWindowInfos.getRawTransform(*windowHandle->getInfo()),
+ firstDownTimeInTarget));
it = inputTargets.end() - 1;
}
@@ -3032,11 +2907,12 @@
}
}
-void InputDispatcher::addPointerWindowTargetLocked(
+void InputDispatcher::DispatcherTouchState::addPointerWindowTarget(
const sp<android::gui::WindowInfoHandle>& windowHandle,
InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags,
std::bitset<MAX_POINTER_ID + 1> pointerIds, std::optional<nsecs_t> firstDownTimeInTarget,
- std::vector<InputTarget>& inputTargets) const REQUIRES(mLock) {
+ std::optional<ui::LogicalDisplayId> pointerDisplayId, std::function<void()> dump,
+ std::vector<InputTarget>& inputTargets) {
if (pointerIds.none()) {
for (const auto& target : inputTargets) {
LOG(INFO) << "Target: " << target;
@@ -3061,16 +2937,19 @@
it = inputTargets.end();
}
- const WindowInfo* windowInfo = windowHandle->getInfo();
+ const WindowInfo& windowInfo = *windowHandle->getInfo();
if (it == inputTargets.end()) {
- std::optional<InputTarget> target =
- createInputTargetLocked(windowHandle, dispatchMode, targetFlags,
- firstDownTimeInTarget);
- if (!target) {
+ std::shared_ptr<Connection> connection = mConnectionManager.getConnection(windowInfo.token);
+ if (connection == nullptr) {
+ ALOGW("Not creating InputTarget for %s, no input channel", windowInfo.name.c_str());
return;
}
- inputTargets.push_back(*target);
+ inputTargets.push_back(
+ createInputTarget(connection, windowHandle, dispatchMode, targetFlags,
+ mWindowInfos.getRawTransform(*windowHandle->getInfo(),
+ pointerDisplayId),
+ firstDownTimeInTarget));
it = inputTargets.end() - 1;
}
@@ -3082,33 +2961,44 @@
LOG(ERROR) << __func__ << ": Flags don't match! new targetFlags=" << targetFlags.string()
<< ", it=" << *it;
}
- if (it->globalScaleFactor != windowInfo->globalScaleFactor) {
+ if (it->globalScaleFactor != windowInfo.globalScaleFactor) {
LOG(ERROR) << __func__ << ": Mismatch! it->globalScaleFactor=" << it->globalScaleFactor
- << ", windowInfo->globalScaleFactor=" << windowInfo->globalScaleFactor;
+ << ", windowInfo->globalScaleFactor=" << windowInfo.globalScaleFactor;
}
- Result<void> result = it->addPointers(pointerIds, windowInfo->transform);
+ Result<void> result = it->addPointers(pointerIds, windowInfo.transform);
if (!result.ok()) {
- logDispatchStateLocked();
+ dump();
LOG(FATAL) << result.error().message();
}
}
void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets,
ui::LogicalDisplayId displayId) {
- auto monitorsIt = mGlobalMonitorsByDisplay.find(displayId);
- if (monitorsIt == mGlobalMonitorsByDisplay.end()) return;
+ mConnectionManager
+ .forEachGlobalMonitorConnection(displayId,
+ [&](const std::shared_ptr<Connection>& connection) {
+ if (!connection->responsive) {
+ ALOGW("Ignoring unrsponsive monitor: %s",
+ connection->getInputChannelName()
+ .c_str());
+ return;
+ }
- for (const Monitor& monitor : selectResponsiveMonitorsLocked(monitorsIt->second)) {
- InputTarget target{monitor.connection};
- // target.firstDownTimeInTarget is not set for global monitors. It is only required in split
- // touch and global monitoring works as intended even without setting firstDownTimeInTarget
- if (const auto& it = mDisplayInfos.find(displayId); it != mDisplayInfos.end()) {
- target.displayTransform = it->second.transform;
- }
- target.setDefaultPointerTransform(target.displayTransform);
- inputTargets.push_back(target);
- }
+ InputTarget target{connection};
+ // target.firstDownTimeInTarget is not set for
+ // global monitors. It is only required in split
+ // touch and global monitoring works as intended
+ // even without setting firstDownTimeInTarget. Since
+ // global monitors don't have windows, use the
+ // display transform as the raw transform.
+ base::ScopedLockAssertion assumeLocked(mLock);
+ target.rawTransform =
+ mWindowInfos.getDisplayTransform(displayId);
+ target.setDefaultPointerTransform(
+ target.rawTransform);
+ inputTargets.push_back(target);
+ });
}
/**
@@ -3164,11 +3054,12 @@
*
* If neither of those is true, then it means the touch can be allowed.
*/
-InputDispatcher::TouchOcclusionInfo InputDispatcher::computeTouchOcclusionInfoLocked(
+InputDispatcher::DispatcherWindowInfo::TouchOcclusionInfo
+InputDispatcher::DispatcherWindowInfo::computeTouchOcclusionInfo(
const sp<WindowInfoHandle>& windowHandle, float x, float y) const {
const WindowInfo* windowInfo = windowHandle->getInfo();
ui::LogicalDisplayId displayId = windowInfo->displayId;
- const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);
+ const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesForDisplay(displayId);
TouchOcclusionInfo info;
info.hasBlockingOcclusion = false;
info.obscuringOpacity = 0;
@@ -3180,11 +3071,11 @@
}
const WindowInfo* otherInfo = otherHandle->getInfo();
if (canBeObscuredBy(windowHandle, otherHandle) &&
- windowOccludesTouchAt(*otherInfo, displayId, x, y, getTransformLocked(displayId)) &&
+ windowOccludesTouchAt(*otherInfo, displayId, x, y, getDisplayTransform(displayId)) &&
!haveSameApplicationToken(windowInfo, otherInfo)) {
if (DEBUG_TOUCH_OCCLUSION) {
info.debugInfo.push_back(
- dumpWindowForTouchOcclusion(otherInfo, /*isTouchedWindow=*/false));
+ dumpWindowForTouchOcclusion(*otherInfo, /*isTouchedWindow=*/false));
}
// canBeObscuredBy() has returned true above, which means this window is untrusted, so
// we perform the checks below to see if the touch can be propagated or not based on the
@@ -3212,28 +3103,14 @@
}
}
if (DEBUG_TOUCH_OCCLUSION) {
- info.debugInfo.push_back(dumpWindowForTouchOcclusion(windowInfo, /*isTouchedWindow=*/true));
+ info.debugInfo.push_back(
+ dumpWindowForTouchOcclusion(*windowInfo, /*isTouchedWindow=*/true));
}
return info;
}
-std::string InputDispatcher::dumpWindowForTouchOcclusion(const WindowInfo* info,
- bool isTouchedWindow) const {
- return StringPrintf(INDENT2 "* %spackage=%s/%s, id=%" PRId32 ", mode=%s, alpha=%.2f, "
- "frame=[%" PRId32 ",%" PRId32 "][%" PRId32 ",%" PRId32
- "], touchableRegion=%s, window={%s}, inputConfig={%s}, "
- "hasToken=%s, applicationInfo.name=%s, applicationInfo.token=%s\n",
- isTouchedWindow ? "[TOUCHED] " : "", info->packageName.c_str(),
- info->ownerUid.toString().c_str(), info->id,
- toString(info->touchOcclusionMode).c_str(), info->alpha, info->frame.left,
- info->frame.top, info->frame.right, info->frame.bottom,
- dumpRegion(info->touchableRegion).c_str(), info->name.c_str(),
- info->inputConfig.string().c_str(), toString(info->token != nullptr),
- info->applicationInfo.name.c_str(),
- binderToString(info->applicationInfo.token).c_str());
-}
-
-bool InputDispatcher::isTouchTrustedLocked(const TouchOcclusionInfo& occlusionInfo) const {
+bool InputDispatcher::DispatcherWindowInfo::isTouchTrusted(
+ const TouchOcclusionInfo& occlusionInfo) const {
if (occlusionInfo.hasBlockingOcclusion) {
ALOGW("Untrusted touch due to occlusion by %s/%s", occlusionInfo.obscuringPackage.c_str(),
occlusionInfo.obscuringUid.toString().c_str());
@@ -3249,26 +3126,27 @@
return true;
}
-bool InputDispatcher::isWindowObscuredAtPointLocked(const sp<WindowInfoHandle>& windowHandle,
- float x, float y) const {
+bool InputDispatcher::DispatcherWindowInfo::isWindowObscuredAtPoint(
+ const sp<WindowInfoHandle>& windowHandle, float x, float y) const {
ui::LogicalDisplayId displayId = windowHandle->getInfo()->displayId;
- const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);
+ const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesForDisplay(displayId);
for (const sp<WindowInfoHandle>& otherHandle : windowHandles) {
if (windowHandle == otherHandle) {
break; // All future windows are below us. Exit early.
}
const WindowInfo* otherInfo = otherHandle->getInfo();
if (canBeObscuredBy(windowHandle, otherHandle) &&
- windowOccludesTouchAt(*otherInfo, displayId, x, y, getTransformLocked(displayId))) {
+ windowOccludesTouchAt(*otherInfo, displayId, x, y, getDisplayTransform(displayId))) {
return true;
}
}
return false;
}
-bool InputDispatcher::isWindowObscuredLocked(const sp<WindowInfoHandle>& windowHandle) const {
+bool InputDispatcher::DispatcherWindowInfo::isWindowObscured(
+ const sp<WindowInfoHandle>& windowHandle) const {
ui::LogicalDisplayId displayId = windowHandle->getInfo()->displayId;
- const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);
+ const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesForDisplay(displayId);
const WindowInfo* windowInfo = windowHandle->getInfo();
for (const sp<WindowInfoHandle>& otherHandle : windowHandles) {
if (windowHandle == otherHandle) {
@@ -3334,10 +3212,9 @@
return;
}
if (windowDisablingUserActivityInfo != nullptr) {
- if (DEBUG_DISPATCH_CYCLE) {
- ALOGD("Not poking user activity: disabled by window '%s'.",
- windowDisablingUserActivityInfo->name.c_str());
- }
+ LOG_IF(INFO, DEBUG_DISPATCH_CYCLE)
+ << "Not poking user activity: disabled by window '"
+ << windowDisablingUserActivityInfo->name << "'.";
return;
}
break;
@@ -3351,10 +3228,9 @@
// the apps, like system shortcuts
if (windowDisablingUserActivityInfo != nullptr &&
keyEntry.interceptKeyResult != KeyEntry::InterceptKeyResult::SKIP) {
- if (DEBUG_DISPATCH_CYCLE) {
- ALOGD("Not poking user activity: disabled by window '%s'.",
- windowDisablingUserActivityInfo->name.c_str());
- }
+ LOG_IF(INFO, DEBUG_DISPATCH_CYCLE)
+ << "Not poking user activity: disabled by window '"
+ << windowDisablingUserActivityInfo->name << "'.";
return;
}
break;
@@ -3382,22 +3258,19 @@
ATRACE_NAME_IF(ATRACE_ENABLED(),
StringPrintf("prepareDispatchCycleLocked(inputChannel=%s, id=0x%" PRIx32 ")",
connection->getInputChannelName().c_str(), eventEntry->id));
- if (DEBUG_DISPATCH_CYCLE) {
- ALOGD("channel '%s' ~ prepareDispatchCycle - flags=%s, "
- "globalScaleFactor=%f, pointerIds=%s %s",
- connection->getInputChannelName().c_str(), inputTarget.flags.string().c_str(),
- inputTarget.globalScaleFactor, bitsetToString(inputTarget.getPointerIds()).c_str(),
- inputTarget.getPointerInfoString().c_str());
- }
+ LOG_IF(INFO, DEBUG_DISPATCH_CYCLE)
+ << "channel '" << connection->getInputChannelName()
+ << "' ~ prepareDispatchCycle - flags=" << inputTarget.flags.string()
+ << ", globalScaleFactor=" << inputTarget.globalScaleFactor
+ << ", pointerIds=" << bitsetToString(inputTarget.getPointerIds()) << " "
+ << inputTarget.getPointerInfoString();
// Skip this event if the connection status is not normal.
// We don't want to enqueue additional outbound events if the connection is broken.
if (connection->status != Connection::Status::NORMAL) {
- if (DEBUG_DISPATCH_CYCLE) {
- ALOGD("channel '%s' ~ Dropping event because the channel status is %s",
- connection->getInputChannelName().c_str(),
- ftl::enum_string(connection->status).c_str());
- }
+ LOG_IF(INFO, DEBUG_DISPATCH_CYCLE) << "channel '" << connection->getInputChannelName()
+ << "' ~ Dropping event because the channel status is "
+ << ftl::enum_string(connection->status);
return;
}
@@ -3516,11 +3389,10 @@
if (resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE &&
!connection->inputState.isHovering(motionEntry.deviceId, motionEntry.source,
motionEntry.displayId)) {
- if (DEBUG_DISPATCH_CYCLE) {
- LOG(DEBUG) << "channel '" << connection->getInputChannelName().c_str()
- << "' ~ enqueueDispatchEntryLocked: filling in missing hover "
- "enter event";
- }
+ LOG_IF(INFO, DEBUG_DISPATCH_CYCLE)
+ << "channel '" << connection->getInputChannelName().c_str()
+ << "' ~ enqueueDispatchEntryLocked: filling in missing hover enter "
+ "event";
resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
}
@@ -3814,9 +3686,8 @@
ATRACE_NAME_IF(ATRACE_ENABLED(),
StringPrintf("startDispatchCycleLocked(inputChannel=%s)",
connection->getInputChannelName().c_str()));
- if (DEBUG_DISPATCH_CYCLE) {
- ALOGD("channel '%s' ~ startDispatchCycle", connection->getInputChannelName().c_str());
- }
+ LOG_IF(INFO, DEBUG_DISPATCH_CYCLE)
+ << "channel '" << connection->getInputChannelName() << "' ~ startDispatchCycle";
while (connection->status == Connection::Status::NORMAL && !connection->outboundQueue.empty()) {
std::unique_ptr<DispatchEntry>& dispatchEntry = connection->outboundQueue.front();
@@ -3831,10 +3702,9 @@
case EventEntry::Type::KEY: {
const KeyEntry& keyEntry = static_cast<const KeyEntry&>(eventEntry);
std::array<uint8_t, 32> hmac = getSignature(keyEntry, *dispatchEntry);
- if (DEBUG_OUTBOUND_EVENT_DETAILS) {
- LOG(INFO) << "Publishing " << *dispatchEntry << " to "
- << connection->getInputChannelName();
- }
+ LOG_IF(INFO, DEBUG_OUTBOUND_EVENT_DETAILS)
+ << "Publishing " << *dispatchEntry << " to "
+ << connection->getInputChannelName();
// Publish the key event.
status = connection->inputPublisher
@@ -3853,10 +3723,9 @@
}
case EventEntry::Type::MOTION: {
- if (DEBUG_OUTBOUND_EVENT_DETAILS) {
- LOG(INFO) << "Publishing " << *dispatchEntry << " to "
- << connection->getInputChannelName();
- }
+ LOG_IF(INFO, DEBUG_OUTBOUND_EVENT_DETAILS)
+ << "Publishing " << *dispatchEntry << " to "
+ << connection->getInputChannelName();
const MotionEntry& motionEntry = static_cast<const MotionEntry&>(eventEntry);
status = publishMotionEvent(*connection, *dispatchEntry);
if (status == BAD_VALUE) {
@@ -3925,22 +3794,21 @@
"event to it, status=%s(%d)",
connection->getInputChannelName().c_str(), statusToString(status).c_str(),
status);
- abortBrokenDispatchCycleLocked(currentTime, connection, /*notify=*/true);
+ abortBrokenDispatchCycleLocked(connection, /*notify=*/true);
} else {
// Pipe is full and we are waiting for the app to finish process some events
// before sending more events to it.
- if (DEBUG_DISPATCH_CYCLE) {
- ALOGD("channel '%s' ~ Could not publish event because the pipe is full, "
- "waiting for the application to catch up",
- connection->getInputChannelName().c_str());
- }
+ LOG_IF(INFO, DEBUG_DISPATCH_CYCLE)
+ << "channel '" << connection->getInputChannelName()
+ << "' ~ Could not publish event because the pipe is full, waiting for "
+ "the application to catch up";
}
} else {
ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, "
"status=%s(%d)",
connection->getInputChannelName().c_str(), statusToString(status).c_str(),
status);
- abortBrokenDispatchCycleLocked(currentTime, connection, /*notify=*/true);
+ abortBrokenDispatchCycleLocked(connection, /*notify=*/true);
}
return;
}
@@ -3999,10 +3867,9 @@
void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
const std::shared_ptr<Connection>& connection,
uint32_t seq, bool handled, nsecs_t consumeTime) {
- if (DEBUG_DISPATCH_CYCLE) {
- ALOGD("channel '%s' ~ finishDispatchCycle - seq=%u, handled=%s",
- connection->getInputChannelName().c_str(), seq, toString(handled));
- }
+ LOG_IF(INFO, DEBUG_DISPATCH_CYCLE)
+ << "channel '" << connection->getInputChannelName()
+ << "' ~ finishDispatchCycle - seq=" << seq << ", handled=" << toString(handled);
if (connection->status != Connection::Status::NORMAL) {
return;
@@ -4015,13 +3882,10 @@
postCommandLocked(std::move(command));
}
-void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime,
- const std::shared_ptr<Connection>& connection,
+void InputDispatcher::abortBrokenDispatchCycleLocked(const std::shared_ptr<Connection>& connection,
bool notify) {
- if (DEBUG_DISPATCH_CYCLE) {
- LOG(INFO) << "channel '" << connection->getInputChannelName() << "'~ " << __func__
- << " - notify=" << toString(notify);
- }
+ LOG_IF(INFO, DEBUG_DISPATCH_CYCLE) << "channel '" << connection->getInputChannelName() << "'~ "
+ << __func__ << " - notify=" << toString(notify);
// Clear the dispatch queues.
drainDispatchQueue(connection->outboundQueue);
@@ -4063,7 +3927,7 @@
int InputDispatcher::handleReceiveCallback(int events, sp<IBinder> connectionToken) {
std::scoped_lock _l(mLock);
- std::shared_ptr<Connection> connection = getConnectionLocked(connectionToken);
+ std::shared_ptr<Connection> connection = mConnectionManager.getConnection(connectionToken);
if (connection == nullptr) {
ALOGW("Received looper callback for unknown input channel token %p. events=0x%x",
connectionToken.get(), events);
@@ -4122,7 +3986,8 @@
} else {
// Monitor channels are never explicitly unregistered.
// We do it automatically when the remote endpoint is closed so don't warn about them.
- const bool stillHaveWindowHandle = getWindowHandleLocked(connection->getToken()) != nullptr;
+ const bool stillHaveWindowHandle =
+ mWindowInfos.findWindowHandle(connection->getToken()) != nullptr;
notify = !connection->monitor && stillHaveWindowHandle;
if (notify) {
ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred. events=0x%x",
@@ -4131,7 +3996,7 @@
}
// Remove the channel.
- removeInputChannelLocked(connection->getToken(), notify);
+ removeInputChannelLocked(connection, notify);
return 0; // remove the callback
}
@@ -4145,23 +4010,27 @@
// Generate cancellations for touched windows first. This is to avoid generating cancellations
// through a non-touched window if there are more than one window for an input channel.
if (cancelPointers) {
- for (const auto& [displayId, touchState] : mTouchStatesByDisplay) {
- if (options.displayId.has_value() && options.displayId != displayId) {
- continue;
- }
- for (const auto& touchedWindow : touchState.windows) {
- synthesizeCancelationEventsForWindowLocked(touchedWindow.windowHandle, options);
- }
+ if (options.displayId.has_value()) {
+ mTouchStates.forAllTouchedWindowsOnDisplay(
+ options.displayId.value(), [&](const sp<gui::WindowInfoHandle>& windowHandle) {
+ base::ScopedLockAssertion assumeLocked(mLock);
+ synthesizeCancelationEventsForWindowLocked(windowHandle, options);
+ });
+ } else {
+ mTouchStates.forAllTouchedWindows([&](const sp<gui::WindowInfoHandle>& windowHandle) {
+ base::ScopedLockAssertion assumeLocked(mLock);
+ synthesizeCancelationEventsForWindowLocked(windowHandle, options);
+ });
}
}
// Follow up by generating cancellations for all windows, because we don't explicitly track
// the windows that have an ongoing focus event stream.
if (cancelNonPointers) {
- for (const auto& [_, handles] : mWindowHandlesByDisplay) {
- for (const auto& windowHandle : handles) {
- synthesizeCancelationEventsForWindowLocked(windowHandle, options);
- }
- }
+ mWindowInfos.forEachWindowHandle(
+ [&](const sp<android::gui::WindowInfoHandle>& windowHandle) {
+ base::ScopedLockAssertion assumeLocked(mLock);
+ synthesizeCancelationEventsForWindowLocked(windowHandle, options);
+ });
}
// Cancel monitors.
@@ -4170,12 +4039,12 @@
void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked(
const CancelationOptions& options) {
- for (const auto& [_, monitors] : mGlobalMonitorsByDisplay) {
- for (const Monitor& monitor : monitors) {
- synthesizeCancelationEventsForConnectionLocked(monitor.connection, options,
- /*window=*/nullptr);
- }
- }
+ mConnectionManager.forEachGlobalMonitorConnection(
+ [&](const std::shared_ptr<Connection>& connection) {
+ base::ScopedLockAssertion assumeLocked(mLock);
+ synthesizeCancelationEventsForConnectionLocked(connection, options,
+ /*window=*/nullptr);
+ });
}
void InputDispatcher::synthesizeCancelationEventsForWindowLocked(
@@ -4193,7 +4062,7 @@
}
std::shared_ptr<Connection> resolvedConnection =
- connection ? connection : getConnectionLocked(windowHandle->getToken());
+ connection ? connection : mConnectionManager.getConnection(windowHandle->getToken());
if (!resolvedConnection) {
LOG(DEBUG) << __func__ << "No connection found for window: " << windowHandle->getName();
return;
@@ -4222,12 +4091,11 @@
return;
}
- if (DEBUG_OUTBOUND_EVENT_DETAILS) {
- ALOGD("channel '%s' ~ Synthesized %zu cancelation events to bring channel back in sync "
- "with reality: %s, mode=%s.",
- connection->getInputChannelName().c_str(), cancelationEvents.size(), options.reason,
- ftl::enum_string(options.mode).c_str());
- }
+ LOG_IF(INFO, DEBUG_OUTBOUND_EVENT_DETAILS)
+ << "channel '" << connection->getInputChannelName() << "' ~ Synthesized "
+ << cancelationEvents.size()
+ << " cancelation events to bring channel back in sync with reality: " << options.reason
+ << ", mode=" << ftl::enum_string(options.mode) << ".";
std::string reason = std::string("reason=").append(options.reason);
android_log_event_list(LOGTAG_INPUT_CANCEL)
@@ -4280,16 +4148,22 @@
sendDropWindowCommandLocked(nullptr, /*x=*/0, /*y=*/0);
mDragState.reset();
}
- addPointerWindowTargetLocked(window, InputTarget::DispatchMode::AS_IS,
- ftl::Flags<InputTarget::Flags>(), pointerIds,
- motionEntry.downTime, targets);
+ mTouchStates
+ .addPointerWindowTarget(window, InputTarget::DispatchMode::AS_IS,
+ ftl::Flags<InputTarget::Flags>(), pointerIds,
+ motionEntry.downTime,
+ /*pointerDisplayId=*/std::nullopt,
+ std::bind_front(&InputDispatcher::
+ logDispatchStateLocked,
+ this),
+ targets);
} else {
targets.emplace_back(fallbackTarget);
- const auto it = mDisplayInfos.find(motionEntry.displayId);
- if (it != mDisplayInfos.end()) {
- targets.back().displayTransform = it->second.transform;
- targets.back().setDefaultPointerTransform(it->second.transform);
- }
+ // Since we don't have a window, use the display transform as the raw transform.
+ const ui::Transform displayTransform =
+ mWindowInfos.getDisplayTransform(motionEntry.displayId);
+ targets.back().rawTransform = displayTransform;
+ targets.back().setDefaultPointerTransform(displayTransform);
}
logOutboundMotionDetails("cancel - ", motionEntry);
break;
@@ -4338,17 +4212,12 @@
return;
}
- if (DEBUG_OUTBOUND_EVENT_DETAILS) {
- ALOGD("channel '%s' ~ Synthesized %zu down events to ensure consistent event stream.",
- connection->getInputChannelName().c_str(), downEvents.size());
- }
+ LOG_IF(INFO, DEBUG_OUTBOUND_EVENT_DETAILS)
+ << "channel '" << connection->getInputChannelName() << "' ~ Synthesized "
+ << downEvents.size() << " down events to ensure consistent event stream.";
- const auto [_, touchedWindowState, displayId] =
- findTouchStateWindowAndDisplayLocked(connection->getToken());
- if (touchedWindowState == nullptr) {
- LOG(FATAL) << __func__ << ": Touch state is out of sync: No touched window for token";
- }
- const auto& windowHandle = touchedWindowState->windowHandle;
+ const auto [windowHandle, displayId] =
+ mTouchStates.findExistingTouchedWindowHandleAndDisplay(connection->getToken());
const bool wasEmpty = connection->outboundQueue.empty();
for (std::unique_ptr<EventEntry>& downEventEntry : downEvents) {
@@ -4366,16 +4235,21 @@
pointerIndex++) {
pointerIds.set(motionEntry.pointerProperties[pointerIndex].id);
}
- addPointerWindowTargetLocked(windowHandle, InputTarget::DispatchMode::AS_IS,
- targetFlags, pointerIds, motionEntry.downTime,
- targets);
+ mTouchStates
+ .addPointerWindowTarget(windowHandle, InputTarget::DispatchMode::AS_IS,
+ targetFlags, pointerIds, motionEntry.downTime,
+ /*pointerDisplayId=*/std::nullopt,
+ std::bind_front(&InputDispatcher::
+ logDispatchStateLocked,
+ this),
+ targets);
} else {
targets.emplace_back(connection, targetFlags);
- const auto it = mDisplayInfos.find(motionEntry.displayId);
- if (it != mDisplayInfos.end()) {
- targets.back().displayTransform = it->second.transform;
- targets.back().setDefaultPointerTransform(it->second.transform);
- }
+ // Since we don't have a window, use the display transform as the raw transform.
+ const ui::Transform displayTransform =
+ mWindowInfos.getDisplayTransform(motionEntry.displayId);
+ targets.back().rawTransform = displayTransform;
+ targets.back().setDefaultPointerTransform(displayTransform);
}
logOutboundMotionDetails("down - ", motionEntry);
break;
@@ -4475,15 +4349,15 @@
}
void InputDispatcher::notifyKey(const NotifyKeyArgs& args) {
- ALOGD_IF(debugInboundEventDetails(),
- "notifyKey - id=%" PRIx32 ", eventTime=%" PRId64
- ", deviceId=%d, source=%s, displayId=%s, policyFlags=0x%x, action=%s, flags=0x%x, "
- "keyCode=%s, scanCode=0x%x, metaState=0x%x, "
- "downTime=%" PRId64,
- args.id, args.eventTime, args.deviceId, inputEventSourceToString(args.source).c_str(),
- args.displayId.toString().c_str(), args.policyFlags,
- KeyEvent::actionToString(args.action), args.flags, KeyEvent::getLabel(args.keyCode),
- args.scanCode, args.metaState, args.downTime);
+ LOG_IF(INFO, debugInboundEventDetails())
+ << "notifyKey - id=" << args.id << ", eventTime=" << args.eventTime
+ << ", deviceId=" << args.deviceId
+ << ", source=" << inputEventSourceToString(args.source)
+ << ", displayId=" << args.displayId.toString() << ", policyFlags=0x" << std::hex
+ << args.policyFlags << ", action=" << KeyEvent::actionToString(args.action)
+ << ", flags=0x" << args.flags << ", keyCode=" << KeyEvent::getLabel(args.keyCode)
+ << ", scanCode=0x" << args.scanCode << ", metaState=0x" << args.metaState
+ << ", downTime=" << std::dec << args.downTime;
Result<void> keyCheck = validateKeyEvent(args.action);
if (!keyCheck.ok()) {
LOG(ERROR) << "invalid key event: " << keyCheck.error();
@@ -4551,7 +4425,7 @@
if (args.id != android::os::IInputConstants::INVALID_INPUT_EVENT_ID &&
IdGenerator::getSource(args.id) == IdGenerator::Source::INPUT_READER &&
!mInputFilterEnabled) {
- mLatencyTracker.trackNotifyKey(args);
+ mLatencyTracker.trackListener(args);
}
}
@@ -4611,8 +4485,9 @@
args.displayId.toString().c_str()));
Result<void> result =
it->second.processMovement(args.deviceId, args.source, args.action,
- args.getPointerCount(), args.pointerProperties.data(),
- args.pointerCoords.data(), args.flags);
+ args.actionButton, args.getPointerCount(),
+ args.pointerProperties.data(), args.pointerCoords.data(),
+ args.flags, args.buttonState);
if (!result.ok()) {
LOG(FATAL) << "Bad stream: " << result.error() << " caused by " << args.dump();
}
@@ -4635,21 +4510,13 @@
if (!(policyFlags & POLICY_FLAG_PASS_TO_USER)) {
// Set the flag anyway if we already have an ongoing gesture. That would allow us to
// complete the processing of the current stroke.
- const auto touchStateIt = mTouchStatesByDisplay.find(args.displayId);
- if (touchStateIt != mTouchStatesByDisplay.end()) {
- const TouchState& touchState = touchStateIt->second;
- if (touchState.hasTouchingPointers(args.deviceId) ||
- touchState.hasHoveringPointers(args.deviceId)) {
- policyFlags |= POLICY_FLAG_PASS_TO_USER;
- }
+ if (mTouchStates.hasTouchingOrHoveringPointers(args.displayId, args.deviceId)) {
+ policyFlags |= POLICY_FLAG_PASS_TO_USER;
}
}
if (shouldSendMotionToInputFilterLocked(args)) {
- ui::Transform displayTransform;
- if (const auto it = mDisplayInfos.find(args.displayId); it != mDisplayInfos.end()) {
- displayTransform = it->second.transform;
- }
+ ui::Transform displayTransform = mWindowInfos.getDisplayTransform(args.displayId);
mLock.unlock();
@@ -4687,7 +4554,7 @@
if (args.id != android::os::IInputConstants::INVALID_INPUT_EVENT_ID &&
IdGenerator::getSource(args.id) == IdGenerator::Source::INPUT_READER &&
!mInputFilterEnabled) {
- mLatencyTracker.trackNotifyMotion(args);
+ mLatencyTracker.trackListener(args);
}
needWake = enqueueInboundEventLocked(std::move(newEntry));
@@ -4700,12 +4567,10 @@
}
void InputDispatcher::notifySensor(const NotifySensorArgs& args) {
- if (debugInboundEventDetails()) {
- ALOGD("notifySensor - id=%" PRIx32 " eventTime=%" PRId64 ", deviceId=%d, source=0x%x, "
- " sensorType=%s",
- args.id, args.eventTime, args.deviceId, args.source,
- ftl::enum_string(args.sensorType).c_str());
- }
+ LOG_IF(INFO, debugInboundEventDetails())
+ << "notifySensor - id=" << args.id << " eventTime=" << args.eventTime
+ << ", deviceId=" << args.deviceId << ", source=0x" << std::hex << args.source
+ << std::dec << ", sensorType=" << ftl::enum_string(args.sensorType);
bool needWake = false;
{ // acquire lock
@@ -4727,10 +4592,9 @@
}
void InputDispatcher::notifyVibratorState(const NotifyVibratorStateArgs& args) {
- if (debugInboundEventDetails()) {
- ALOGD("notifyVibratorState - eventTime=%" PRId64 ", device=%d, isOn=%d", args.eventTime,
- args.deviceId, args.isOn);
- }
+ LOG_IF(INFO, debugInboundEventDetails())
+ << "notifyVibratorState - eventTime=" << args.eventTime << ", device=" << args.deviceId
+ << ", isOn=" << args.isOn;
mPolicy.notifyVibratorState(args.deviceId, args.isOn);
}
@@ -4739,11 +4603,10 @@
}
void InputDispatcher::notifySwitch(const NotifySwitchArgs& args) {
- if (debugInboundEventDetails()) {
- ALOGD("notifySwitch - eventTime=%" PRId64 ", policyFlags=0x%x, switchValues=0x%08x, "
- "switchMask=0x%08x",
- args.eventTime, args.policyFlags, args.switchValues, args.switchMask);
- }
+ LOG_IF(INFO, debugInboundEventDetails())
+ << "notifySwitch - eventTime=" << args.eventTime << ", policyFlags=0x" << std::hex
+ << args.policyFlags << ", switchValues=0x" << std::setfill('0') << std::setw(8)
+ << args.switchValues << ", switchMask=0x" << std::setw(8) << args.switchMask;
uint32_t policyFlags = args.policyFlags;
policyFlags |= POLICY_FLAG_TRUSTED;
@@ -4752,10 +4615,8 @@
void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
// TODO(b/308677868) Remove device reset from the InputListener interface
- if (debugInboundEventDetails()) {
- ALOGD("notifyDeviceReset - eventTime=%" PRId64 ", deviceId=%d", args.eventTime,
- args.deviceId);
- }
+ LOG_IF(INFO, debugInboundEventDetails())
+ << "notifyDeviceReset - eventTime=" << args.eventTime << ", deviceId=" << args.deviceId;
bool needWake = false;
{ // acquire lock
@@ -4776,10 +4637,9 @@
}
void InputDispatcher::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) {
- if (debugInboundEventDetails()) {
- ALOGD("notifyPointerCaptureChanged - eventTime=%" PRId64 ", enabled=%s", args.eventTime,
- args.request.isEnable() ? "true" : "false");
- }
+ LOG_IF(INFO, debugInboundEventDetails())
+ << "notifyPointerCaptureChanged - eventTime=%" << args.eventTime
+ << ", enabled=" << toString(args.request.isEnable());
bool needWake = false;
{ // acquire lock
@@ -4816,9 +4676,10 @@
Result<void> result =
verifier.processMovement(deviceId, motionEvent.getSource(), motionEvent.getAction(),
- motionEvent.getPointerCount(),
+ motionEvent.getActionButton(), motionEvent.getPointerCount(),
motionEvent.getPointerProperties(),
- motionEvent.getSamplePointerCoords(), flags);
+ motionEvent.getSamplePointerCoords(), flags,
+ motionEvent.getButtonState());
if (!result.ok()) {
logDispatchStateLocked();
LOG(ERROR) << "Inconsistent event: " << motionEvent << ", reason: " << result.error();
@@ -4838,12 +4699,10 @@
return InputEventInjectionResult::FAILED;
}
- if (debugInboundEventDetails()) {
- LOG(INFO) << __func__ << ": targetUid=" << toString(targetUid, &uidString)
- << ", syncMode=" << ftl::enum_string(syncMode) << ", timeout=" << timeout.count()
- << "ms, policyFlags=0x" << std::hex << policyFlags << std::dec
- << ", event=" << *event;
- }
+ LOG_IF(INFO, debugInboundEventDetails())
+ << __func__ << ": targetUid=" << toString(targetUid, &uidString)
+ << ", syncMode=" << ftl::enum_string(syncMode) << ", timeout=" << timeout.count()
+ << "ms, policyFlags=0x" << std::hex << policyFlags << std::dec << ", event=" << *event;
nsecs_t endTime = now() + std::chrono::duration_cast<std::chrono::nanoseconds>(timeout).count();
policyFlags |= POLICY_FLAG_INJECTED | POLICY_FLAG_TRUSTED;
@@ -4935,6 +4794,10 @@
flags |= AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT;
}
+ if (policyFlags & POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY_TOOL) {
+ flags |= AMOTION_EVENT_FLAG_INJECTED_FROM_ACCESSIBILITY_TOOL;
+ }
+
mLock.lock();
if (shouldRejectInjectedMotionLocked(motionEvent, resolvedDeviceId, displayId,
@@ -4943,6 +4806,14 @@
return InputEventInjectionResult::FAILED;
}
+ if (!(policyFlags & POLICY_FLAG_PASS_TO_USER)) {
+ // Set the flag anyway if we already have an ongoing motion gesture. That
+ // would allow us to complete the processing of the current stroke.
+ if (mTouchStates.hasTouchingOrHoveringPointers(displayId, resolvedDeviceId)) {
+ policyFlags |= POLICY_FLAG_PASS_TO_USER;
+ }
+ }
+
const nsecs_t* sampleEventTimes = motionEvent.getSampleEventTimes();
const size_t pointerCount = motionEvent.getPointerCount();
const std::vector<PointerProperties>
@@ -5008,9 +4879,7 @@
bool needWake = false;
while (!injectedEntries.empty()) {
- if (DEBUG_INJECTION) {
- LOG(INFO) << "Injecting " << injectedEntries.front()->getDescription();
- }
+ LOG_IF(INFO, DEBUG_INJECTION) << "Injecting " << injectedEntries.front()->getDescription();
needWake |= enqueueInboundEventLocked(std::move(injectedEntries.front()));
injectedEntries.pop();
}
@@ -5036,10 +4905,8 @@
nsecs_t remainingTimeout = endTime - now();
if (remainingTimeout <= 0) {
- if (DEBUG_INJECTION) {
- ALOGD("injectInputEvent - Timed out waiting for injection result "
- "to become available.");
- }
+ LOG_IF(INFO, DEBUG_INJECTION) << "injectInputEvent - Timed out waiting for "
+ "injection result to become available.";
injectionResult = InputEventInjectionResult::TIMED_OUT;
break;
}
@@ -5050,16 +4917,14 @@
if (injectionResult == InputEventInjectionResult::SUCCEEDED &&
syncMode == InputEventInjectionSync::WAIT_FOR_FINISHED) {
while (injectionState->pendingForegroundDispatches != 0) {
- if (DEBUG_INJECTION) {
- ALOGD("injectInputEvent - Waiting for %d pending foreground dispatches.",
- injectionState->pendingForegroundDispatches);
- }
+ LOG_IF(INFO, DEBUG_INJECTION) << "injectInputEvent - Waiting for "
+ << injectionState->pendingForegroundDispatches
+ << " pending foreground dispatches.";
nsecs_t remainingTimeout = endTime - now();
if (remainingTimeout <= 0) {
- if (DEBUG_INJECTION) {
- ALOGD("injectInputEvent - Timed out waiting for pending foreground "
- "dispatches to finish.");
- }
+ LOG_IF(INFO, DEBUG_INJECTION)
+ << "injectInputEvent - Timed out waiting for pending foreground "
+ "dispatches to finish.";
injectionResult = InputEventInjectionResult::TIMED_OUT;
break;
}
@@ -5070,10 +4935,8 @@
}
} // release lock
- if (DEBUG_INJECTION) {
- LOG(INFO) << "injectInputEvent - Finished with result "
- << ftl::enum_string(injectionResult);
- }
+ LOG_IF(INFO, DEBUG_INJECTION) << "injectInputEvent - Finished with result "
+ << ftl::enum_string(injectionResult);
return injectionResult;
}
@@ -5119,10 +4982,8 @@
}
InjectionState& injectionState = *entry.injectionState;
- if (DEBUG_INJECTION) {
- LOG(INFO) << "Setting input event injection result to "
- << ftl::enum_string(injectionResult);
- }
+ LOG_IF(INFO, DEBUG_INJECTION) << "Setting input event injection result to "
+ << ftl::enum_string(injectionResult);
if (injectionState.injectionIsAsync && !(entry.policyFlags & POLICY_FLAG_FILTERED)) {
// Log the outcome since the injector did not wait for the injection result.
@@ -5153,9 +5014,8 @@
MotionEntry& entry, const ui::Transform& injectedTransform) const {
// Input injection works in the logical display coordinate space, but the input pipeline works
// display space, so we need to transform the injected events accordingly.
- const auto it = mDisplayInfos.find(entry.displayId);
- if (it == mDisplayInfos.end()) return;
- const auto& transformToDisplay = it->second.transform.inverse() * injectedTransform;
+ const ui::Transform displayTransform = mWindowInfos.getDisplayTransform(entry.displayId);
+ const auto& transformToDisplay = displayTransform.inverse() * injectedTransform;
if (entry.xCursorPosition != AMOTION_EVENT_INVALID_CURSOR_POSITION &&
entry.yCursorPosition != AMOTION_EVENT_INVALID_CURSOR_POSITION) {
@@ -5188,14 +5048,7 @@
}
}
-const std::vector<sp<WindowInfoHandle>>& InputDispatcher::getWindowHandlesLocked(
- ui::LogicalDisplayId displayId) const {
- static const std::vector<sp<WindowInfoHandle>> EMPTY_WINDOW_HANDLES;
- auto it = mWindowHandlesByDisplay.find(displayId);
- return it != mWindowHandlesByDisplay.end() ? it->second : EMPTY_WINDOW_HANDLES;
-}
-
-sp<WindowInfoHandle> InputDispatcher::getWindowHandleLocked(
+sp<WindowInfoHandle> InputDispatcher::DispatcherWindowInfo::findWindowHandle(
const sp<IBinder>& windowHandleToken, std::optional<ui::LogicalDisplayId> displayId) const {
if (windowHandleToken == nullptr) {
return nullptr;
@@ -5214,15 +5067,26 @@
}
// Only look through the requested display.
- for (const sp<WindowInfoHandle>& windowHandle : getWindowHandlesLocked(*displayId)) {
- if (windowHandle->getToken() == windowHandleToken) {
+ return findWindowHandleOnDisplay(windowHandleToken, *displayId);
+}
+
+sp<WindowInfoHandle> InputDispatcher::DispatcherWindowInfo::findWindowHandleOnConnectedDisplays(
+ const sp<IBinder>& windowHandleToken, ui::LogicalDisplayId displayId) const {
+ if (windowHandleToken == nullptr) {
+ return nullptr;
+ }
+
+ sp<WindowInfoHandle> windowHandle;
+ for (ui::LogicalDisplayId connectedDisplayId : getConnectedDisplays(displayId)) {
+ windowHandle = findWindowHandleOnDisplay(windowHandleToken, connectedDisplayId);
+ if (windowHandle != nullptr) {
return windowHandle;
}
}
return nullptr;
}
-sp<WindowInfoHandle> InputDispatcher::getWindowHandleLocked(
+bool InputDispatcher::DispatcherWindowInfo::isWindowPresent(
const sp<WindowInfoHandle>& windowHandle) const {
for (const auto& [displayId, windowHandles] : mWindowHandlesByDisplay) {
for (const sp<WindowInfoHandle>& handle : windowHandles) {
@@ -5234,27 +5098,159 @@
windowHandle->getName().c_str(), displayId.toString().c_str(),
windowHandle->getInfo()->displayId.toString().c_str());
}
- return handle;
+ return true;
}
}
}
- return nullptr;
+ return false;
}
sp<WindowInfoHandle> InputDispatcher::getFocusedWindowHandleLocked(
ui::LogicalDisplayId displayId) const {
sp<IBinder> focusedToken = mFocusResolver.getFocusedWindowToken(displayId);
- return getWindowHandleLocked(focusedToken, displayId);
+ return mWindowInfos.findWindowHandle(focusedToken, displayId);
}
-ui::Transform InputDispatcher::getTransformLocked(ui::LogicalDisplayId displayId) const {
+void InputDispatcher::DispatcherWindowInfo::setWindowHandlesForDisplay(
+ ui::LogicalDisplayId displayId, std::vector<sp<WindowInfoHandle>>&& windowHandles) {
+ // Insert or replace
+ mWindowHandlesByDisplay[displayId] = std::move(windowHandles);
+}
+
+void InputDispatcher::DispatcherWindowInfo::setDisplayInfos(
+ const std::vector<android::gui::DisplayInfo>& displayInfos) {
+ mDisplayInfos.clear();
+ for (const auto& displayInfo : displayInfos) {
+ mDisplayInfos.emplace(displayInfo.displayId, displayInfo);
+ }
+}
+
+void InputDispatcher::DispatcherWindowInfo::removeDisplay(ui::LogicalDisplayId displayId) {
+ mWindowHandlesByDisplay.erase(displayId);
+}
+
+const std::vector<sp<android::gui::WindowInfoHandle>>&
+InputDispatcher::DispatcherWindowInfo::getWindowHandlesForDisplay(
+ ui::LogicalDisplayId displayId) const {
+ static const std::vector<sp<WindowInfoHandle>> EMPTY_WINDOW_HANDLES;
+ const auto it = mWindowHandlesByDisplay.find(displayId);
+ return it != mWindowHandlesByDisplay.end() ? it->second : EMPTY_WINDOW_HANDLES;
+}
+
+void InputDispatcher::DispatcherWindowInfo::forEachWindowHandle(
+ std::function<void(const sp<android::gui::WindowInfoHandle>&)> f) const {
+ for (const auto& [_, windowHandles] : mWindowHandlesByDisplay) {
+ for (const auto& windowHandle : windowHandles) {
+ f(windowHandle);
+ }
+ }
+}
+
+void InputDispatcher::DispatcherWindowInfo::forEachDisplayId(
+ std::function<void(ui::LogicalDisplayId)> f) const {
+ for (const auto& [displayId, _] : mWindowHandlesByDisplay) {
+ f(displayId);
+ }
+}
+
+ui::Transform InputDispatcher::DispatcherWindowInfo::getDisplayTransform(
+ ui::LogicalDisplayId displayId) const {
auto displayInfoIt = mDisplayInfos.find(displayId);
return displayInfoIt != mDisplayInfos.end() ? displayInfoIt->second.transform
: kIdentityTransform;
}
-bool InputDispatcher::canWindowReceiveMotionLocked(const sp<WindowInfoHandle>& window,
- const MotionEntry& motionEntry) const {
+ui::Transform InputDispatcher::DispatcherWindowInfo::getRawTransform(
+ const android::gui::WindowInfo& windowInfo,
+ std::optional<ui::LogicalDisplayId> pointerDisplayId) const {
+ // TODO(b/383092013): Handle TOPOLOGY_AWARE window flag.
+ // For now, we assume all windows are topology-aware and can handle cross-display streams.
+ if (com::android::input::flags::connected_displays_cursor() && pointerDisplayId.has_value() &&
+ *pointerDisplayId != windowInfo.displayId) {
+ // Sending pointer to a different display than the window. This is a
+ // cross-display drag gesture, so always use the new display's transform.
+ return getDisplayTransform(*pointerDisplayId);
+ }
+ // If the window has a cloneLayerStackTransform, always use it as the transform for the "getRaw"
+ // APIs. If not, fall back to using the DisplayInfo transform of the window's display
+ bool useClonedScreenCoordinates = (input_flags::use_cloned_screen_coordinates_as_raw() &&
+ windowInfo.cloneLayerStackTransform);
+ if (useClonedScreenCoordinates) {
+ return *windowInfo.cloneLayerStackTransform;
+ }
+ return getDisplayTransform(windowInfo.displayId);
+}
+
+ui::LogicalDisplayId InputDispatcher::DispatcherWindowInfo::getPrimaryDisplayId(
+ ui::LogicalDisplayId displayId) const {
+ if (mTopology.graph.contains(displayId)) {
+ return mTopology.primaryDisplayId;
+ }
+ return displayId;
+}
+
+bool InputDispatcher::DispatcherWindowInfo::areDisplaysConnected(
+ ui::LogicalDisplayId display1, ui::LogicalDisplayId display2) const {
+ return display1 == display2 ||
+ (mTopology.graph.contains(display1) && mTopology.graph.contains(display2));
+}
+
+std::string InputDispatcher::DispatcherWindowInfo::dumpDisplayAndWindowInfo() const {
+ std::string dump;
+ if (!mWindowHandlesByDisplay.empty()) {
+ for (const auto& [displayId, windowHandles] : mWindowHandlesByDisplay) {
+ dump += StringPrintf("Display: %s\n", displayId.toString().c_str());
+ if (const auto& it = mDisplayInfos.find(displayId); it != mDisplayInfos.end()) {
+ const auto& displayInfo = it->second;
+ dump += StringPrintf(INDENT "logicalSize=%dx%d\n", displayInfo.logicalWidth,
+ displayInfo.logicalHeight);
+ displayInfo.transform.dump(dump, "transform", INDENT3);
+ } else {
+ dump += INDENT "No DisplayInfo found!\n";
+ }
+
+ if (!windowHandles.empty()) {
+ dump += INDENT "Windows:\n";
+ for (size_t i = 0; i < windowHandles.size(); i++) {
+ dump += StringPrintf(INDENT2 "%zu: %s", i,
+ streamableToString(*windowHandles[i]).c_str());
+ }
+ } else {
+ dump += INDENT "Windows: <none>\n";
+ }
+ }
+ } else {
+ dump += "Displays: <none>\n";
+ }
+ return dump;
+}
+
+std::vector<ui::LogicalDisplayId> InputDispatcher::DispatcherWindowInfo::getConnectedDisplays(
+ ui::LogicalDisplayId displayId) const {
+ if (!mTopology.graph.contains(displayId)) {
+ return {displayId};
+ }
+
+ std::vector<ui::LogicalDisplayId> connectedDisplays;
+ for (auto it : mTopology.graph) {
+ connectedDisplays.push_back(it.first);
+ }
+ return connectedDisplays;
+}
+
+sp<WindowInfoHandle> InputDispatcher::DispatcherWindowInfo::findWindowHandleOnDisplay(
+ const sp<IBinder>& windowHandleToken, ui::LogicalDisplayId displayId) const {
+ for (const sp<WindowInfoHandle>& windowHandle : getWindowHandlesForDisplay(displayId)) {
+ if (windowHandle->getToken() == windowHandleToken) {
+ return windowHandle;
+ }
+ }
+ return nullptr;
+}
+
+bool InputDispatcher::DispatcherTouchState::canWindowReceiveMotion(
+ const sp<android::gui::WindowInfoHandle>& window,
+ const android::inputdispatcher::MotionEntry& motionEntry) const {
const WindowInfo& info = *window->getInfo();
// Skip spy window targets that are not valid for targeted injection.
@@ -5273,7 +5269,7 @@
return false;
}
- std::shared_ptr<Connection> connection = getConnectionLocked(window->getToken());
+ std::shared_ptr<Connection> connection = mConnectionManager.getConnection(window->getToken());
if (connection == nullptr) {
ALOGW("Not sending touch to %s because there's no corresponding connection",
window->getName().c_str());
@@ -5287,8 +5283,9 @@
// Drop events that can't be trusted due to occlusion
const auto [x, y] = resolveTouchedPosition(motionEntry);
- TouchOcclusionInfo occlusionInfo = computeTouchOcclusionInfoLocked(window, x, y);
- if (!isTouchTrustedLocked(occlusionInfo)) {
+ DispatcherWindowInfo::TouchOcclusionInfo occlusionInfo =
+ mWindowInfos.computeTouchOcclusionInfo(window, x, y);
+ if (!mWindowInfos.isTouchTrusted(occlusionInfo)) {
if (DEBUG_TOUCH_OCCLUSION) {
ALOGD("Stack of obscuring windows during untrusted touch (%.1f, %.1f):", x, y);
for (const auto& log : occlusionInfo.debugInfo) {
@@ -5301,13 +5298,13 @@
}
// Drop touch events if requested by input feature
- if (shouldDropInput(motionEntry, window)) {
+ if (shouldDropInput(motionEntry, window, mWindowInfos)) {
return false;
}
// Ignore touches if stylus is down anywhere on screen
if (info.inputConfig.test(WindowInfo::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH) &&
- isStylusActiveInDisplay(info.displayId, mTouchStatesByDisplay)) {
+ isStylusActiveInDisplay(info.displayId)) {
LOG(INFO) << "Dropping touch from " << window->getName() << " because stylus is active";
return false;
}
@@ -5320,13 +5317,14 @@
ui::LogicalDisplayId displayId) {
if (windowInfoHandles.empty()) {
// Remove all handles on a display if there are no windows left.
- mWindowHandlesByDisplay.erase(displayId);
+ mWindowInfos.removeDisplay(displayId);
return;
}
// Since we compare the pointer of input window handles across window updates, we need
// to make sure the handle object for the same window stays unchanged across updates.
- const std::vector<sp<WindowInfoHandle>>& oldHandles = getWindowHandlesLocked(displayId);
+ const std::vector<sp<WindowInfoHandle>>& oldHandles =
+ mWindowInfos.getWindowHandlesForDisplay(displayId);
std::unordered_map<int32_t /*id*/, sp<WindowInfoHandle>> oldHandlesById;
for (const sp<WindowInfoHandle>& handle : oldHandles) {
oldHandlesById[handle->getId()] = handle;
@@ -5335,7 +5333,7 @@
std::vector<sp<WindowInfoHandle>> newHandles;
for (const sp<WindowInfoHandle>& handle : windowInfoHandles) {
const WindowInfo* info = handle->getInfo();
- if (getConnectionLocked(handle->getToken()) == nullptr) {
+ if (mConnectionManager.getConnection(handle->getToken()) == nullptr) {
const bool noInputChannel =
info->inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL);
const bool canReceiveInput =
@@ -5365,8 +5363,7 @@
}
}
- // Insert or replace
- mWindowHandlesByDisplay[displayId] = newHandles;
+ mWindowInfos.setWindowHandlesForDisplay(displayId, std::move(newHandles));
}
/**
@@ -5416,12 +5413,14 @@
}
// Copy old handles for release if they are no longer present.
- const std::vector<sp<WindowInfoHandle>> oldWindowHandles = getWindowHandlesLocked(displayId);
+ const std::vector<sp<WindowInfoHandle>> oldWindowHandles =
+ mWindowInfos.getWindowHandlesForDisplay(displayId);
const sp<WindowInfoHandle> removedFocusedWindowHandle = getFocusedWindowHandleLocked(displayId);
updateWindowHandlesForDisplayLocked(windowInfoHandles, displayId);
- const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);
+ const std::vector<sp<WindowInfoHandle>>& windowHandles =
+ mWindowInfos.getWindowHandlesForDisplay(displayId);
std::optional<FocusResolver::FocusChanges> changes =
mFocusResolver.setInputWindows(displayId, windowHandles);
@@ -5429,69 +5428,38 @@
onFocusChangedLocked(*changes, traceContext.getTracker(), removedFocusedWindowHandle);
}
- if (const auto& it = mTouchStatesByDisplay.find(displayId); it != mTouchStatesByDisplay.end()) {
- TouchState& state = it->second;
- for (size_t i = 0; i < state.windows.size();) {
- TouchedWindow& touchedWindow = state.windows[i];
- if (getWindowHandleLocked(touchedWindow.windowHandle) != nullptr) {
- i++;
- continue;
- }
- LOG(INFO) << "Touched window was removed: " << touchedWindow.windowHandle->getName()
- << " in display %" << displayId;
- CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
- "touched window was removed", traceContext.getTracker());
- synthesizeCancelationEventsForWindowLocked(touchedWindow.windowHandle, options);
- // Since we are about to drop the touch, cancel the events for the wallpaper as
- // well.
- if (touchedWindow.targetFlags.test(InputTarget::Flags::FOREGROUND) &&
- touchedWindow.windowHandle->getInfo()->inputConfig.test(
- gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
- for (const DeviceId deviceId : touchedWindow.getTouchingDeviceIds()) {
- if (const auto& ww = state.getWallpaperWindow(deviceId); ww != nullptr) {
- options.deviceId = deviceId;
- synthesizeCancelationEventsForWindowLocked(ww, options);
- }
- }
- }
- state.windows.erase(state.windows.begin() + i);
- }
-
- // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We
- // could just clear the state here.
- if (mDragState && mDragState->dragWindow->getInfo()->displayId == displayId &&
- std::find(windowHandles.begin(), windowHandles.end(), mDragState->dragWindow) ==
- windowHandles.end()) {
- ALOGI("Drag window went away: %s", mDragState->dragWindow->getName().c_str());
- sendDropWindowCommandLocked(nullptr, 0, 0);
- mDragState.reset();
+ CancelationOptions pointerCancellationOptions(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
+ "touched window was removed",
+ traceContext.getTracker());
+ CancelationOptions hoverCancellationOptions(CancelationOptions::Mode::CANCEL_HOVER_EVENTS,
+ "WindowInfo changed", traceContext.getTracker());
+ const std::list<DispatcherTouchState::CancellationArgs> cancellations =
+ mTouchStates.updateFromWindowInfo(displayId);
+ for (const auto& cancellationArgs : cancellations) {
+ switch (cancellationArgs.mode) {
+ case CancelationOptions::Mode::CANCEL_POINTER_EVENTS:
+ pointerCancellationOptions.deviceId = cancellationArgs.deviceId;
+ synthesizeCancelationEventsForWindowLocked(cancellationArgs.windowHandle,
+ pointerCancellationOptions);
+ break;
+ case CancelationOptions::Mode::CANCEL_HOVER_EVENTS:
+ hoverCancellationOptions.deviceId = cancellationArgs.deviceId;
+ synthesizeCancelationEventsForWindowLocked(cancellationArgs.windowHandle,
+ hoverCancellationOptions);
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Unexpected cancellation Mode");
}
}
- // Check if the hovering should stop because the window is no longer eligible to receive it
- // (for example, if the touchable region changed)
- if (const auto& it = mTouchStatesByDisplay.find(displayId); it != mTouchStatesByDisplay.end()) {
- TouchState& state = it->second;
- for (TouchedWindow& touchedWindow : state.windows) {
- std::vector<DeviceId> erasedDevices = touchedWindow.eraseHoveringPointersIf(
- [this, displayId, &touchedWindow](const PointerProperties& properties, float x,
- float y) REQUIRES(mLock) {
- const bool isStylus = properties.toolType == ToolType::STYLUS;
- const ui::Transform displayTransform = getTransformLocked(displayId);
- const bool stillAcceptsTouch =
- windowAcceptsTouchAt(*touchedWindow.windowHandle->getInfo(),
- displayId, x, y, isStylus, displayTransform);
- return !stillAcceptsTouch;
- });
-
- for (DeviceId deviceId : erasedDevices) {
- CancelationOptions options(CancelationOptions::Mode::CANCEL_HOVER_EVENTS,
- "WindowInfo changed",
- traceContext.getTracker());
- options.deviceId = deviceId;
- synthesizeCancelationEventsForWindowLocked(touchedWindow.windowHandle, options);
- }
- }
+ // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We
+ // could just clear the state here.
+ if (mDragState && mDragState->dragWindow->getInfo()->displayId == displayId &&
+ std::find(windowHandles.begin(), windowHandles.end(), mDragState->dragWindow) ==
+ windowHandles.end()) {
+ ALOGI("Drag window went away: %s", mDragState->dragWindow->getName().c_str());
+ sendDropWindowCommandLocked(nullptr, 0, 0);
+ mDragState.reset();
}
// Release information for windows that are no longer present.
@@ -5499,22 +5467,87 @@
// Otherwise, they might stick around until the window handle is destroyed
// which might not happen until the next GC.
for (const sp<WindowInfoHandle>& oldWindowHandle : oldWindowHandles) {
- if (getWindowHandleLocked(oldWindowHandle) == nullptr) {
- if (DEBUG_FOCUS) {
- ALOGD("Window went away: %s", oldWindowHandle->getName().c_str());
- }
+ if (!mWindowInfos.isWindowPresent(oldWindowHandle)) {
+ LOG_IF(INFO, DEBUG_FOCUS) << "Window went away: " << oldWindowHandle->getName();
oldWindowHandle->releaseChannel();
}
}
}
+std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>
+InputDispatcher::DispatcherTouchState::updateFromWindowInfo(ui::LogicalDisplayId displayId) {
+ std::list<CancellationArgs> cancellations;
+ forTouchAndCursorStatesOnDisplay(displayId, [&](TouchState& state) {
+ cancellations.splice(cancellations.end(),
+ eraseRemovedWindowsFromWindowInfo(state, displayId));
+ cancellations.splice(cancellations.end(),
+ updateHoveringStateFromWindowInfo(state, displayId));
+ return false;
+ });
+ return cancellations;
+}
+
+std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>
+InputDispatcher::DispatcherTouchState::eraseRemovedWindowsFromWindowInfo(
+ TouchState& state, ui::LogicalDisplayId displayId) {
+ std::list<CancellationArgs> cancellations;
+ for (auto it = state.windows.begin(); it != state.windows.end();) {
+ TouchedWindow& touchedWindow = *it;
+ if (mWindowInfos.isWindowPresent(touchedWindow.windowHandle)) {
+ it++;
+ continue;
+ }
+ LOG(INFO) << "Touched window was removed: " << touchedWindow.windowHandle->getName()
+ << " in display %" << displayId;
+ cancellations.emplace_back(touchedWindow.windowHandle,
+ CancelationOptions::Mode::CANCEL_POINTER_EVENTS);
+ // Since we are about to drop the touch, cancel the events for the wallpaper as well.
+ if (touchedWindow.targetFlags.test(InputTarget::Flags::FOREGROUND) &&
+ touchedWindow.windowHandle->getInfo()->inputConfig.test(
+ gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
+ for (const DeviceId deviceId : touchedWindow.getTouchingDeviceIds()) {
+ if (const auto& ww = state.getWallpaperWindow(deviceId); ww != nullptr) {
+ cancellations.emplace_back(ww, CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
+ deviceId);
+ }
+ }
+ }
+ it = state.windows.erase(it);
+ }
+ return cancellations;
+}
+
+std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>
+InputDispatcher::DispatcherTouchState::updateHoveringStateFromWindowInfo(
+ TouchState& state, ui::LogicalDisplayId displayId) {
+ std::list<CancellationArgs> cancellations;
+ // Check if the hovering should stop because the window is no longer eligible to receive it
+ // (for example, if the touchable region changed)
+ ui::Transform displayTransform = mWindowInfos.getDisplayTransform(displayId);
+ for (TouchedWindow& touchedWindow : state.windows) {
+ std::vector<DeviceId> erasedDevices = touchedWindow.eraseHoveringPointersIf(
+ [&](const PointerProperties& properties, float x, float y) {
+ const bool isStylus = properties.toolType == ToolType::STYLUS;
+ const bool stillAcceptsTouch =
+ windowAcceptsTouchAt(*touchedWindow.windowHandle->getInfo(), displayId,
+ x, y, isStylus, displayTransform);
+ return !stillAcceptsTouch;
+ });
+
+ for (DeviceId deviceId : erasedDevices) {
+ cancellations.emplace_back(touchedWindow.windowHandle,
+ CancelationOptions::Mode::CANCEL_HOVER_EVENTS, deviceId);
+ }
+ }
+ return cancellations;
+}
+
void InputDispatcher::setFocusedApplication(
ui::LogicalDisplayId displayId,
const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) {
- if (DEBUG_FOCUS) {
- ALOGD("setFocusedApplication displayId=%s %s", displayId.toString().c_str(),
- inputApplicationHandle ? inputApplicationHandle->getName().c_str() : "<nullptr>");
- }
+ LOG_IF(INFO, DEBUG_FOCUS) << "setFocusedApplication displayId=" << displayId.toString() << " "
+ << (inputApplicationHandle ? inputApplicationHandle->getName()
+ : "<nullptr>");
{ // acquire lock
std::scoped_lock _l(mLock);
setFocusedApplicationLocked(displayId, inputApplicationHandle);
@@ -5564,9 +5597,7 @@
* display. The display-specified events won't be affected.
*/
void InputDispatcher::setFocusedDisplay(ui::LogicalDisplayId displayId) {
- if (DEBUG_FOCUS) {
- ALOGD("setFocusedDisplay displayId=%s", displayId.toString().c_str());
- }
+ LOG_IF(INFO, DEBUG_FOCUS) << "setFocusedDisplay displayId=" << displayId.toString();
{ // acquire lock
std::scoped_lock _l(mLock);
ScopedSyntheticEventTracer traceContext(mTracer);
@@ -5576,7 +5607,7 @@
mFocusResolver.getFocusedWindowToken(mFocusedDisplayId);
if (oldFocusedWindowToken != nullptr) {
const auto windowHandle =
- getWindowHandleLocked(oldFocusedWindowToken, mFocusedDisplayId);
+ mWindowInfos.findWindowHandle(oldFocusedWindowToken, mFocusedDisplayId);
if (windowHandle == nullptr) {
LOG(FATAL) << __func__ << ": Previously focused token did not have a window";
}
@@ -5620,9 +5651,8 @@
}
void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
- if (DEBUG_FOCUS) {
- ALOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
- }
+ LOG_IF(INFO, DEBUG_FOCUS) << "setInputDispatchMode: enabled=" << enabled
+ << ", frozen=" << frozen;
bool changed;
{ // acquire lock
@@ -5652,9 +5682,7 @@
}
void InputDispatcher::setInputFilterEnabled(bool enabled) {
- if (DEBUG_FOCUS) {
- ALOGD("setInputFilterEnabled: enabled=%d", enabled);
- }
+ LOG_IF(INFO, DEBUG_FOCUS) << "setInputFilterEnabled: enabled=" << enabled;
{ // acquire lock
std::scoped_lock _l(mLock);
@@ -5676,14 +5704,16 @@
bool needWake = false;
{
std::scoped_lock lock(mLock);
- ALOGD_IF(DEBUG_TOUCH_MODE,
- "Request to change touch mode to %s (calling pid=%s, uid=%s, "
- "hasPermission=%s, target displayId=%s, mTouchModePerDisplay[displayId]=%s)",
- toString(inTouchMode), pid.toString().c_str(), uid.toString().c_str(),
- toString(hasPermission), displayId.toString().c_str(),
- mTouchModePerDisplay.count(displayId) == 0
- ? "not set"
- : std::to_string(mTouchModePerDisplay[displayId]).c_str());
+ LOG_IF(INFO, DEBUG_TOUCH_MODE)
+ << "Request to change touch mode to " << toString(inTouchMode)
+ << " (calling pid=" << pid.toString() << ", uid=" << uid.toString()
+ << ", hasPermission=" << toString(hasPermission)
+ << ", target displayId=" << displayId.toString()
+ << ", mTouchModePerDisplay[displayId]="
+ << (mTouchModePerDisplay.count(displayId) == 0
+ ? "not set"
+ : std::to_string(mTouchModePerDisplay[displayId]))
+ << ")";
auto touchModeIt = mTouchModePerDisplay.find(displayId);
if (touchModeIt != mTouchModePerDisplay.end() && touchModeIt->second == inTouchMode) {
@@ -5715,7 +5745,7 @@
if (focusedToken == nullptr) {
return false;
}
- sp<WindowInfoHandle> windowHandle = getWindowHandleLocked(focusedToken);
+ sp<WindowInfoHandle> windowHandle = mWindowInfos.findWindowHandle(focusedToken);
return isWindowOwnedBy(windowHandle, pid, uid);
}
@@ -5723,105 +5753,52 @@
return std::find_if(mInteractionConnectionTokens.begin(), mInteractionConnectionTokens.end(),
[&](const sp<IBinder>& connectionToken) REQUIRES(mLock) {
const sp<WindowInfoHandle> windowHandle =
- getWindowHandleLocked(connectionToken);
+ mWindowInfos.findWindowHandle(connectionToken);
return isWindowOwnedBy(windowHandle, pid, uid);
}) != mInteractionConnectionTokens.end();
}
void InputDispatcher::setMaximumObscuringOpacityForTouch(float opacity) {
- if (opacity < 0 || opacity > 1) {
- LOG_ALWAYS_FATAL("Maximum obscuring opacity for touch should be >= 0 and <= 1");
- return;
- }
-
std::scoped_lock lock(mLock);
- mMaximumObscuringOpacityForTouch = opacity;
-}
-
-std::tuple<TouchState*, TouchedWindow*, ui::LogicalDisplayId>
-InputDispatcher::findTouchStateWindowAndDisplayLocked(const sp<IBinder>& token) {
- for (auto& [displayId, state] : mTouchStatesByDisplay) {
- for (TouchedWindow& w : state.windows) {
- if (w.windowHandle->getToken() == token) {
- return std::make_tuple(&state, &w, displayId);
- }
- }
- }
- return std::make_tuple(nullptr, nullptr, ui::LogicalDisplayId::DEFAULT);
-}
-
-std::tuple<const TouchState*, const TouchedWindow*, ui::LogicalDisplayId>
-InputDispatcher::findTouchStateWindowAndDisplayLocked(const sp<IBinder>& token) const {
- return const_cast<InputDispatcher*>(this)->findTouchStateWindowAndDisplayLocked(token);
-}
-
-bool InputDispatcher::windowHasTouchingPointersLocked(const sp<WindowInfoHandle>& windowHandle,
- DeviceId deviceId) const {
- const auto& [touchState, touchedWindow, _] =
- findTouchStateWindowAndDisplayLocked(windowHandle->getToken());
- if (touchState == nullptr) {
- // No touching pointers at all
- return false;
- }
- return touchState->hasTouchingPointers(deviceId);
+ mWindowInfos.setMaximumObscuringOpacityForTouch(opacity);
}
bool InputDispatcher::transferTouchGesture(const sp<IBinder>& fromToken, const sp<IBinder>& toToken,
bool isDragDrop) {
if (fromToken == toToken) {
- if (DEBUG_FOCUS) {
- ALOGD("Trivial transfer to same window.");
- }
+ LOG_IF(INFO, DEBUG_FOCUS) << "Trivial transfer to same window.";
return true;
}
{ // acquire lock
std::scoped_lock _l(mLock);
- // Find the target touch state and touched window by fromToken.
- auto [state, touchedWindow, displayId] = findTouchStateWindowAndDisplayLocked(fromToken);
+ ScopedSyntheticEventTracer traceContext(mTracer);
+ CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
+ "transferring touch from this window to another window",
+ traceContext.getTracker());
- if (state == nullptr || touchedWindow == nullptr) {
- ALOGD("Touch transfer failed because from window is not being touched.");
- return false;
- }
- std::set<DeviceId> deviceIds = touchedWindow->getTouchingDeviceIds();
- if (deviceIds.size() != 1) {
- LOG(INFO) << "Can't transfer touch. Currently touching devices: " << dumpSet(deviceIds)
- << " for window: " << touchedWindow->dump();
- return false;
- }
- const DeviceId deviceId = *deviceIds.begin();
-
- const sp<WindowInfoHandle> fromWindowHandle = touchedWindow->windowHandle;
- const sp<WindowInfoHandle> toWindowHandle = getWindowHandleLocked(toToken, displayId);
- if (!toWindowHandle) {
- ALOGW("Cannot transfer touch because the transfer target window was not found.");
+ auto result = mTouchStates.transferTouchGesture(fromToken, toToken);
+ if (!result.has_value()) {
return false;
}
- if (DEBUG_FOCUS) {
- ALOGD("%s: fromWindowHandle=%s, toWindowHandle=%s", __func__,
- touchedWindow->windowHandle->getName().c_str(),
- toWindowHandle->getName().c_str());
+ const auto& [toWindowHandle, deviceId, pointers, cancellations, pointerDowns] =
+ result.value();
+
+ for (const auto& cancellationArgs : cancellations) {
+ LOG_ALWAYS_FATAL_IF(cancellationArgs.mode !=
+ CancelationOptions::Mode::CANCEL_POINTER_EVENTS);
+ LOG_ALWAYS_FATAL_IF(cancellationArgs.deviceId.has_value());
+ synthesizeCancelationEventsForWindowLocked(cancellationArgs.windowHandle, options);
}
- // Erase old window.
- ftl::Flags<InputTarget::Flags> oldTargetFlags = touchedWindow->targetFlags;
- std::vector<PointerProperties> pointers = touchedWindow->getTouchingPointers(deviceId);
- state->removeWindowByToken(fromToken);
-
- // Add new window.
- nsecs_t downTimeInTarget = now();
- ftl::Flags<InputTarget::Flags> newTargetFlags =
- oldTargetFlags & (InputTarget::Flags::SPLIT);
- if (canReceiveForegroundTouches(*toWindowHandle->getInfo())) {
- newTargetFlags |= InputTarget::Flags::FOREGROUND;
+ for (const auto& pointerDownArgs : pointerDowns) {
+ synthesizePointerDownEventsForConnectionLocked(pointerDownArgs.downTimeInTarget,
+ pointerDownArgs.connection,
+ pointerDownArgs.targetFlags,
+ traceContext.getTracker());
}
- // Transferring touch focus using this API should not effect the focused window.
- newTargetFlags |= InputTarget::Flags::NO_FOCUS_CHANGE;
- state->addOrUpdateWindow(toWindowHandle, InputTarget::DispatchMode::AS_IS, newTargetFlags,
- deviceId, pointers, downTimeInTarget);
// Store the dragging window.
if (isDragDrop) {
@@ -5834,30 +5811,6 @@
const size_t id = pointers.begin()->id;
mDragState = std::make_unique<DragState>(toWindowHandle, deviceId, id);
}
-
- // Synthesize cancel for old window and down for new window.
- ScopedSyntheticEventTracer traceContext(mTracer);
- std::shared_ptr<Connection> fromConnection = getConnectionLocked(fromToken);
- std::shared_ptr<Connection> toConnection = getConnectionLocked(toToken);
- if (fromConnection != nullptr && toConnection != nullptr) {
- fromConnection->inputState.mergePointerStateTo(toConnection->inputState);
- CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
- "transferring touch from this window to another window",
- traceContext.getTracker());
- synthesizeCancelationEventsForWindowLocked(fromWindowHandle, options, fromConnection);
-
- // Check if the wallpaper window should deliver the corresponding event.
- transferWallpaperTouch(oldTargetFlags, newTargetFlags, fromWindowHandle, toWindowHandle,
- *state, deviceId, pointers, traceContext.getTracker());
-
- // Because new window may have a wallpaper window, it will merge input state from it
- // parent window, after this the firstNewPointerIdx in input state will be reset, then
- // it will cause new move event be thought inconsistent, so we should synthesize the
- // down event after it reset.
- synthesizePointerDownEventsForConnectionLocked(downTimeInTarget, toConnection,
- newTargetFlags,
- traceContext.getTracker());
- }
} // release lock
// Wake up poll loop since it may need to make new input dispatching choices.
@@ -5865,33 +5818,110 @@
return true;
}
+std::optional<std::tuple<sp<gui::WindowInfoHandle>, DeviceId, std::vector<PointerProperties>,
+ std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>,
+ std::list<InputDispatcher::DispatcherTouchState::PointerDownArgs>>>
+InputDispatcher::DispatcherTouchState::transferTouchGesture(const sp<android::IBinder>& fromToken,
+ const sp<android::IBinder>& toToken) {
+ // Find the target touch state and touched window by fromToken.
+ auto touchStateWindowAndDisplay = findTouchStateWindowAndDisplay(fromToken);
+ if (!touchStateWindowAndDisplay.has_value()) {
+ ALOGD("Touch transfer failed because from window is not being touched.");
+ return std::nullopt;
+ }
+
+ auto [state, touchedWindow, displayId] = touchStateWindowAndDisplay.value();
+ std::set<DeviceId> deviceIds = touchedWindow.getTouchingDeviceIds();
+ if (deviceIds.size() != 1) {
+ LOG(INFO) << "Can't transfer touch. Currently touching devices: "
+ << dumpContainer(deviceIds) << " for window: " << touchedWindow.dump();
+ return std::nullopt;
+ }
+ const DeviceId deviceId = *deviceIds.begin();
+
+ const sp<WindowInfoHandle> fromWindowHandle = touchedWindow.windowHandle;
+ // TouchState displayId may not be same as window displayId, we need to lookup for toToken on
+ // all connected displays.
+ const sp<WindowInfoHandle> toWindowHandle =
+ mWindowInfos.findWindowHandleOnConnectedDisplays(toToken, displayId);
+ if (!toWindowHandle) {
+ ALOGW("Cannot transfer touch because the transfer target window was not found.");
+ return std::nullopt;
+ }
+
+ LOG_IF(INFO, DEBUG_FOCUS) << __func__ << ": fromWindowHandle=" << fromWindowHandle->getName()
+ << ", toWindowHandle=" << toWindowHandle->getName();
+
+ // Erase old window.
+ ftl::Flags<InputTarget::Flags> oldTargetFlags = touchedWindow.targetFlags;
+ std::vector<PointerProperties> pointers = touchedWindow.getTouchingPointers(deviceId);
+ state.removeWindowByToken(fromToken);
+
+ // Add new window.
+ nsecs_t downTimeInTarget = now();
+ ftl::Flags<InputTarget::Flags> newTargetFlags = oldTargetFlags & (InputTarget::Flags::SPLIT);
+ if (canReceiveForegroundTouches(*toWindowHandle->getInfo())) {
+ newTargetFlags |= InputTarget::Flags::FOREGROUND;
+ }
+ // Transferring touch focus using this API should not effect the focused window.
+ newTargetFlags |= InputTarget::Flags::NO_FOCUS_CHANGE;
+ state.addOrUpdateWindow(toWindowHandle, InputTarget::DispatchMode::AS_IS, newTargetFlags,
+ deviceId, pointers, downTimeInTarget);
+
+ // Synthesize cancel for old window and down for new window.
+ std::shared_ptr<Connection> fromConnection = mConnectionManager.getConnection(fromToken);
+ std::shared_ptr<Connection> toConnection = mConnectionManager.getConnection(toToken);
+ std::list<CancellationArgs> cancellations;
+ std::list<PointerDownArgs> pointerDowns;
+ if (fromConnection != nullptr && toConnection != nullptr) {
+ fromConnection->inputState.mergePointerStateTo(toConnection->inputState);
+ cancellations.emplace_back(fromWindowHandle,
+ CancelationOptions::Mode::CANCEL_POINTER_EVENTS);
+
+ // Check if the wallpaper window should deliver the corresponding event.
+ auto [wallpaperCancellations, wallpaperPointerDowns] =
+ transferWallpaperTouch(fromWindowHandle, toWindowHandle, state, deviceId, pointers,
+ oldTargetFlags, newTargetFlags);
+
+ cancellations.splice(cancellations.end(), wallpaperCancellations);
+ pointerDowns.splice(pointerDowns.end(), wallpaperPointerDowns);
+
+ // Because new window may have a wallpaper window, it will merge input state from it
+ // parent window, after this the firstNewPointerIdx in input state will be reset, then
+ // it will cause new move event be thought inconsistent, so we should synthesize the
+ // down event after it reset.
+ pointerDowns.emplace_back(downTimeInTarget, toConnection, newTargetFlags);
+ }
+
+ return std::make_tuple(toWindowHandle, deviceId, pointers, cancellations, pointerDowns);
+}
+
/**
* Get the touched foreground window on the given display.
* Return null if there are no windows touched on that display, or if more than one foreground
* window is being touched.
*/
-sp<WindowInfoHandle> InputDispatcher::findTouchedForegroundWindowLocked(
+sp<WindowInfoHandle> InputDispatcher::DispatcherTouchState::findTouchedForegroundWindow(
ui::LogicalDisplayId displayId) const {
- auto stateIt = mTouchStatesByDisplay.find(displayId);
- if (stateIt == mTouchStatesByDisplay.end()) {
- ALOGI("No touch state on display %s", displayId.toString().c_str());
- return nullptr;
- }
-
- const TouchState& state = stateIt->second;
sp<WindowInfoHandle> touchedForegroundWindow;
- // If multiple foreground windows are touched, return nullptr
- for (const TouchedWindow& window : state.windows) {
- if (window.targetFlags.test(InputTarget::Flags::FOREGROUND)) {
- if (touchedForegroundWindow != nullptr) {
- ALOGI("Two or more foreground windows: %s and %s",
- touchedForegroundWindow->getName().c_str(),
- window.windowHandle->getName().c_str());
- return nullptr;
+ forTouchAndCursorStatesOnDisplay(displayId, [&](const TouchState& state) {
+ // If multiple foreground windows are touched, return nullptr
+ for (const TouchedWindow& window : state.windows) {
+ if (window.targetFlags.test(InputTarget::Flags::FOREGROUND)) {
+ if (touchedForegroundWindow != nullptr) {
+ ALOGI("Two or more foreground windows: %s and %s",
+ touchedForegroundWindow->getName().c_str(),
+ window.windowHandle->getName().c_str());
+ touchedForegroundWindow = nullptr;
+ return true;
+ }
+ touchedForegroundWindow = window.windowHandle;
}
- touchedForegroundWindow = window.windowHandle;
}
- }
+ return false;
+ });
+ ALOGI_IF(touchedForegroundWindow == nullptr,
+ "No touch state or no touched foreground window on display %d", displayId.val());
return touchedForegroundWindow;
}
@@ -5901,14 +5931,15 @@
sp<IBinder> fromToken;
{ // acquire lock
std::scoped_lock _l(mLock);
- sp<WindowInfoHandle> toWindowHandle = getWindowHandleLocked(destChannelToken, displayId);
+ sp<WindowInfoHandle> toWindowHandle =
+ mWindowInfos.findWindowHandle(destChannelToken, displayId);
if (toWindowHandle == nullptr) {
ALOGW("Could not find window associated with token=%p on display %s",
destChannelToken.get(), displayId.toString().c_str());
return false;
}
- sp<WindowInfoHandle> from = findTouchedForegroundWindowLocked(displayId);
+ sp<WindowInfoHandle> from = mTouchStates.findTouchedForegroundWindow(displayId);
if (from == nullptr) {
ALOGE("Could not find a source window in %s for %p", __func__, destChannelToken.get());
return false;
@@ -5921,9 +5952,7 @@
}
void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
- if (DEBUG_FOCUS) {
- ALOGD("Resetting and dropping all events (%s).", reason);
- }
+ LOG_IF(INFO, DEBUG_FOCUS) << "Resetting and dropping all events (" << reason << ").";
ScopedSyntheticEventTracer traceContext(mTracer);
CancelationOptions options(CancelationOptions::Mode::CANCEL_ALL_EVENTS, reason,
@@ -5936,7 +5965,7 @@
resetNoFocusedWindowTimeoutLocked();
mAnrTracker.clear();
- mTouchStatesByDisplay.clear();
+ mTouchStates.clear();
}
void InputDispatcher::logDispatchStateLocked() const {
@@ -5960,7 +5989,7 @@
std::string windowName = "None";
if (mWindowTokenWithPointerCapture) {
const sp<WindowInfoHandle> captureWindowHandle =
- getWindowHandleLocked(mWindowTokenWithPointerCapture);
+ mWindowInfos.findWindowHandle(mWindowTokenWithPointerCapture);
windowName = captureWindowHandle ? captureWindowHandle->getName().c_str()
: "token has capture without window";
}
@@ -5994,59 +6023,19 @@
dump += mFocusResolver.dump();
dump += dumpPointerCaptureStateLocked();
- if (!mTouchStatesByDisplay.empty()) {
- dump += StringPrintf(INDENT "TouchStatesByDisplay:\n");
- for (const auto& [displayId, state] : mTouchStatesByDisplay) {
- std::string touchStateDump = addLinePrefix(state.dump(), INDENT2);
- dump += INDENT2 + displayId.toString() + " : " + touchStateDump;
- }
- } else {
- dump += INDENT "TouchStates: <no displays touched>\n";
- }
+ dump += addLinePrefix(mTouchStates.dump(), INDENT);
if (mDragState) {
dump += StringPrintf(INDENT "DragState:\n");
mDragState->dump(dump, INDENT2);
}
- if (!mWindowHandlesByDisplay.empty()) {
- for (const auto& [displayId, windowHandles] : mWindowHandlesByDisplay) {
- dump += StringPrintf(INDENT "Display: %s\n", displayId.toString().c_str());
- if (const auto& it = mDisplayInfos.find(displayId); it != mDisplayInfos.end()) {
- const auto& displayInfo = it->second;
- dump += StringPrintf(INDENT2 "logicalSize=%dx%d\n", displayInfo.logicalWidth,
- displayInfo.logicalHeight);
- displayInfo.transform.dump(dump, "transform", INDENT4);
- } else {
- dump += INDENT2 "No DisplayInfo found!\n";
- }
-
- if (!windowHandles.empty()) {
- dump += INDENT2 "Windows:\n";
- for (size_t i = 0; i < windowHandles.size(); i++) {
- dump += StringPrintf(INDENT3 "%zu: %s", i,
- streamableToString(*windowHandles[i]).c_str());
- }
- } else {
- dump += INDENT2 "Windows: <none>\n";
- }
- }
- } else {
- dump += INDENT "Displays: <none>\n";
- }
-
- if (!mGlobalMonitorsByDisplay.empty()) {
- for (const auto& [displayId, monitors] : mGlobalMonitorsByDisplay) {
- dump += StringPrintf(INDENT "Global monitors on display %s:\n",
- displayId.toString().c_str());
- dumpMonitors(dump, monitors);
- }
- } else {
- dump += INDENT "Global Monitors: <none>\n";
- }
+ dump += addLinePrefix(mWindowInfos.dumpDisplayAndWindowInfo(), INDENT);
const nsecs_t currentTime = now();
+ dump += addLinePrefix(mConnectionManager.dump(currentTime), INDENT);
+
// Dump recently dispatched or dropped events from oldest to newest.
if (!mRecentQueue.empty()) {
dump += StringPrintf(INDENT "RecentQueue: length=%zu\n", mRecentQueue.size());
@@ -6088,37 +6077,6 @@
dump += INDENT "CommandQueue: <empty>\n";
}
- if (!mConnectionsByToken.empty()) {
- dump += INDENT "Connections:\n";
- for (const auto& [token, connection] : mConnectionsByToken) {
- dump += StringPrintf(INDENT2 "%i: channelName='%s', "
- "status=%s, monitor=%s, responsive=%s\n",
- connection->inputPublisher.getChannel().getFd(),
- connection->getInputChannelName().c_str(),
- ftl::enum_string(connection->status).c_str(),
- toString(connection->monitor), toString(connection->responsive));
-
- if (!connection->outboundQueue.empty()) {
- dump += StringPrintf(INDENT3 "OutboundQueue: length=%zu\n",
- connection->outboundQueue.size());
- dump += dumpQueue(connection->outboundQueue, currentTime);
- }
-
- if (!connection->waitQueue.empty()) {
- dump += StringPrintf(INDENT3 "WaitQueue: length=%zu\n",
- connection->waitQueue.size());
- dump += dumpQueue(connection->waitQueue, currentTime);
- }
- std::string inputStateDump = streamableToString(connection->inputState);
- if (!inputStateDump.empty()) {
- dump += INDENT3 "InputState: ";
- dump += inputStateDump + "\n";
- }
- }
- } else {
- dump += INDENT "Connections: <none>\n";
- }
-
if (!mTouchModePerDisplay.empty()) {
dump += INDENT "TouchModePerDisplay:\n";
for (const auto& [displayId, touchMode] : mTouchModePerDisplay) {
@@ -6139,16 +6097,6 @@
dump += mTracer == nullptr ? "Disabled" : "Enabled";
}
-void InputDispatcher::dumpMonitors(std::string& dump, const std::vector<Monitor>& monitors) const {
- const size_t numMonitors = monitors.size();
- for (size_t i = 0; i < numMonitors; i++) {
- const Monitor& monitor = monitors[i];
- const std::shared_ptr<Connection>& connection = monitor.connection;
- dump += StringPrintf(INDENT2 "%zu: '%s', ", i, connection->getInputChannelName().c_str());
- dump += "\n";
- }
-}
-
class LooperEventCallback : public LooperCallback {
public:
LooperEventCallback(std::function<int(int events)> callback) : mCallback(callback) {}
@@ -6159,9 +6107,7 @@
};
Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) {
- if (DEBUG_CHANNEL_CREATION) {
- ALOGD("channel '%s' ~ createInputChannel", name.c_str());
- }
+ LOG_IF(INFO, DEBUG_CHANNEL_CREATION) << "channel '" << name << "' ~ createInputChannel";
std::unique_ptr<InputChannel> serverChannel;
std::unique_ptr<InputChannel> clientChannel;
@@ -6174,21 +6120,10 @@
{ // acquire lock
std::scoped_lock _l(mLock);
const sp<IBinder>& token = serverChannel->getConnectionToken();
- const int fd = serverChannel->getFd();
- std::shared_ptr<Connection> connection =
- std::make_shared<Connection>(std::move(serverChannel), /*monitor=*/false,
- mIdGenerator);
-
- auto [_, inserted] = mConnectionsByToken.try_emplace(token, connection);
- if (!inserted) {
- ALOGE("Created a new connection, but the token %p is already known", token.get());
- }
-
std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
this, std::placeholders::_1, token);
- mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, sp<LooperEventCallback>::make(callback),
- nullptr);
+ mConnectionManager.createConnection(std::move(serverChannel), mIdGenerator, callback);
} // release lock
// Wake the looper because some connections have changed.
@@ -6214,23 +6149,11 @@
}
const sp<IBinder>& token = serverChannel->getConnectionToken();
- const int fd = serverChannel->getFd();
- std::shared_ptr<Connection> connection =
- std::make_shared<Connection>(std::move(serverChannel), /*monitor=*/true,
- mIdGenerator);
-
- auto [_, inserted] = mConnectionsByToken.emplace(token, connection);
- if (!inserted) {
- ALOGE("Created a new connection, but the token %p is already known", token.get());
- }
-
std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
this, std::placeholders::_1, token);
- mGlobalMonitorsByDisplay[displayId].emplace_back(connection, pid);
-
- mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, sp<LooperEventCallback>::make(callback),
- nullptr);
+ mConnectionManager.createGlobalInputMonitor(displayId, std::move(serverChannel),
+ mIdGenerator, pid, callback);
}
// Wake the looper because some connections have changed.
@@ -6241,8 +6164,14 @@
status_t InputDispatcher::removeInputChannel(const sp<IBinder>& connectionToken) {
{ // acquire lock
std::scoped_lock _l(mLock);
+ std::shared_ptr<Connection> connection = mConnectionManager.getConnection(connectionToken);
+ if (connection == nullptr) {
+ // Connection can be removed via socket hang up or an explicit call to
+ // 'removeInputChannel'
+ return BAD_VALUE;
+ }
- status_t status = removeInputChannelLocked(connectionToken, /*notify=*/false);
+ status_t status = removeInputChannelLocked(connection, /*notify=*/false);
if (status) {
return status;
}
@@ -6254,30 +6183,18 @@
return OK;
}
-status_t InputDispatcher::removeInputChannelLocked(const sp<IBinder>& connectionToken,
+status_t InputDispatcher::removeInputChannelLocked(const std::shared_ptr<Connection>& connection,
bool notify) {
- std::shared_ptr<Connection> connection = getConnectionLocked(connectionToken);
- if (connection == nullptr) {
- // Connection can be removed via socket hang up or an explicit call to 'removeInputChannel'
- return BAD_VALUE;
- }
+ LOG_ALWAYS_FATAL_IF(connection == nullptr);
+ abortBrokenDispatchCycleLocked(connection, notify);
- removeConnectionLocked(connection);
+ mAnrTracker.eraseToken(connection->getToken());
+ mConnectionManager.removeConnection(connection);
- if (connection->monitor) {
- removeMonitorChannelLocked(connectionToken);
- }
-
- mLooper->removeFd(connection->inputPublisher.getChannel().getFd());
-
- nsecs_t currentTime = now();
- abortBrokenDispatchCycleLocked(currentTime, connection, notify);
-
- connection->status = Connection::Status::ZOMBIE;
return OK;
}
-void InputDispatcher::removeMonitorChannelLocked(const sp<IBinder>& connectionToken) {
+void InputDispatcher::ConnectionManager::removeMonitorChannel(const sp<IBinder>& connectionToken) {
for (auto it = mGlobalMonitorsByDisplay.begin(); it != mGlobalMonitorsByDisplay.end();) {
auto& [displayId, monitors] = *it;
std::erase_if(monitors, [connectionToken](const Monitor& monitor) {
@@ -6298,49 +6215,70 @@
}
status_t InputDispatcher::pilferPointersLocked(const sp<IBinder>& token) {
- const std::shared_ptr<Connection> requestingConnection = getConnectionLocked(token);
+ const std::shared_ptr<Connection> requestingConnection =
+ mConnectionManager.getConnection(token);
if (!requestingConnection) {
LOG(WARNING)
<< "Attempted to pilfer pointers from an un-registered channel or invalid token";
return BAD_VALUE;
}
- auto [statePtr, windowPtr, displayId] = findTouchStateWindowAndDisplayLocked(token);
- if (statePtr == nullptr || windowPtr == nullptr) {
- LOG(WARNING)
- << "Attempted to pilfer points from a channel without any on-going pointer streams."
- " Ignoring.";
- return BAD_VALUE;
- }
- std::set<int32_t> deviceIds = windowPtr->getTouchingDeviceIds();
- if (deviceIds.empty()) {
- LOG(WARNING) << "Can't pilfer: no touching devices in window: " << windowPtr->dump();
- return BAD_VALUE;
+ const auto result = mTouchStates.pilferPointers(token, *requestingConnection);
+ if (!result.ok()) {
+ return result.error().code();
}
ScopedSyntheticEventTracer traceContext(mTracer);
+ CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
+ "input channel stole pointer stream", traceContext.getTracker());
+ const auto cancellations = *result;
+ for (const auto& cancellationArgs : cancellations) {
+ LOG_ALWAYS_FATAL_IF(cancellationArgs.mode !=
+ CancelationOptions::Mode::CANCEL_POINTER_EVENTS);
+ options.displayId = cancellationArgs.displayId;
+ options.deviceId = cancellationArgs.deviceId;
+ options.pointerIds = cancellationArgs.pointerIds;
+ synthesizeCancelationEventsForWindowLocked(cancellationArgs.windowHandle, options);
+ }
+ return OK;
+}
+
+base::Result<std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>, status_t>
+InputDispatcher::DispatcherTouchState::pilferPointers(const sp<IBinder>& token,
+ const Connection& requestingConnection) {
+ auto touchStateWindowAndDisplay = findTouchStateWindowAndDisplay(token);
+ if (!touchStateWindowAndDisplay.has_value()) {
+ LOG(WARNING)
+ << "Attempted to pilfer points from a channel without any on-going pointer streams."
+ " Ignoring.";
+ return Error(BAD_VALUE);
+ }
+
+ auto [state, window, displayId] = touchStateWindowAndDisplay.value();
+
+ std::set<int32_t> deviceIds = window.getTouchingDeviceIds();
+ if (deviceIds.empty()) {
+ LOG(WARNING) << "Can't pilfer: no touching devices in window: " << window.dump();
+ return Error(BAD_VALUE);
+ }
+
+ std::list<CancellationArgs> cancellations;
for (const DeviceId deviceId : deviceIds) {
- TouchState& state = *statePtr;
- TouchedWindow& window = *windowPtr;
// Send cancel events to all the input channels we're stealing from.
- CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
- "input channel stole pointer stream", traceContext.getTracker());
- options.deviceId = deviceId;
- options.displayId = displayId;
std::vector<PointerProperties> pointers = window.getTouchingPointers(deviceId);
std::bitset<MAX_POINTER_ID + 1> pointerIds = getPointerIds(pointers);
- options.pointerIds = pointerIds;
-
std::string canceledWindows;
for (const TouchedWindow& w : state.windows) {
if (w.windowHandle->getToken() != token) {
- synthesizeCancelationEventsForWindowLocked(w.windowHandle, options);
+ cancellations.emplace_back(w.windowHandle,
+ CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
+ deviceId, displayId, pointerIds);
canceledWindows += canceledWindows.empty() ? "[" : ", ";
canceledWindows += w.windowHandle->getName();
}
}
canceledWindows += canceledWindows.empty() ? "[]" : "]";
- LOG(INFO) << "Channel " << requestingConnection->getInputChannelName()
+ LOG(INFO) << "Channel " << requestingConnection.getInputChannelName()
<< " is stealing input gesture for device " << deviceId << " from "
<< canceledWindows;
@@ -6350,14 +6288,14 @@
state.cancelPointersForWindowsExcept(deviceId, pointerIds, token);
}
- return OK;
+ return cancellations;
}
void InputDispatcher::requestPointerCapture(const sp<IBinder>& windowToken, bool enabled) {
{ // acquire lock
std::scoped_lock _l(mLock);
if (DEBUG_FOCUS) {
- const sp<WindowInfoHandle> windowHandle = getWindowHandleLocked(windowToken);
+ const sp<WindowInfoHandle> windowHandle = mWindowInfos.findWindowHandle(windowToken);
ALOGI("Request to %s Pointer Capture from: %s.", enabled ? "enable" : "disable",
windowHandle != nullptr ? windowHandle->getName().c_str()
: "token without window");
@@ -6404,7 +6342,8 @@
} // release lock
}
-std::optional<gui::Pid> InputDispatcher::findMonitorPidByTokenLocked(const sp<IBinder>& token) {
+std::optional<gui::Pid> InputDispatcher::ConnectionManager::findMonitorPidByToken(
+ const sp<IBinder>& token) const {
for (const auto& [_, monitors] : mGlobalMonitorsByDisplay) {
for (const Monitor& monitor : monitors) {
if (monitor.connection->getToken() == token) {
@@ -6415,7 +6354,7 @@
return std::nullopt;
}
-std::shared_ptr<Connection> InputDispatcher::getConnectionLocked(
+std::shared_ptr<Connection> InputDispatcher::ConnectionManager::getConnection(
const sp<IBinder>& inputConnectionToken) const {
if (inputConnectionToken == nullptr) {
return nullptr;
@@ -6430,19 +6369,6 @@
return nullptr;
}
-std::string InputDispatcher::getConnectionNameLocked(const sp<IBinder>& connectionToken) const {
- std::shared_ptr<Connection> connection = getConnectionLocked(connectionToken);
- if (connection == nullptr) {
- return "<nullptr>";
- }
- return connection->getInputChannelName();
-}
-
-void InputDispatcher::removeConnectionLocked(const std::shared_ptr<Connection>& connection) {
- mAnrTracker.eraseToken(connection->getToken());
- mConnectionsByToken.erase(connection->getToken());
-}
-
void InputDispatcher::doDispatchCycleFinishedCommand(nsecs_t finishTime,
const std::shared_ptr<Connection>& connection,
uint32_t seq, bool handled,
@@ -6497,17 +6423,17 @@
}
traceWaitQueueLength(*connection);
if (fallbackKeyEntry && connection->status == Connection::Status::NORMAL) {
- const auto windowHandle = getWindowHandleLocked(connection->getToken());
+ const auto windowHandle = mWindowInfos.findWindowHandle(connection->getToken());
// Only dispatch fallbacks if there is a window for the connection.
if (windowHandle != nullptr) {
- const auto inputTarget =
- createInputTargetLocked(windowHandle, InputTarget::DispatchMode::AS_IS,
- dispatchEntry->targetFlags,
- fallbackKeyEntry->downTime);
- if (inputTarget.has_value()) {
- enqueueDispatchEntryLocked(connection, std::move(fallbackKeyEntry),
- *inputTarget);
- }
+ nsecs_t downTime = fallbackKeyEntry->downTime;
+ enqueueDispatchEntryLocked(connection, std::move(fallbackKeyEntry),
+ createInputTarget(connection, windowHandle,
+ InputTarget::DispatchMode::AS_IS,
+ dispatchEntry->targetFlags,
+ mWindowInfos.getRawTransform(
+ *windowHandle->getInfo()),
+ downTime));
}
}
releaseDispatchEntry(std::move(dispatchEntry));
@@ -6561,7 +6487,7 @@
ns2ms(currentWait),
oldestEntry.eventEntry->getDescription().c_str());
sp<IBinder> connectionToken = connection->getToken();
- updateLastAnrStateLocked(getWindowHandleLocked(connectionToken), reason);
+ updateLastAnrStateLocked(mWindowInfos.findWindowHandle(connectionToken), reason);
processConnectionUnresponsiveLocked(*connection, std::move(reason));
@@ -6612,24 +6538,27 @@
void InputDispatcher::doInterceptKeyBeforeDispatchingCommand(const sp<IBinder>& focusedWindowToken,
const KeyEntry& entry) {
const KeyEvent event = createKeyEvent(entry);
+ std::variant<nsecs_t, KeyEntry::InterceptKeyResult> interceptResult;
nsecs_t delay = 0;
{ // release lock
scoped_unlock unlock(mLock);
android::base::Timer t;
- delay = mPolicy.interceptKeyBeforeDispatching(focusedWindowToken, event, entry.policyFlags);
+ interceptResult =
+ mPolicy.interceptKeyBeforeDispatching(focusedWindowToken, event, entry.policyFlags);
if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
ALOGW("Excessive delay in interceptKeyBeforeDispatching; took %s ms",
std::to_string(t.duration().count()).c_str());
}
} // acquire lock
- if (delay < 0) {
- entry.interceptKeyResult = KeyEntry::InterceptKeyResult::SKIP;
- } else if (delay == 0) {
- entry.interceptKeyResult = KeyEntry::InterceptKeyResult::CONTINUE;
- } else {
+ if (std::holds_alternative<KeyEntry::InterceptKeyResult>(interceptResult)) {
+ entry.interceptKeyResult = std::get<KeyEntry::InterceptKeyResult>(interceptResult);
+ return;
+ }
+
+ if (std::holds_alternative<nsecs_t>(interceptResult)) {
entry.interceptKeyResult = KeyEntry::InterceptKeyResult::TRY_AGAIN_LATER;
- entry.interceptKeyWakeupTime = now() + delay;
+ entry.interceptKeyWakeupTime = now() + std::get<nsecs_t>(interceptResult);
}
}
@@ -6664,12 +6593,12 @@
if (connection.monitor) {
ALOGW("Monitor %s is unresponsive: %s", connection.getInputChannelName().c_str(),
reason.c_str());
- pid = findMonitorPidByTokenLocked(connectionToken);
+ pid = mConnectionManager.findMonitorPidByToken(connectionToken);
} else {
// The connection is a window
ALOGW("Window %s is unresponsive: %s", connection.getInputChannelName().c_str(),
reason.c_str());
- const sp<WindowInfoHandle> handle = getWindowHandleLocked(connectionToken);
+ const sp<WindowInfoHandle> handle = mWindowInfos.findWindowHandle(connectionToken);
if (handle != nullptr) {
pid = handle->getInfo()->ownerPid;
}
@@ -6684,10 +6613,10 @@
const sp<IBinder>& connectionToken = connection.getToken();
std::optional<gui::Pid> pid;
if (connection.monitor) {
- pid = findMonitorPidByTokenLocked(connectionToken);
+ pid = mConnectionManager.findMonitorPidByToken(connectionToken);
} else {
// The connection is a window
- const sp<WindowInfoHandle> handle = getWindowHandleLocked(connectionToken);
+ const sp<WindowInfoHandle> handle = mWindowInfos.findWindowHandle(connectionToken);
if (handle != nullptr) {
pid = handle->getInfo()->ownerPid;
}
@@ -6729,12 +6658,11 @@
// then cancel the associated fallback key, if any.
if (fallbackKeyCode) {
// Dispatch the unhandled key to the policy with the cancel flag.
- if (DEBUG_OUTBOUND_EVENT_DETAILS) {
- ALOGD("Unhandled key event: Asking policy to cancel fallback action. "
- "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
- keyEntry.keyCode, keyEntry.action, keyEntry.repeatCount,
- keyEntry.policyFlags);
- }
+ LOG_IF(INFO, DEBUG_OUTBOUND_EVENT_DETAILS)
+ << "Unhandled key event: Asking policy to cancel fallback action. keyCode="
+ << keyEntry.keyCode << ", action=" << keyEntry.action
+ << ", repeatCount=" << keyEntry.repeatCount << ", policyFlags=0x" << std::hex
+ << keyEntry.policyFlags;
KeyEvent event = createKeyEvent(keyEntry);
event.setFlags(event.getFlags() | AKEY_EVENT_FLAG_CANCELED);
@@ -6752,7 +6680,7 @@
// Cancel the fallback key, but only if we still have a window for the channel.
// It could have been removed during the policy call.
if (*fallbackKeyCode != AKEYCODE_UNKNOWN) {
- const auto windowHandle = getWindowHandleLocked(connection->getToken());
+ const auto windowHandle = mWindowInfos.findWindowHandle(connection->getToken());
if (windowHandle != nullptr) {
CancelationOptions options(CancelationOptions::Mode::CANCEL_FALLBACK_EVENTS,
"application handled the original non-fallback key "
@@ -6771,21 +6699,22 @@
// Then ask the policy what to do with it.
bool initialDown = keyEntry.action == AKEY_EVENT_ACTION_DOWN && keyEntry.repeatCount == 0;
if (!fallbackKeyCode && !initialDown) {
- if (DEBUG_OUTBOUND_EVENT_DETAILS) {
- ALOGD("Unhandled key event: Skipping unhandled key event processing "
- "since this is not an initial down. "
- "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
- originalKeyCode, keyEntry.action, keyEntry.repeatCount, keyEntry.policyFlags);
- }
+ LOG_IF(INFO, DEBUG_OUTBOUND_EVENT_DETAILS)
+ << "Unhandled key event: Skipping unhandled key event processing since this is "
+ "not an initial down. keyCode="
+ << originalKeyCode << ", action=" << keyEntry.action
+ << ", repeatCount=" << keyEntry.repeatCount << ", policyFlags=0x" << std::hex
+ << keyEntry.policyFlags;
return {};
}
// Dispatch the unhandled key to the policy.
- if (DEBUG_OUTBOUND_EVENT_DETAILS) {
- ALOGD("Unhandled key event: Asking policy to perform fallback action. "
- "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
- keyEntry.keyCode, keyEntry.action, keyEntry.repeatCount, keyEntry.policyFlags);
- }
+ LOG_IF(INFO, DEBUG_OUTBOUND_EVENT_DETAILS)
+ << "Unhandled key event: Asking policy to perform fallback action. keyCode="
+ << keyEntry.keyCode << ", action=" << keyEntry.action
+ << ", repeatCount=" << keyEntry.repeatCount << ", policyFlags=0x" << std::hex
+ << keyEntry.policyFlags;
+ ;
KeyEvent event = createKeyEvent(keyEntry);
mLock.unlock();
@@ -6809,14 +6738,15 @@
// The fallback keycode cannot change at any other point in the lifecycle.
if (initialDown) {
if (fallback) {
- *fallbackKeyCode = event.getKeyCode();
+ fallbackKeyCode = event.getKeyCode();
} else {
- *fallbackKeyCode = AKEYCODE_UNKNOWN;
+ fallbackKeyCode = AKEYCODE_UNKNOWN;
}
connection->inputState.setFallbackKey(originalKeyCode, *fallbackKeyCode);
}
- ALOG_ASSERT(fallbackKeyCode);
+ LOG_IF(FATAL, !fallbackKeyCode)
+ << "fallbackKeyCode is not initialized. initialDown = " << initialDown;
// Cancel the fallback key if the policy decides not to send it anymore.
// We will continue to dispatch the key to the policy but we will no
@@ -6837,7 +6767,7 @@
}
}
- const auto windowHandle = getWindowHandleLocked(connection->getToken());
+ const auto windowHandle = mWindowInfos.findWindowHandle(connection->getToken());
if (windowHandle != nullptr) {
CancelationOptions options(CancelationOptions::Mode::CANCEL_FALLBACK_EVENTS,
"canceling fallback, policy no longer desires it",
@@ -6881,16 +6811,13 @@
newEntry->traceTracker =
mTracer->traceDerivedEvent(*newEntry, *keyEntry.traceTracker);
}
- if (DEBUG_OUTBOUND_EVENT_DETAILS) {
- ALOGD("Unhandled key event: Dispatching fallback key. "
- "originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x",
- originalKeyCode, *fallbackKeyCode, keyEntry.metaState);
- }
+ LOG_IF(INFO, DEBUG_OUTBOUND_EVENT_DETAILS)
+ << "Unhandled key event: Dispatching fallback key. originalKeyCode="
+ << originalKeyCode << ", fallbackKeyCode=" << *fallbackKeyCode
+ << ", fallbackMetaState=0x" << std::hex << keyEntry.metaState;
return newEntry;
} else {
- if (DEBUG_OUTBOUND_EVENT_DETAILS) {
- ALOGD("Unhandled key event: No fallback key.");
- }
+ LOG_IF(INFO, DEBUG_OUTBOUND_EVENT_DETAILS) << "Unhandled key event: No fallback key.";
// Report the key as unhandled, since there is no fallback key.
mReporter->reportUnhandledKey(keyEntry.id);
@@ -6979,7 +6906,7 @@
std::scoped_lock _l(mLock);
std::optional<FocusResolver::FocusChanges> changes =
mFocusResolver.setFocusedWindow(request,
- getWindowHandlesLocked(
+ mWindowInfos.getWindowHandlesForDisplay(
ui::LogicalDisplayId{request.displayId}));
ScopedSyntheticEventTracer traceContext(mTracer);
if (changes) {
@@ -6997,7 +6924,7 @@
if (changes.oldFocus) {
const auto resolvedWindow = removedFocusedWindowHandle != nullptr
? removedFocusedWindowHandle
- : getWindowHandleLocked(changes.oldFocus, changes.displayId);
+ : mWindowInfos.findWindowHandle(changes.oldFocus, changes.displayId);
if (resolvedWindow == nullptr) {
LOG(FATAL) << __func__ << ": Previously focused token did not have a window";
}
@@ -7031,7 +6958,7 @@
return;
}
- ALOGD_IF(DEBUG_FOCUS, "Disabling Pointer Capture because the window lost focus.");
+ LOG_IF(INFO, DEBUG_FOCUS) << "Disabling Pointer Capture because the window lost focus.";
if (mCurrentPointerCaptureRequest.isEnable()) {
setPointerCaptureLocked(nullptr);
@@ -7101,13 +7028,6 @@
for (const auto& info : update.windowInfos) {
handlesPerDisplay.emplace(info.displayId, std::vector<sp<WindowInfoHandle>>());
handlesPerDisplay[info.displayId].push_back(sp<WindowInfoHandle>::make(info));
- if (input_flags::split_all_touches()) {
- handlesPerDisplay[info.displayId]
- .back()
- ->editInfo()
- ->setInputConfig(android::gui::WindowInfo::InputConfig::PREVENT_SPLITTING,
- false);
- }
}
{ // acquire lock
@@ -7115,14 +7035,10 @@
// Ensure that we have an entry created for all existing displays so that if a displayId has
// no windows, we can tell that the windows were removed from the display.
- for (const auto& [displayId, _] : mWindowHandlesByDisplay) {
- handlesPerDisplay[displayId];
- }
+ mWindowInfos.forEachDisplayId(
+ [&](ui::LogicalDisplayId displayId) { handlesPerDisplay[displayId]; });
- mDisplayInfos.clear();
- for (const auto& displayInfo : update.displayInfos) {
- mDisplayInfos.emplace(displayInfo.displayId, displayInfo);
- }
+ mWindowInfos.setDisplayInfos(update.displayInfos);
for (const auto& [displayId, handles] : handlesPerDisplay) {
setInputWindowsLocked(handles, displayId);
@@ -7139,12 +7055,13 @@
mLooper->wake();
}
-bool InputDispatcher::shouldDropInput(
- const EventEntry& entry, const sp<android::gui::WindowInfoHandle>& windowHandle) const {
+bool InputDispatcher::shouldDropInput(const EventEntry& entry,
+ const sp<WindowInfoHandle>& windowHandle,
+ const DispatcherWindowInfo& windowInfos) {
if (windowHandle->getInfo()->inputConfig.test(WindowInfo::InputConfig::DROP_INPUT) ||
(windowHandle->getInfo()->inputConfig.test(
WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED) &&
- isWindowObscuredLocked(windowHandle))) {
+ windowInfos.isWindowObscured(windowHandle))) {
ALOGW("Dropping %s event targeting %s as requested by the input configuration {%s} on "
"display %s.",
ftl::enum_string(entry.type).c_str(), windowHandle->getName().c_str(),
@@ -7169,7 +7086,7 @@
"cancel current touch", traceContext.getTracker());
synthesizeCancelationEventsForAllConnectionsLocked(options);
- mTouchStatesByDisplay.clear();
+ mTouchStates.clear();
}
// Wake up poll loop since there might be work to do.
mLooper->wake();
@@ -7180,11 +7097,10 @@
mMonitorDispatchingTimeout = timeout;
}
-void InputDispatcher::slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
- const sp<WindowInfoHandle>& oldWindowHandle,
- const sp<WindowInfoHandle>& newWindowHandle,
- TouchState& state, const MotionEntry& entry,
- std::vector<InputTarget>& targets) const {
+void InputDispatcher::DispatcherTouchState::slipWallpaperTouch(
+ ftl::Flags<InputTarget::Flags> targetFlags, const sp<WindowInfoHandle>& oldWindowHandle,
+ const sp<WindowInfoHandle>& newWindowHandle, TouchState& state, const MotionEntry& entry,
+ std::vector<InputTarget>& targets, std::function<void()> dump) {
LOG_IF(FATAL, entry.getPointerCount() != 1) << "Entry not eligible for slip: " << entry;
const DeviceId deviceId = entry.deviceId;
const PointerProperties& pointerProperties = entry.pointerProperties[0];
@@ -7197,16 +7113,17 @@
const sp<WindowInfoHandle> oldWallpaper =
oldHasWallpaper ? state.getWallpaperWindow(deviceId) : nullptr;
const sp<WindowInfoHandle> newWallpaper =
- newHasWallpaper ? findWallpaperWindowBelow(newWindowHandle) : nullptr;
+ newHasWallpaper ? mWindowInfos.findWallpaperWindowBelow(newWindowHandle) : nullptr;
if (oldWallpaper == newWallpaper) {
return;
}
if (oldWallpaper != nullptr) {
const TouchedWindow& oldTouchedWindow = state.getTouchedWindow(oldWallpaper);
- addPointerWindowTargetLocked(oldWallpaper, InputTarget::DispatchMode::SLIPPERY_EXIT,
- oldTouchedWindow.targetFlags, getPointerIds(pointers),
- oldTouchedWindow.getDownTimeInTarget(deviceId), targets);
+ addPointerWindowTarget(oldWallpaper, InputTarget::DispatchMode::SLIPPERY_EXIT,
+ oldTouchedWindow.targetFlags, getPointerIds(pointers),
+ oldTouchedWindow.getDownTimeInTarget(deviceId),
+ /*pointerDisplayId=*/std::nullopt, dump, targets);
state.removeTouchingPointerFromWindow(deviceId, pointerProperties.id, oldWallpaper);
}
@@ -7218,12 +7135,14 @@
}
}
-void InputDispatcher::transferWallpaperTouch(
+std::pair<std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>,
+ std::list<InputDispatcher::DispatcherTouchState::PointerDownArgs>>
+InputDispatcher::DispatcherTouchState::transferWallpaperTouch(
+ const sp<gui::WindowInfoHandle> fromWindowHandle,
+ const sp<gui::WindowInfoHandle> toWindowHandle, TouchState& state,
+ android::DeviceId deviceId, const std::vector<PointerProperties>& pointers,
ftl::Flags<InputTarget::Flags> oldTargetFlags,
- ftl::Flags<InputTarget::Flags> newTargetFlags, const sp<WindowInfoHandle> fromWindowHandle,
- const sp<WindowInfoHandle> toWindowHandle, TouchState& state, DeviceId deviceId,
- const std::vector<PointerProperties>& pointers,
- const std::unique_ptr<trace::EventTrackerInterface>& traceTracker) {
+ ftl::Flags<InputTarget::Flags> newTargetFlags) {
const bool oldHasWallpaper = oldTargetFlags.test(InputTarget::Flags::FOREGROUND) &&
fromWindowHandle->getInfo()->inputConfig.test(
gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER);
@@ -7234,16 +7153,16 @@
const sp<WindowInfoHandle> oldWallpaper =
oldHasWallpaper ? state.getWallpaperWindow(deviceId) : nullptr;
const sp<WindowInfoHandle> newWallpaper =
- newHasWallpaper ? findWallpaperWindowBelow(toWindowHandle) : nullptr;
+ newHasWallpaper ? mWindowInfos.findWallpaperWindowBelow(toWindowHandle) : nullptr;
if (oldWallpaper == newWallpaper) {
- return;
+ return {};
}
+ std::list<CancellationArgs> cancellations;
+ std::list<PointerDownArgs> pointerDowns;
if (oldWallpaper != nullptr) {
- CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
- "transferring touch focus to another window", traceTracker);
state.removeWindowByToken(oldWallpaper->getToken());
- synthesizeCancelationEventsForWindowLocked(oldWallpaper, options);
+ cancellations.emplace_back(oldWallpaper, CancelationOptions::Mode::CANCEL_POINTER_EVENTS);
}
if (newWallpaper != nullptr) {
@@ -7255,21 +7174,22 @@
state.addOrUpdateWindow(newWallpaper, InputTarget::DispatchMode::AS_IS, wallpaperFlags,
deviceId, pointers, downTimeInTarget);
std::shared_ptr<Connection> wallpaperConnection =
- getConnectionLocked(newWallpaper->getToken());
+ mConnectionManager.getConnection(newWallpaper->getToken());
if (wallpaperConnection != nullptr) {
std::shared_ptr<Connection> toConnection =
- getConnectionLocked(toWindowHandle->getToken());
+ mConnectionManager.getConnection(toWindowHandle->getToken());
toConnection->inputState.mergePointerStateTo(wallpaperConnection->inputState);
- synthesizePointerDownEventsForConnectionLocked(downTimeInTarget, wallpaperConnection,
- wallpaperFlags, traceTracker);
+ pointerDowns.emplace_back(downTimeInTarget, wallpaperConnection, wallpaperFlags);
}
+ pointerDowns.emplace_back(downTimeInTarget, wallpaperConnection, wallpaperFlags);
}
+ return {cancellations, pointerDowns};
}
-sp<WindowInfoHandle> InputDispatcher::findWallpaperWindowBelow(
+sp<WindowInfoHandle> InputDispatcher::DispatcherWindowInfo::findWallpaperWindowBelow(
const sp<WindowInfoHandle>& windowHandle) const {
const std::vector<sp<WindowInfoHandle>>& windowHandles =
- getWindowHandlesLocked(windowHandle->getInfo()->displayId);
+ getWindowHandlesForDisplay(windowHandle->getInfo()->displayId);
bool foundWindow = false;
for (const sp<WindowInfoHandle>& otherHandle : windowHandles) {
if (!foundWindow && otherHandle != windowHandle) {
@@ -7301,18 +7221,7 @@
ui::LogicalDisplayId displayId, DeviceId deviceId,
int32_t pointerId) {
std::scoped_lock _l(mLock);
- auto touchStateIt = mTouchStatesByDisplay.find(displayId);
- if (touchStateIt == mTouchStatesByDisplay.end()) {
- return false;
- }
- for (const TouchedWindow& window : touchStateIt->second.windows) {
- if (window.windowHandle->getToken() == token &&
- (window.hasTouchingPointer(deviceId, pointerId) ||
- window.hasHoveringPointer(deviceId, pointerId))) {
- return true;
- }
- }
- return false;
+ return mTouchStates.isPointerInWindow(token, displayId, deviceId, pointerId);
}
void InputDispatcher::setInputMethodConnectionIsActive(bool isActive) {
@@ -7322,4 +7231,392 @@
}
}
+void InputDispatcher::setDisplayTopology(
+ const android::DisplayTopologyGraph& displayTopologyGraph) {
+ std::scoped_lock _l(mLock);
+ mWindowInfos.setDisplayTopology(displayTopologyGraph);
+}
+
+InputDispatcher::ConnectionManager::ConnectionManager(const sp<android::Looper>& looper)
+ : mLooper(looper) {}
+
+// This destructor is required to ensure cleanup of each input connection, so that the fd is
+// removed from the looper.
+InputDispatcher::ConnectionManager::~ConnectionManager() {
+ while (!mConnectionsByToken.empty()) {
+ std::shared_ptr<Connection> connection = mConnectionsByToken.begin()->second;
+ removeConnection(connection);
+ }
+}
+
+void InputDispatcher::ConnectionManager::forEachGlobalMonitorConnection(
+ std::function<void(const std::shared_ptr<Connection>&)> f) const {
+ for (const auto& [_, monitors] : mGlobalMonitorsByDisplay) {
+ for (const Monitor& monitor : monitors) {
+ f(monitor.connection);
+ }
+ }
+}
+
+void InputDispatcher::ConnectionManager::forEachGlobalMonitorConnection(
+ ui::LogicalDisplayId displayId,
+ std::function<void(const std::shared_ptr<Connection>&)> f) const {
+ auto monitorsIt = mGlobalMonitorsByDisplay.find(displayId);
+ if (monitorsIt == mGlobalMonitorsByDisplay.end()) return;
+
+ for (const Monitor& monitor : monitorsIt->second) {
+ f(monitor.connection);
+ }
+}
+
+void InputDispatcher::ConnectionManager::createGlobalInputMonitor(
+ ui::LogicalDisplayId displayId, std::unique_ptr<InputChannel>&& inputChannel,
+ const android::IdGenerator& idGenerator, gui::Pid pid, std::function<int(int)> callback) {
+ const int fd = inputChannel->getFd();
+ std::shared_ptr<Connection> connection =
+ std::make_shared<Connection>(std::move(inputChannel), /*monitor=*/true, idGenerator);
+ sp<IBinder> token = connection->getToken();
+ auto [_, inserted] = mConnectionsByToken.emplace(token, connection);
+ if (!inserted) {
+ ALOGE("Created a new connection, but the token %p is already known", token.get());
+ }
+ mGlobalMonitorsByDisplay[displayId].emplace_back(connection, pid);
+
+ mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, sp<LooperEventCallback>::make(callback), nullptr);
+}
+
+void InputDispatcher::ConnectionManager::createConnection(
+ std::unique_ptr<InputChannel>&& inputChannel, const android::IdGenerator& idGenerator,
+ std::function<int(int)> callback) {
+ const int fd = inputChannel->getFd();
+ std::shared_ptr<Connection> connection =
+ std::make_shared<Connection>(std::move(inputChannel), /*monitor=*/false, idGenerator);
+ sp<IBinder> token = connection->getToken();
+ auto [_, inserted] = mConnectionsByToken.try_emplace(token, connection);
+ if (!inserted) {
+ ALOGE("Created a new connection, but the token %p is already known", token.get());
+ }
+
+ mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, sp<LooperEventCallback>::make(callback), nullptr);
+}
+
+status_t InputDispatcher::ConnectionManager::removeConnection(
+ const std::shared_ptr<Connection>& connection) {
+ mConnectionsByToken.erase(connection->getToken());
+
+ if (connection->monitor) {
+ removeMonitorChannel(connection->getToken());
+ }
+
+ mLooper->removeFd(connection->inputPublisher.getChannel().getFd());
+
+ connection->status = Connection::Status::ZOMBIE;
+ return OK;
+}
+
+std::string InputDispatcher::ConnectionManager::dump(nsecs_t currentTime) const {
+ std::string dump;
+ if (!mGlobalMonitorsByDisplay.empty()) {
+ for (const auto& [displayId, monitors] : mGlobalMonitorsByDisplay) {
+ dump += StringPrintf("Global monitors on display %s:\n", displayId.toString().c_str());
+ const size_t numMonitors = monitors.size();
+ for (size_t i = 0; i < numMonitors; i++) {
+ const Monitor& monitor = monitors[i];
+ const std::shared_ptr<Connection>& connection = monitor.connection;
+ dump += StringPrintf(INDENT "%zu: '%s', ", i,
+ connection->getInputChannelName().c_str());
+ dump += "\n";
+ }
+ }
+ } else {
+ dump += "Global Monitors: <none>\n";
+ }
+
+ if (!mConnectionsByToken.empty()) {
+ dump += "Connections:\n";
+ for (const auto& [token, connection] : mConnectionsByToken) {
+ dump += StringPrintf(INDENT "%i: channelName='%s', "
+ "status=%s, monitor=%s, responsive=%s\n",
+ connection->inputPublisher.getChannel().getFd(),
+ connection->getInputChannelName().c_str(),
+ ftl::enum_string(connection->status).c_str(),
+ toString(connection->monitor), toString(connection->responsive));
+
+ if (!connection->outboundQueue.empty()) {
+ dump += StringPrintf(INDENT2 "OutboundQueue: length=%zu\n",
+ connection->outboundQueue.size());
+ dump += dumpQueue(connection->outboundQueue, currentTime);
+ }
+
+ if (!connection->waitQueue.empty()) {
+ dump += StringPrintf(INDENT2 "WaitQueue: length=%zu\n",
+ connection->waitQueue.size());
+ dump += dumpQueue(connection->waitQueue, currentTime);
+ }
+ std::string inputStateDump = streamableToString(connection->inputState);
+ if (!inputStateDump.empty()) {
+ dump += INDENT2 "InputState: ";
+ dump += inputStateDump + "\n";
+ }
+ }
+ } else {
+ dump += "Connections: <none>\n";
+ }
+ return dump;
+}
+
+void InputDispatcher::DispatcherWindowInfo::setMaximumObscuringOpacityForTouch(float opacity) {
+ if (opacity < 0 || opacity > 1) {
+ LOG_ALWAYS_FATAL("Maximum obscuring opacity for touch should be >= 0 and <= 1");
+ }
+ mMaximumObscuringOpacityForTouch = opacity;
+}
+
+void InputDispatcher::DispatcherWindowInfo::setDisplayTopology(
+ const DisplayTopologyGraph& displayTopologyGraph) {
+ mTopology = displayTopologyGraph;
+}
+
+InputDispatcher::DispatcherTouchState::DispatcherTouchState(const DispatcherWindowInfo& windowInfos,
+ const ConnectionManager& connections)
+ : mWindowInfos(windowInfos), mConnectionManager(connections) {}
+
+ftl::Flags<InputTarget::Flags> InputDispatcher::DispatcherTouchState::getTargetFlags(
+ const sp<WindowInfoHandle>& targetWindow, vec2 targetPosition, bool isSplit) {
+ ftl::Flags<InputTarget::Flags> targetFlags;
+ if (canReceiveForegroundTouches(*targetWindow->getInfo())) {
+ // There should only be one touched window that can be "foreground" for the pointer.
+ targetFlags |= InputTarget::Flags::FOREGROUND;
+ }
+ if (isSplit) {
+ targetFlags |= InputTarget::Flags::SPLIT;
+ }
+ if (mWindowInfos.isWindowObscuredAtPoint(targetWindow, targetPosition.x, targetPosition.y)) {
+ targetFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED;
+ } else if (mWindowInfos.isWindowObscured(targetWindow)) {
+ targetFlags |= InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
+ }
+ return targetFlags;
+}
+
+bool InputDispatcher::DispatcherTouchState::hasTouchingOrHoveringPointers(
+ ui::LogicalDisplayId displayId, int32_t deviceId) const {
+ bool hasTouchingOrHoveringPointers = false;
+ forTouchAndCursorStatesOnDisplay(displayId, [&](const TouchState& state) {
+ hasTouchingOrHoveringPointers =
+ state.hasTouchingPointers(deviceId) || state.hasHoveringPointers(deviceId);
+ return hasTouchingOrHoveringPointers;
+ });
+ return hasTouchingOrHoveringPointers;
+}
+
+bool InputDispatcher::DispatcherTouchState::isPointerInWindow(const sp<android::IBinder>& token,
+ ui::LogicalDisplayId displayId,
+ android::DeviceId deviceId,
+ int32_t pointerId) const {
+ bool isPointerInWindow = false;
+ forTouchAndCursorStatesOnDisplay(displayId, [&](const TouchState& state) {
+ for (const TouchedWindow& window : state.windows) {
+ if (window.windowHandle->getToken() == token &&
+ (window.hasTouchingPointer(deviceId, pointerId) ||
+ window.hasHoveringPointer(deviceId, pointerId))) {
+ isPointerInWindow = true;
+ return true;
+ }
+ }
+ return false;
+ });
+ return isPointerInWindow;
+}
+
+std::tuple<const sp<gui::WindowInfoHandle>&, ui::LogicalDisplayId>
+InputDispatcher::DispatcherTouchState::findExistingTouchedWindowHandleAndDisplay(
+ const sp<android::IBinder>& token) const {
+ std::optional<std::tuple<const sp<gui::WindowInfoHandle>&, ui::LogicalDisplayId>>
+ touchedWindowHandleAndDisplay;
+ forAllTouchAndCursorStates([&](ui::LogicalDisplayId displayId, const TouchState& state) {
+ for (const TouchedWindow& w : state.windows) {
+ if (w.windowHandle->getToken() == token) {
+ touchedWindowHandleAndDisplay.emplace(std::ref(w.windowHandle), displayId);
+ return true;
+ }
+ }
+ return false;
+ });
+ LOG_ALWAYS_FATAL_IF(!touchedWindowHandleAndDisplay.has_value(),
+ "%s : Touch state is out of sync: No touched window for token", __func__);
+ return touchedWindowHandleAndDisplay.value();
+}
+
+void InputDispatcher::DispatcherTouchState::forAllTouchedWindows(
+ std::function<void(const sp<gui::WindowInfoHandle>&)> f) const {
+ forAllTouchAndCursorStates([&](ui::LogicalDisplayId displayId, const TouchState& state) {
+ for (const TouchedWindow& window : state.windows) {
+ f(window.windowHandle);
+ }
+ return false;
+ });
+}
+
+void InputDispatcher::DispatcherTouchState::forAllTouchedWindowsOnDisplay(
+ ui::LogicalDisplayId displayId,
+ std::function<void(const sp<gui::WindowInfoHandle>&)> f) const {
+ forTouchAndCursorStatesOnDisplay(displayId, [&](const TouchState& state) {
+ for (const TouchedWindow& window : state.windows) {
+ f(window.windowHandle);
+ }
+ return false;
+ });
+}
+
+std::string InputDispatcher::DispatcherTouchState::dump() const {
+ std::string dump;
+ if (mTouchStatesByDisplay.empty()) {
+ dump += "TouchStatesByDisplay: <no displays touched>\n";
+ } else {
+ dump += "TouchStatesByDisplay:\n";
+ for (const auto& [displayId, state] : mTouchStatesByDisplay) {
+ std::string touchStateDump = addLinePrefix(state.dump(), INDENT);
+ dump += INDENT + displayId.toString() + " : " + touchStateDump;
+ }
+ }
+ if (mCursorStateByDisplay.empty()) {
+ dump += "CursorStatesByDisplay: <no displays touched by cursor>\n";
+ } else {
+ dump += "CursorStatesByDisplay:\n";
+ for (const auto& [displayId, state] : mCursorStateByDisplay) {
+ std::string touchStateDump = addLinePrefix(state.dump(), INDENT);
+ dump += INDENT + displayId.toString() + " : " + touchStateDump;
+ }
+ }
+ return dump;
+}
+
+void InputDispatcher::DispatcherTouchState::removeAllPointersForDevice(android::DeviceId deviceId) {
+ forAllTouchAndCursorStates([&](ui::LogicalDisplayId displayId, TouchState& state) {
+ state.removeAllPointersForDevice(deviceId);
+ return false;
+ });
+}
+
+void InputDispatcher::DispatcherTouchState::clear() {
+ mTouchStatesByDisplay.clear();
+ mCursorStateByDisplay.clear();
+}
+
+void InputDispatcher::DispatcherTouchState::saveTouchStateForMotionEntry(
+ const android::inputdispatcher::MotionEntry& entry,
+ android::inputdispatcher::TouchState&& touchState) {
+ if (touchState.windows.empty()) {
+ eraseTouchStateForMotionEntry(entry);
+ return;
+ }
+
+ if (InputFlags::connectedDisplaysCursorEnabled() && isMouseOrTouchpad(entry.source)) {
+ mCursorStateByDisplay[mWindowInfos.getPrimaryDisplayId(entry.displayId)] =
+ std::move(touchState);
+ } else {
+ mTouchStatesByDisplay[entry.displayId] = std::move(touchState);
+ }
+}
+
+void InputDispatcher::DispatcherTouchState::eraseTouchStateForMotionEntry(
+ const android::inputdispatcher::MotionEntry& entry) {
+ if (InputFlags::connectedDisplaysCursorEnabled() && isMouseOrTouchpad(entry.source)) {
+ mCursorStateByDisplay.erase(mWindowInfos.getPrimaryDisplayId(entry.displayId));
+ } else {
+ mTouchStatesByDisplay.erase(entry.displayId);
+ }
+}
+
+const TouchState* InputDispatcher::DispatcherTouchState::getTouchStateForMotionEntry(
+ const android::inputdispatcher::MotionEntry& entry) const {
+ if (InputFlags::connectedDisplaysCursorEnabled() && isMouseOrTouchpad(entry.source)) {
+ auto touchStateIt =
+ mCursorStateByDisplay.find(mWindowInfos.getPrimaryDisplayId(entry.displayId));
+ if (touchStateIt != mCursorStateByDisplay.end()) {
+ return &touchStateIt->second;
+ }
+ } else {
+ auto touchStateIt = mTouchStatesByDisplay.find(entry.displayId);
+ if (touchStateIt != mTouchStatesByDisplay.end()) {
+ return &touchStateIt->second;
+ }
+ }
+ return nullptr;
+}
+
+void InputDispatcher::DispatcherTouchState::forTouchAndCursorStatesOnDisplay(
+ ui::LogicalDisplayId displayId, std::function<bool(const TouchState&)> f) const {
+ const auto touchStateIt = mTouchStatesByDisplay.find(displayId);
+ if (touchStateIt != mTouchStatesByDisplay.end() && f(touchStateIt->second)) {
+ return;
+ }
+
+ // DisplayId for the Cursor state may not be same as supplied displayId if display is part of
+ // topology. Instead we should to check from the topology's primary display.
+ const auto cursorStateIt =
+ mCursorStateByDisplay.find(mWindowInfos.getPrimaryDisplayId(displayId));
+ if (cursorStateIt != mCursorStateByDisplay.end()) {
+ f(cursorStateIt->second);
+ }
+}
+
+void InputDispatcher::DispatcherTouchState::forTouchAndCursorStatesOnDisplay(
+ ui::LogicalDisplayId displayId, std::function<bool(TouchState&)> f) {
+ const_cast<const DispatcherTouchState&>(*this)
+ .forTouchAndCursorStatesOnDisplay(displayId, [&](const TouchState& state) {
+ return f(const_cast<TouchState&>(state));
+ });
+}
+
+void InputDispatcher::DispatcherTouchState::forAllTouchAndCursorStates(
+ std::function<bool(ui::LogicalDisplayId, const TouchState&)> f) const {
+ for (auto& [displayId, state] : mTouchStatesByDisplay) {
+ if (f(displayId, state)) {
+ return;
+ }
+ }
+ for (auto& [displayId, state] : mCursorStateByDisplay) {
+ if (f(displayId, state)) {
+ return;
+ }
+ }
+}
+
+void InputDispatcher::DispatcherTouchState::forAllTouchAndCursorStates(
+ std::function<bool(ui::LogicalDisplayId, TouchState&)> f) {
+ const_cast<const DispatcherTouchState&>(*this).forAllTouchAndCursorStates(
+ [&](ui::LogicalDisplayId displayId, const TouchState& constState) {
+ return f(displayId, const_cast<TouchState&>(constState));
+ });
+}
+
+std::optional<std::tuple<TouchState&, TouchedWindow&, ui::LogicalDisplayId>>
+InputDispatcher::DispatcherTouchState::findTouchStateWindowAndDisplay(
+ const sp<android::IBinder>& token) {
+ std::optional<std::tuple<TouchState&, TouchedWindow&, ui::LogicalDisplayId>>
+ touchStateWindowAndDisplay;
+ forAllTouchAndCursorStates([&](ui::LogicalDisplayId displayId, TouchState& state) {
+ for (TouchedWindow& w : state.windows) {
+ if (w.windowHandle->getToken() == token) {
+ touchStateWindowAndDisplay.emplace(std::ref(state), std::ref(w), displayId);
+ return true;
+ }
+ }
+ return false;
+ });
+ return touchStateWindowAndDisplay;
+}
+
+bool InputDispatcher::DispatcherTouchState::isStylusActiveInDisplay(
+ ui::LogicalDisplayId displayId) const {
+ const auto it = mTouchStatesByDisplay.find(displayId);
+ if (it == mTouchStatesByDisplay.end()) {
+ return false;
+ }
+ const TouchState& state = it->second;
+ return state.hasActiveStylus();
+}
+
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index fade853..38f7825 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -164,6 +164,8 @@
void setInputMethodConnectionIsActive(bool isActive) override;
+ void setDisplayTopology(const DisplayTopologyGraph& displayTopologyGraph) override;
+
private:
enum class DropReason {
NOT_DROPPED,
@@ -224,6 +226,316 @@
/** Stores the latest user-activity poke event times per user activity types. */
std::array<nsecs_t, USER_ACTIVITY_EVENT_LAST + 1> mLastUserActivityTimes GUARDED_BY(mLock);
+ template <typename T>
+ struct StrongPointerHash {
+ std::size_t operator()(const sp<T>& b) const { return std::hash<T*>{}(b.get()); }
+ };
+
+ class ConnectionManager {
+ public:
+ ConnectionManager(const sp<Looper>& lopper);
+ ~ConnectionManager();
+
+ std::shared_ptr<Connection> getConnection(const sp<IBinder>& inputConnectionToken) const;
+
+ // Find a monitor pid by the provided token.
+ std::optional<gui::Pid> findMonitorPidByToken(const sp<IBinder>& token) const;
+ void forEachGlobalMonitorConnection(
+ std::function<void(const std::shared_ptr<Connection>&)> f) const;
+ void forEachGlobalMonitorConnection(
+ ui::LogicalDisplayId displayId,
+ std::function<void(const std::shared_ptr<Connection>&)> f) const;
+
+ void createGlobalInputMonitor(ui::LogicalDisplayId displayId,
+ std::unique_ptr<InputChannel>&& inputChannel,
+ const IdGenerator& idGenerator, gui::Pid pid,
+ std::function<int(int)> callback);
+
+ status_t removeConnection(const std::shared_ptr<Connection>& connection);
+
+ void createConnection(std::unique_ptr<InputChannel>&& inputChannel,
+ const IdGenerator& idGenerator, std::function<int(int)> callback);
+
+ std::string dump(nsecs_t currentTime) const;
+
+ private:
+ const sp<Looper> mLooper;
+
+ // All registered connections mapped by input channel token.
+ std::unordered_map<sp<IBinder>, std::shared_ptr<Connection>, StrongPointerHash<IBinder>>
+ mConnectionsByToken;
+
+ // Input channels that will receive a copy of all input events sent to the provided display.
+ std::unordered_map<ui::LogicalDisplayId, std::vector<Monitor>> mGlobalMonitorsByDisplay;
+
+ void removeMonitorChannel(const sp<IBinder>& connectionToken);
+ };
+
+ ConnectionManager mConnectionManager GUARDED_BY(mLock);
+
+ class DispatcherWindowInfo {
+ public:
+ struct TouchOcclusionInfo {
+ bool hasBlockingOcclusion;
+ float obscuringOpacity;
+ std::string obscuringPackage;
+ gui::Uid obscuringUid = gui::Uid::INVALID;
+ std::vector<std::string> debugInfo;
+ };
+
+ void setWindowHandlesForDisplay(
+ ui::LogicalDisplayId displayId,
+ std::vector<sp<android::gui::WindowInfoHandle>>&& windowHandles);
+
+ void setDisplayInfos(const std::vector<android::gui::DisplayInfo>& displayInfos);
+
+ void removeDisplay(ui::LogicalDisplayId displayId);
+
+ void setMaximumObscuringOpacityForTouch(float opacity);
+
+ void setDisplayTopology(const DisplayTopologyGraph& displayTopologyGraph);
+
+ // Get a reference to window handles by display, return an empty vector if not found.
+ const std::vector<sp<android::gui::WindowInfoHandle>>& getWindowHandlesForDisplay(
+ ui::LogicalDisplayId displayId) const;
+
+ void forEachWindowHandle(
+ std::function<void(const sp<android::gui::WindowInfoHandle>&)> f) const;
+
+ void forEachDisplayId(std::function<void(ui::LogicalDisplayId)> f) const;
+
+ // Get the transform for display, returns Identity-transform if display is missing.
+ ui::Transform getDisplayTransform(ui::LogicalDisplayId displayId) const;
+
+ // Get the raw transform to use for motion events going to the given window. Optionally a
+ // pointer displayId may be supplied if pointer is on a different display from the window.
+ ui::Transform getRawTransform(
+ const android::gui::WindowInfo& windowInfo,
+ std::optional<ui::LogicalDisplayId> pointerDisplayId = std::nullopt) const;
+
+ // Lookup for WindowInfoHandle from token and optionally a display-id. In cases where
+ // display-id is not provided lookup is done for all displays.
+ sp<android::gui::WindowInfoHandle> findWindowHandle(
+ const sp<IBinder>& windowHandleToken,
+ std::optional<ui::LogicalDisplayId> displayId = {}) const;
+
+ // Lookup for WindowInfoHandle from token and a display-id. Lookup is done for all connected
+ // displays in the topology of the queried display.
+ sp<android::gui::WindowInfoHandle> findWindowHandleOnConnectedDisplays(
+ const sp<IBinder>& windowHandleToken, ui::LogicalDisplayId displayId) const;
+
+ bool isWindowPresent(const sp<android::gui::WindowInfoHandle>& windowHandle) const;
+
+ // Returns the touched window at the given location, excluding the ignoreWindow if provided.
+ sp<android::gui::WindowInfoHandle> findTouchedWindowAt(
+ ui::LogicalDisplayId displayId, float x, float y, bool isStylus = false,
+ const sp<android::gui::WindowInfoHandle> ignoreWindow = nullptr) const;
+
+ TouchOcclusionInfo computeTouchOcclusionInfo(
+ const sp<android::gui::WindowInfoHandle>& windowHandle, float x, float y) const;
+
+ bool isWindowObscured(const sp<android::gui::WindowInfoHandle>& windowHandle) const;
+
+ bool isWindowObscuredAtPoint(const sp<android::gui::WindowInfoHandle>& windowHandle,
+ float x, float y) const;
+
+ sp<android::gui::WindowInfoHandle> findWallpaperWindowBelow(
+ const sp<android::gui::WindowInfoHandle>& windowHandle) const;
+
+ bool isTouchTrusted(const TouchOcclusionInfo& occlusionInfo) const;
+
+ // Returns topology's primary display if the display belongs to it, otherwise the
+ // same displayId.
+ ui::LogicalDisplayId getPrimaryDisplayId(ui::LogicalDisplayId displayId) const;
+
+ bool areDisplaysConnected(ui::LogicalDisplayId display1,
+ ui::LogicalDisplayId display2) const;
+
+ std::string dumpDisplayAndWindowInfo() const;
+
+ private:
+ std::vector<ui::LogicalDisplayId> getConnectedDisplays(
+ ui::LogicalDisplayId displayId) const;
+
+ sp<android::gui::WindowInfoHandle> findWindowHandleOnDisplay(
+ const sp<IBinder>& windowHandleToken, ui::LogicalDisplayId displayId) const;
+
+ std::unordered_map<ui::LogicalDisplayId /*displayId*/,
+ std::vector<sp<android::gui::WindowInfoHandle>>>
+ mWindowHandlesByDisplay;
+ std::unordered_map<ui::LogicalDisplayId /*displayId*/, android::gui::DisplayInfo>
+ mDisplayInfos;
+ float mMaximumObscuringOpacityForTouch{1.0f};
+
+ // Topology is initialized with default-constructed value, which is an empty topology until
+ // we receive setDisplayTopology call. Meanwhile we will treat every display as an
+ // independent display.
+ DisplayTopologyGraph mTopology;
+ };
+
+ DispatcherWindowInfo mWindowInfos GUARDED_BY(mLock);
+
+ class DispatcherTouchState {
+ public:
+ struct CancellationArgs {
+ const sp<gui::WindowInfoHandle> windowHandle;
+ CancelationOptions::Mode mode;
+ std::optional<DeviceId> deviceId{std::nullopt};
+ ui::LogicalDisplayId displayId{ui::LogicalDisplayId::INVALID};
+ std::bitset<MAX_POINTER_ID + 1> pointerIds{};
+ };
+
+ struct PointerDownArgs {
+ const nsecs_t downTimeInTarget;
+ const std::shared_ptr<Connection> connection;
+ const ftl::Flags<InputTarget::Flags> targetFlags;
+ };
+
+ DispatcherTouchState(const DispatcherWindowInfo& windowInfos,
+ const ConnectionManager& connections);
+
+ void addPointerWindowTarget(const sp<android::gui::WindowInfoHandle>& windowHandle,
+ InputTarget::DispatchMode dispatchMode,
+ ftl::Flags<InputTarget::Flags> targetFlags,
+ std::bitset<MAX_POINTER_ID + 1> pointerIds,
+ std::optional<nsecs_t> firstDownTimeInTarget,
+ std::optional<ui::LogicalDisplayId> pointerDisplayId,
+ std::function<void()> dump,
+ std::vector<InputTarget>& inputTargets);
+
+ base::Result<std::vector<InputTarget>, android::os::InputEventInjectionResult>
+ findTouchedWindowTargets(nsecs_t currentTime, const MotionEntry& entry,
+ const sp<android::gui::WindowInfoHandle> dragWindow,
+ std::function<void(const MotionEntry&)> addDragEvent,
+ std::function<void()> dump);
+
+ sp<android::gui::WindowInfoHandle> findTouchedForegroundWindow(
+ ui::LogicalDisplayId displayId) const;
+
+ bool hasTouchingOrHoveringPointers(ui::LogicalDisplayId displayId, int32_t deviceId) const;
+
+ bool isPointerInWindow(const sp<android::IBinder>& token, ui::LogicalDisplayId displayId,
+ DeviceId deviceId, int32_t pointerId) const;
+
+ // Find an existing touched windowHandle and display by token.
+ std::tuple<const sp<gui::WindowInfoHandle>&, ui::LogicalDisplayId>
+ findExistingTouchedWindowHandleAndDisplay(const sp<IBinder>& token) const;
+
+ void forAllTouchedWindows(std::function<void(const sp<gui::WindowInfoHandle>&)> f) const;
+
+ void forAllTouchedWindowsOnDisplay(
+ ui::LogicalDisplayId displayId,
+ std::function<void(const sp<gui::WindowInfoHandle>&)> f) const;
+
+ std::string dump() const;
+
+ // Updates the touchState for display from WindowInfo,
+ // returns list of CancellationArgs for every cancelled touch
+ std::list<CancellationArgs> updateFromWindowInfo(ui::LogicalDisplayId displayId);
+
+ void removeAllPointersForDevice(DeviceId deviceId);
+
+ // transfer touch between provided tokens, returns destination WindowHandle, deviceId,
+ // pointers, list of cancelled windows and pointers on successful transfer.
+ std::optional<
+ std::tuple<sp<gui::WindowInfoHandle>, DeviceId, std::vector<PointerProperties>,
+ std::list<CancellationArgs>, std::list<PointerDownArgs>>>
+ transferTouchGesture(const sp<IBinder>& fromToken, const sp<IBinder>& toToken);
+
+ base::Result<std::list<CancellationArgs>, status_t> pilferPointers(
+ const sp<IBinder>& token, const Connection& requestingConnection);
+
+ void clear();
+
+ private:
+ std::unordered_map<ui::LogicalDisplayId, TouchState> mTouchStatesByDisplay;
+
+ // As there can be only one CursorState per topology group, we will treat all displays in
+ // the topology as one connected display-group. These will be identified by
+ // DisplayTopologyGraph::primaryDisplayId.
+ // Cursor on the any of the displays that are not part of the topology will be identified by
+ // the displayId similar to mTouchStatesByDisplay.
+ std::unordered_map<ui::LogicalDisplayId, TouchState> mCursorStateByDisplay;
+
+ // The supplied lambda is invoked for each touch and cursor state of the display.
+ // The function iterates until the lambda returns true, effectively performing a 'break'
+ // from the iteration.
+ void forTouchAndCursorStatesOnDisplay(ui::LogicalDisplayId displayId,
+ std::function<bool(const TouchState&)> f) const;
+
+ void forTouchAndCursorStatesOnDisplay(ui::LogicalDisplayId displayId,
+ std::function<bool(TouchState&)> f);
+
+ // The supplied lambda is invoked for each touchState. The function iterates until
+ // the lambda returns true, effectively performing a 'break' from the iteration.
+ void forAllTouchAndCursorStates(
+ std::function<bool(ui::LogicalDisplayId, const TouchState&)> f) const;
+
+ void forAllTouchAndCursorStates(std::function<bool(ui::LogicalDisplayId, TouchState&)> f);
+
+ std::optional<std::tuple<TouchState&, TouchedWindow&, ui::LogicalDisplayId>>
+ findTouchStateWindowAndDisplay(const sp<IBinder>& token);
+
+ std::pair<std::list<CancellationArgs>, std::list<PointerDownArgs>> transferWallpaperTouch(
+ const sp<gui::WindowInfoHandle> fromWindowHandle,
+ const sp<gui::WindowInfoHandle> toWindowHandle, TouchState& state,
+ DeviceId deviceId, const std::vector<PointerProperties>& pointers,
+ ftl::Flags<InputTarget::Flags> oldTargetFlags,
+ ftl::Flags<InputTarget::Flags> newTargetFlags);
+
+ void saveTouchStateForMotionEntry(const MotionEntry& entry, TouchState&& touchState);
+
+ void eraseTouchStateForMotionEntry(const MotionEntry& entry);
+
+ const TouchState* getTouchStateForMotionEntry(
+ const android::inputdispatcher::MotionEntry& entry) const;
+
+ bool canWindowReceiveMotion(const sp<gui::WindowInfoHandle>& window,
+ const MotionEntry& motionEntry) const;
+
+ // Return true if stylus is currently down anywhere on the specified display,
+ // and false otherwise.
+ bool isStylusActiveInDisplay(ui::LogicalDisplayId displayId) const;
+
+ std::list<CancellationArgs> eraseRemovedWindowsFromWindowInfo(
+ TouchState& state, ui::LogicalDisplayId displayId);
+
+ std::list<CancellationArgs> updateHoveringStateFromWindowInfo(
+ TouchState& state, ui::LogicalDisplayId displayId);
+
+ std::vector<InputTarget> findOutsideTargets(ui::LogicalDisplayId displayId,
+ const sp<gui::WindowInfoHandle>& touchedWindow,
+ int32_t pointerId, std::function<void()> dump);
+
+ /**
+ * Slip the wallpaper touch if necessary.
+ *
+ * @param targetFlags the target flags
+ * @param oldWindowHandle the old window that the touch slipped out of
+ * @param newWindowHandle the new window that the touch is slipping into
+ * @param state the current touch state. This will be updated if necessary to reflect the
+ * new windows that are receiving touch.
+ * @param deviceId the device id of the current motion being processed
+ * @param pointerProperties the pointer properties of the current motion being processed
+ * @param targets the current targets to add the walpaper ones to
+ * @param eventTime the new downTime for the wallpaper target
+ */
+ void slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
+ const sp<android::gui::WindowInfoHandle>& oldWindowHandle,
+ const sp<android::gui::WindowInfoHandle>& newWindowHandle,
+ TouchState& state, const MotionEntry& entry,
+ std::vector<InputTarget>& targets, std::function<void()> dump);
+
+ ftl::Flags<InputTarget::Flags> getTargetFlags(
+ const sp<android::gui::WindowInfoHandle>& targetWindow, vec2 targetPosition,
+ bool isSplit);
+
+ const DispatcherWindowInfo& mWindowInfos;
+ const ConnectionManager& mConnectionManager;
+ };
+
+ DispatcherTouchState mTouchStates GUARDED_BY(mLock);
+
// With each iteration, InputDispatcher nominally processes one queued event,
// a timeout, or a response from an input consumer.
// This method should only be called on the input dispatcher's own thread.
@@ -252,45 +564,8 @@
// to transfer focus to a new application.
std::shared_ptr<const EventEntry> mNextUnblockedEvent GUARDED_BY(mLock);
- sp<android::gui::WindowInfoHandle> findTouchedWindowAtLocked(
- ui::LogicalDisplayId displayId, float x, float y, bool isStylus = false,
- bool ignoreDragWindow = false) const REQUIRES(mLock);
- std::vector<InputTarget> findOutsideTargetsLocked(
- ui::LogicalDisplayId displayId, const sp<android::gui::WindowInfoHandle>& touchedWindow,
- int32_t pointerId) const REQUIRES(mLock);
-
- std::vector<sp<android::gui::WindowInfoHandle>> findTouchedSpyWindowsAtLocked(
- ui::LogicalDisplayId displayId, float x, float y, bool isStylus,
- DeviceId deviceId) const REQUIRES(mLock);
-
- sp<android::gui::WindowInfoHandle> findTouchedForegroundWindowLocked(
- ui::LogicalDisplayId displayId) const REQUIRES(mLock);
-
- std::shared_ptr<Connection> getConnectionLocked(const sp<IBinder>& inputConnectionToken) const
- REQUIRES(mLock);
-
- std::string getConnectionNameLocked(const sp<IBinder>& connectionToken) const REQUIRES(mLock);
-
- void removeConnectionLocked(const std::shared_ptr<Connection>& connection) REQUIRES(mLock);
-
status_t pilferPointersLocked(const sp<IBinder>& token) REQUIRES(mLock);
- template <typename T>
- struct StrongPointerHash {
- std::size_t operator()(const sp<T>& b) const { return std::hash<T*>{}(b.get()); }
- };
-
- // All registered connections mapped by input channel token.
- std::unordered_map<sp<IBinder>, std::shared_ptr<Connection>, StrongPointerHash<IBinder>>
- mConnectionsByToken GUARDED_BY(mLock);
-
- // Find a monitor pid by the provided token.
- std::optional<gui::Pid> findMonitorPidByTokenLocked(const sp<IBinder>& token) REQUIRES(mLock);
-
- // Input channels that will receive a copy of all input events sent to the provided display.
- std::unordered_map<ui::LogicalDisplayId, std::vector<Monitor>> mGlobalMonitorsByDisplay
- GUARDED_BY(mLock);
-
const HmacKeyManager mHmacKeyManager;
const std::array<uint8_t, 32> getSignature(const MotionEntry& motionEntry,
const DispatchEntry& dispatchEntry) const;
@@ -350,7 +625,6 @@
bool mDispatchEnabled GUARDED_BY(mLock);
bool mDispatchFrozen GUARDED_BY(mLock);
bool mInputFilterEnabled GUARDED_BY(mLock);
- float mMaximumObscuringOpacityForTouch GUARDED_BY(mLock);
// This map is not really needed, but it helps a lot with debugging (dumpsys input).
// In the java layer, touch mode states are spread across multiple DisplayContent objects,
@@ -368,28 +642,12 @@
};
sp<gui::WindowInfosListener> mWindowInfoListener;
- std::unordered_map<ui::LogicalDisplayId /*displayId*/,
- std::vector<sp<android::gui::WindowInfoHandle>>>
- mWindowHandlesByDisplay GUARDED_BY(mLock);
- std::unordered_map<ui::LogicalDisplayId /*displayId*/, android::gui::DisplayInfo> mDisplayInfos
- GUARDED_BY(mLock);
void setInputWindowsLocked(
const std::vector<sp<android::gui::WindowInfoHandle>>& inputWindowHandles,
ui::LogicalDisplayId displayId) REQUIRES(mLock);
- // Get a reference to window handles by display, return an empty vector if not found.
- const std::vector<sp<android::gui::WindowInfoHandle>>& getWindowHandlesLocked(
- ui::LogicalDisplayId displayId) const REQUIRES(mLock);
- ui::Transform getTransformLocked(ui::LogicalDisplayId displayId) const REQUIRES(mLock);
- sp<android::gui::WindowInfoHandle> getWindowHandleLocked(
- const sp<IBinder>& windowHandleToken,
- std::optional<ui::LogicalDisplayId> displayId = {}) const REQUIRES(mLock);
- sp<android::gui::WindowInfoHandle> getWindowHandleLocked(
- const sp<android::gui::WindowInfoHandle>& windowHandle) const REQUIRES(mLock);
sp<android::gui::WindowInfoHandle> getFocusedWindowHandleLocked(
ui::LogicalDisplayId displayId) const REQUIRES(mLock);
- bool canWindowReceiveMotionLocked(const sp<android::gui::WindowInfoHandle>& window,
- const MotionEntry& motionEntry) const REQUIRES(mLock);
// Returns all the input targets (with their respective input channels) from the window handles
// passed as argument.
@@ -404,8 +662,6 @@
const std::vector<sp<android::gui::WindowInfoHandle>>& inputWindowHandles,
ui::LogicalDisplayId displayId) REQUIRES(mLock);
- std::unordered_map<ui::LogicalDisplayId /*displayId*/, TouchState> mTouchStatesByDisplay
- GUARDED_BY(mLock);
std::unique_ptr<DragState> mDragState GUARDED_BY(mLock);
void setFocusedApplicationLocked(
@@ -545,26 +801,12 @@
base::Result<sp<android::gui::WindowInfoHandle>, android::os::InputEventInjectionResult>
findFocusedWindowTargetLocked(nsecs_t currentTime, const EventEntry& entry,
nsecs_t& nextWakeupTime) REQUIRES(mLock);
- base::Result<std::vector<InputTarget>, android::os::InputEventInjectionResult>
- findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry& entry) REQUIRES(mLock);
- std::vector<Monitor> selectResponsiveMonitorsLocked(
- const std::vector<Monitor>& gestureMonitors) const REQUIRES(mLock);
- std::optional<InputTarget> createInputTargetLocked(
- const sp<android::gui::WindowInfoHandle>& windowHandle,
- InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags,
- std::optional<nsecs_t> firstDownTimeInTarget) const REQUIRES(mLock);
void addWindowTargetLocked(const sp<android::gui::WindowInfoHandle>& windowHandle,
InputTarget::DispatchMode dispatchMode,
ftl::Flags<InputTarget::Flags> targetFlags,
std::optional<nsecs_t> firstDownTimeInTarget,
std::vector<InputTarget>& inputTargets) const REQUIRES(mLock);
- void addPointerWindowTargetLocked(const sp<android::gui::WindowInfoHandle>& windowHandle,
- InputTarget::DispatchMode dispatchMode,
- ftl::Flags<InputTarget::Flags> targetFlags,
- std::bitset<MAX_POINTER_ID + 1> pointerIds,
- std::optional<nsecs_t> firstDownTimeInTarget,
- std::vector<InputTarget>& inputTargets) const REQUIRES(mLock);
void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets,
ui::LogicalDisplayId displayId) REQUIRES(mLock);
void pokeUserActivityLocked(const EventEntry& eventEntry) REQUIRES(mLock);
@@ -573,30 +815,16 @@
void addDragEventLocked(const MotionEntry& entry) REQUIRES(mLock);
void finishDragAndDrop(ui::LogicalDisplayId displayId, float x, float y) REQUIRES(mLock);
- struct TouchOcclusionInfo {
- bool hasBlockingOcclusion;
- float obscuringOpacity;
- std::string obscuringPackage;
- gui::Uid obscuringUid = gui::Uid::INVALID;
- std::vector<std::string> debugInfo;
- };
-
- TouchOcclusionInfo computeTouchOcclusionInfoLocked(
- const sp<android::gui::WindowInfoHandle>& windowHandle, float x, float y) const
- REQUIRES(mLock);
- bool isTouchTrustedLocked(const TouchOcclusionInfo& occlusionInfo) const REQUIRES(mLock);
- bool isWindowObscuredAtPointLocked(const sp<android::gui::WindowInfoHandle>& windowHandle,
- float x, float y) const REQUIRES(mLock);
- bool isWindowObscuredLocked(const sp<android::gui::WindowInfoHandle>& windowHandle) const
- REQUIRES(mLock);
- std::string dumpWindowForTouchOcclusion(const android::gui::WindowInfo* info,
- bool isTouchWindow) const;
std::string getApplicationWindowLabel(const InputApplicationHandle* applicationHandle,
const sp<android::gui::WindowInfoHandle>& windowHandle);
- bool shouldDropInput(const EventEntry& entry,
- const sp<android::gui::WindowInfoHandle>& windowHandle) const
- REQUIRES(mLock);
+ static std::vector<sp<android::gui::WindowInfoHandle>> findTouchedSpyWindowsAt(
+ ui::LogicalDisplayId displayId, float x, float y, bool isStylus, DeviceId deviceId,
+ const DispatcherWindowInfo& windowInfos);
+
+ static bool shouldDropInput(const EventEntry& entry,
+ const sp<android::gui::WindowInfoHandle>& windowHandle,
+ const DispatcherWindowInfo& windowInfo);
// Manage the dispatch cycle for a single connection.
// These methods are deliberately not Interruptible because doing all of the work
@@ -618,8 +846,7 @@
void finishDispatchCycleLocked(nsecs_t currentTime,
const std::shared_ptr<Connection>& connection, uint32_t seq,
bool handled, nsecs_t consumeTime) REQUIRES(mLock);
- void abortBrokenDispatchCycleLocked(nsecs_t currentTime,
- const std::shared_ptr<Connection>& connection, bool notify)
+ void abortBrokenDispatchCycleLocked(const std::shared_ptr<Connection>& connection, bool notify)
REQUIRES(mLock);
void drainDispatchQueue(std::deque<std::unique_ptr<DispatchEntry>>& queue);
void releaseDispatchEntry(std::unique_ptr<DispatchEntry> dispatchEntry);
@@ -659,13 +886,10 @@
// Dump state.
void dumpDispatchStateLocked(std::string& dump) const REQUIRES(mLock);
- void dumpMonitors(std::string& dump, const std::vector<Monitor>& monitors) const;
void logDispatchStateLocked() const REQUIRES(mLock);
std::string dumpPointerCaptureStateLocked() const REQUIRES(mLock);
- // Registration.
- void removeMonitorChannelLocked(const sp<IBinder>& connectionToken) REQUIRES(mLock);
- status_t removeInputChannelLocked(const sp<IBinder>& connectionToken, bool notify)
+ status_t removeInputChannelLocked(const std::shared_ptr<Connection>& connection, bool notify)
REQUIRES(mLock);
// Interesting events that we might like to log or tell the framework about.
@@ -695,15 +919,6 @@
const std::shared_ptr<Connection>& connection, DispatchEntry* dispatchEntry,
bool handled) REQUIRES(mLock);
- // Find touched state and touched window by token.
- std::tuple<TouchState*, TouchedWindow*, ui::LogicalDisplayId>
- findTouchStateWindowAndDisplayLocked(const sp<IBinder>& token) REQUIRES(mLock);
-
- std::tuple<const TouchState*, const TouchedWindow*, ui::LogicalDisplayId>
- findTouchStateWindowAndDisplayLocked(const sp<IBinder>& token) const REQUIRES(mLock);
- bool windowHasTouchingPointersLocked(const sp<android::gui::WindowInfoHandle>& windowHandle,
- DeviceId deviceId) const REQUIRES(mLock);
-
// Statistics gathering.
nsecs_t mLastStatisticPushTime = 0;
std::unique_ptr<InputEventTimelineProcessor> mInputEventTimelineProcessor GUARDED_BY(mLock);
@@ -718,36 +933,6 @@
sp<InputReporterInterface> mReporter;
- /**
- * Slip the wallpaper touch if necessary.
- *
- * @param targetFlags the target flags
- * @param oldWindowHandle the old window that the touch slipped out of
- * @param newWindowHandle the new window that the touch is slipping into
- * @param state the current touch state. This will be updated if necessary to reflect the new
- * windows that are receiving touch.
- * @param deviceId the device id of the current motion being processed
- * @param pointerProperties the pointer properties of the current motion being processed
- * @param targets the current targets to add the walpaper ones to
- * @param eventTime the new downTime for the wallpaper target
- */
- void slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
- const sp<android::gui::WindowInfoHandle>& oldWindowHandle,
- const sp<android::gui::WindowInfoHandle>& newWindowHandle,
- TouchState& state, const MotionEntry& entry,
- std::vector<InputTarget>& targets) const REQUIRES(mLock);
- void transferWallpaperTouch(ftl::Flags<InputTarget::Flags> oldTargetFlags,
- ftl::Flags<InputTarget::Flags> newTargetFlags,
- const sp<android::gui::WindowInfoHandle> fromWindowHandle,
- const sp<android::gui::WindowInfoHandle> toWindowHandle,
- TouchState& state, DeviceId deviceId,
- const std::vector<PointerProperties>& pointers,
- const std::unique_ptr<trace::EventTrackerInterface>& traceTracker)
- REQUIRES(mLock);
-
- sp<android::gui::WindowInfoHandle> findWallpaperWindowBelow(
- const sp<android::gui::WindowInfoHandle>& windowHandle) const REQUIRES(mLock);
-
/** Stores the value of the input flag for per device input latency metrics. */
const bool mPerDeviceInputLatencyMetricsFlag =
com::android::input::flags::enable_per_device_input_latency_metrics();
diff --git a/services/inputflinger/dispatcher/InputState.cpp b/services/inputflinger/dispatcher/InputState.cpp
index 9b5a79b..782a54f 100644
--- a/services/inputflinger/dispatcher/InputState.cpp
+++ b/services/inputflinger/dispatcher/InputState.cpp
@@ -15,7 +15,9 @@
*/
#include "DebugConfig.h"
+#include "input/Input.h"
#include "input/InputDevice.h"
+#include "input/InputFlags.h"
#include "InputState.h"
@@ -221,10 +223,15 @@
}
ssize_t InputState::findMotionMemento(const MotionEntry& entry, bool hovering) const {
+ // If we have connected displays a mouse can move between displays and displayId may change
+ // while a gesture is in-progress.
+ const bool skipDisplayCheck =
+ InputFlags::connectedDisplaysCursorEnabled() && isMouseOrTouchpad(entry.source);
for (size_t i = 0; i < mMotionMementos.size(); i++) {
const MotionMemento& memento = mMotionMementos[i];
if (memento.deviceId == entry.deviceId && memento.source == entry.source &&
- memento.displayId == entry.displayId && memento.hovering == hovering) {
+ memento.hovering == hovering &&
+ (skipDisplayCheck || memento.displayId == entry.displayId)) {
return i;
}
}
@@ -338,7 +345,10 @@
// would receive different events from each display. Since the TouchStates are per-display,
// it's unlikely that those two streams would be consistent with each other. Therefore,
// cancel the previous gesture if the display id changes.
- if (motionEntry.displayId != lastMemento.displayId) {
+ // Except when we have connected-displays where a mouse may move across display boundaries.
+ const bool skipDisplayCheck = (InputFlags::connectedDisplaysCursorEnabled() &&
+ isMouseOrTouchpad(motionEntry.source));
+ if (!skipDisplayCheck && motionEntry.displayId != lastMemento.displayId) {
LOG(INFO) << "Canceling stream: last displayId was " << lastMemento.displayId
<< " and new event is " << motionEntry;
return true;
diff --git a/services/inputflinger/dispatcher/InputTarget.h b/services/inputflinger/dispatcher/InputTarget.h
index 90374f1..76f3fe0 100644
--- a/services/inputflinger/dispatcher/InputTarget.h
+++ b/services/inputflinger/dispatcher/InputTarget.h
@@ -77,8 +77,8 @@
// (ignored for KeyEvents)
float globalScaleFactor = 1.0f;
- // Current display transform. Used for compatibility for raw coordinates.
- ui::Transform displayTransform;
+ // The raw coordinate transform that's used for compatibility for MotionEvent's getRaw APIs.
+ ui::Transform rawTransform;
// Event time for the first motion event (ACTION_DOWN) dispatched to this input target if
// FLAG_SPLIT is set.
diff --git a/services/inputflinger/dispatcher/LatencyAggregatorWithHistograms.cpp b/services/inputflinger/dispatcher/LatencyAggregatorWithHistograms.cpp
index 881a96b..4da05c1 100644
--- a/services/inputflinger/dispatcher/LatencyAggregatorWithHistograms.cpp
+++ b/services/inputflinger/dispatcher/LatencyAggregatorWithHistograms.cpp
@@ -133,10 +133,11 @@
}
void LatencyAggregatorWithHistograms::processStatistics(const InputEventTimeline& timeline) {
- // Only gather data for Down, Move and Up motion events and Key events
+ // Only gather data for Down, Move, Up and Scroll motion events and Key events
if (!(timeline.inputEventActionType == InputEventActionType::MOTION_ACTION_DOWN ||
timeline.inputEventActionType == InputEventActionType::MOTION_ACTION_MOVE ||
timeline.inputEventActionType == InputEventActionType::MOTION_ACTION_UP ||
+ timeline.inputEventActionType == InputEventActionType::MOTION_ACTION_SCROLL ||
timeline.inputEventActionType == InputEventActionType::KEY))
return;
diff --git a/services/inputflinger/dispatcher/LatencyTracker.cpp b/services/inputflinger/dispatcher/LatencyTracker.cpp
index 0852026..0921e37 100644
--- a/services/inputflinger/dispatcher/LatencyTracker.cpp
+++ b/services/inputflinger/dispatcher/LatencyTracker.cpp
@@ -20,6 +20,7 @@
#include <inttypes.h>
+#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android/os/IInputConstants.h>
@@ -32,6 +33,8 @@
namespace android::inputdispatcher {
+namespace {
+
/**
* Events that are older than this time will be considered mature, at which point we will stop
* waiting for the apps to provide further information about them.
@@ -62,27 +65,25 @@
}
}
+} // namespace
+
LatencyTracker::LatencyTracker(InputEventTimelineProcessor& processor)
: mTimelineProcessor(&processor) {}
-void LatencyTracker::trackNotifyMotion(const NotifyMotionArgs& args) {
- std::set<InputDeviceUsageSource> sources = getUsageSourcesForMotionArgs(args);
- trackListener(args.id, args.eventTime, args.readTime, args.deviceId, sources, args.action,
- InputEventType::MOTION);
-}
+void LatencyTracker::trackListener(const NotifyArgs& args) {
+ if (const NotifyKeyArgs* keyArgs = std::get_if<NotifyKeyArgs>(&args)) {
+ std::set<InputDeviceUsageSource> sources =
+ getUsageSourcesForKeyArgs(*keyArgs, mInputDevices);
+ trackListener(keyArgs->id, keyArgs->eventTime, keyArgs->readTime, keyArgs->deviceId,
+ sources, keyArgs->action, InputEventType::KEY);
-void LatencyTracker::trackNotifyKey(const NotifyKeyArgs& args) {
- int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NONE;
- for (auto& inputDevice : mInputDevices) {
- if (args.deviceId == inputDevice.getId()) {
- keyboardType = inputDevice.getKeyboardType();
- break;
- }
+ } else if (const NotifyMotionArgs* motionArgs = std::get_if<NotifyMotionArgs>(&args)) {
+ std::set<InputDeviceUsageSource> sources = getUsageSourcesForMotionArgs(*motionArgs);
+ trackListener(motionArgs->id, motionArgs->eventTime, motionArgs->readTime,
+ motionArgs->deviceId, sources, motionArgs->action, InputEventType::MOTION);
+ } else {
+ LOG(FATAL) << "Unexpected NotifyArgs type: " << args.index();
}
- std::set<InputDeviceUsageSource> sources =
- std::set{getUsageSourceForKeyArgs(keyboardType, args)};
- trackListener(args.id, args.eventTime, args.readTime, args.deviceId, sources, args.action,
- InputEventType::KEY);
}
void LatencyTracker::trackListener(int32_t inputEventId, nsecs_t eventTime, nsecs_t readTime,
diff --git a/services/inputflinger/dispatcher/LatencyTracker.h b/services/inputflinger/dispatcher/LatencyTracker.h
index eb58222..79ea14c 100644
--- a/services/inputflinger/dispatcher/LatencyTracker.h
+++ b/services/inputflinger/dispatcher/LatencyTracker.h
@@ -44,28 +44,20 @@
*/
LatencyTracker(InputEventTimelineProcessor& processor);
/**
- * Start keeping track of an event identified by inputEventId. This must be called first.
+ * Start keeping track of an event identified by the args. This must be called first.
* If duplicate events are encountered (events that have the same eventId), none of them will be
- * tracked. This is because there is not enough information to correctly track them. The api's
- * 'trackFinishedEvent' and 'trackGraphicsLatency' only contain the inputEventId, and not the
- * eventTime. Even if eventTime was provided, there would still be a possibility of having
- * duplicate events that happen to have the same eventTime and inputEventId. Therefore, we
- * must drop all duplicate data.
+ * tracked. This is because there is not enough information to correctly track them. It is
+ * always possible that two different events are generated with the same inputEventId and the
+ * same eventTime, so there aren't ways to distinguish those. Therefore, we must drop all
+ * duplicate data.
+ * For that reason, the APIs 'trackFinishedEvent' and 'trackGraphicsLatency' only receive the
+ * inputEventId as input.
*/
- void trackListener(int32_t inputEventId, nsecs_t eventTime, nsecs_t readTime, DeviceId deviceId,
- const std::set<InputDeviceUsageSource>& sources, int32_t inputEventAction,
- InputEventType inputEventType);
+ void trackListener(const NotifyArgs& args);
void trackFinishedEvent(int32_t inputEventId, const sp<IBinder>& connectionToken,
nsecs_t deliveryTime, nsecs_t consumeTime, nsecs_t finishTime);
void trackGraphicsLatency(int32_t inputEventId, const sp<IBinder>& connectionToken,
std::array<nsecs_t, GraphicsTimeline::SIZE> timeline);
- /**
- * trackNotifyMotion and trackNotifyKeys are intermediates between InputDispatcher and
- * trackListener. They compute the InputDeviceUsageSource set and call trackListener with
- * the relevant parameters for latency computation.
- */
- void trackNotifyMotion(const NotifyMotionArgs& args);
- void trackNotifyKey(const NotifyKeyArgs& args);
std::string dump(const char* prefix) const;
void setInputDevices(const std::vector<InputDeviceInfo>& inputDevices);
@@ -90,6 +82,10 @@
InputEventTimelineProcessor* mTimelineProcessor;
std::vector<InputDeviceInfo> mInputDevices;
+
+ void trackListener(int32_t inputEventId, nsecs_t eventTime, nsecs_t readTime, DeviceId deviceId,
+ const std::set<InputDeviceUsageSource>& sources, int32_t inputEventAction,
+ InputEventType inputEventType);
void reportAndPruneMatureRecords(nsecs_t newEventTime);
};
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index 463a952..ab039c3 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -24,6 +24,7 @@
#include <android/os/InputEventInjectionSync.h>
#include <gui/InputApplication.h>
#include <gui/WindowInfo.h>
+#include <input/DisplayTopologyGraph.h>
#include <input/InputDevice.h>
#include <input/InputTransport.h>
#include <unordered_map>
@@ -243,6 +244,11 @@
* Notify the dispatcher that the state of the input method connection changed.
*/
virtual void setInputMethodConnectionIsActive(bool isActive) = 0;
+
+ /*
+ * Notify the dispatcher of the latest DisplayTopology.
+ */
+ virtual void setDisplayTopology(const DisplayTopologyGraph& displayTopologyGraph) = 0;
};
} // namespace android
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
index b885ba1..5dcd984 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
@@ -20,12 +20,14 @@
#include <android-base/properties.h>
#include <binder/IBinder.h>
+#include <dispatcher/Entry.h>
#include <gui/InputApplication.h>
#include <gui/PidUid.h>
#include <input/Input.h>
#include <input/InputDevice.h>
#include <utils/RefBase.h>
#include <set>
+#include <variant>
namespace android {
@@ -106,9 +108,9 @@
uint32_t& policyFlags) = 0;
/* Allows the policy a chance to intercept a key before dispatching. */
- virtual nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>& token,
- const KeyEvent& keyEvent,
- uint32_t policyFlags) = 0;
+ virtual std::variant<nsecs_t, inputdispatcher::KeyEntry::InterceptKeyResult>
+ interceptKeyBeforeDispatching(const sp<IBinder>& token, const KeyEvent& keyEvent,
+ uint32_t policyFlags) = 0;
/* Allows the policy a chance to perform default processing for an unhandled key.
* Returns an alternate key event to redispatch as a fallback, if needed. */
diff --git a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp
deleted file mode 100644
index 0b17507..0000000
--- a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright 2024 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 "AndroidInputEventProtoConverter.h"
-
-#include <android-base/logging.h>
-#include <perfetto/trace/android/android_input_event.pbzero.h>
-
-namespace android::inputdispatcher::trace {
-
-namespace {
-
-using namespace ftl::flag_operators;
-
-// The trace config to use for maximal tracing.
-const impl::TraceConfig CONFIG_TRACE_ALL{
- .flags = impl::TraceFlag::TRACE_DISPATCHER_INPUT_EVENTS |
- impl::TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH,
- .rules = {impl::TraceRule{.level = impl::TraceLevel::TRACE_LEVEL_COMPLETE,
- .matchAllPackages = {},
- .matchAnyPackages = {},
- .matchSecure{},
- .matchImeConnectionActive = {}}},
-};
-
-} // namespace
-
-void AndroidInputEventProtoConverter::toProtoMotionEvent(const TracedMotionEvent& event,
- proto::AndroidMotionEvent& outProto,
- bool isRedacted) {
- outProto.set_event_id(event.id);
- outProto.set_event_time_nanos(event.eventTime);
- outProto.set_down_time_nanos(event.downTime);
- outProto.set_source(event.source);
- outProto.set_action(event.action);
- outProto.set_device_id(event.deviceId);
- outProto.set_display_id(event.displayId.val());
- outProto.set_classification(static_cast<int32_t>(event.classification));
- outProto.set_flags(event.flags);
- outProto.set_policy_flags(event.policyFlags);
-
- if (!isRedacted) {
- outProto.set_cursor_position_x(event.xCursorPosition);
- outProto.set_cursor_position_y(event.yCursorPosition);
- outProto.set_meta_state(event.metaState);
- }
-
- for (uint32_t i = 0; i < event.pointerProperties.size(); i++) {
- auto* pointer = outProto.add_pointer();
-
- const auto& props = event.pointerProperties[i];
- pointer->set_pointer_id(props.id);
- pointer->set_tool_type(static_cast<int32_t>(props.toolType));
-
- const auto& coords = event.pointerCoords[i];
- auto bits = BitSet64(coords.bits);
- for (int32_t axisIndex = 0; !bits.isEmpty(); axisIndex++) {
- const auto axis = bits.clearFirstMarkedBit();
- auto axisEntry = pointer->add_axis_value();
- axisEntry->set_axis(axis);
-
- if (!isRedacted) {
- axisEntry->set_value(coords.values[axisIndex]);
- }
- }
- }
-}
-
-void AndroidInputEventProtoConverter::toProtoKeyEvent(const TracedKeyEvent& event,
- proto::AndroidKeyEvent& outProto,
- bool isRedacted) {
- outProto.set_event_id(event.id);
- outProto.set_event_time_nanos(event.eventTime);
- outProto.set_down_time_nanos(event.downTime);
- outProto.set_source(event.source);
- outProto.set_action(event.action);
- outProto.set_device_id(event.deviceId);
- outProto.set_display_id(event.displayId.val());
- outProto.set_repeat_count(event.repeatCount);
- outProto.set_flags(event.flags);
- outProto.set_policy_flags(event.policyFlags);
-
- if (!isRedacted) {
- outProto.set_key_code(event.keyCode);
- outProto.set_scan_code(event.scanCode);
- outProto.set_meta_state(event.metaState);
- }
-}
-
-void AndroidInputEventProtoConverter::toProtoWindowDispatchEvent(
- const WindowDispatchArgs& args, proto::AndroidWindowInputDispatchEvent& outProto,
- bool isRedacted) {
- std::visit([&](auto entry) { outProto.set_event_id(entry.id); }, args.eventEntry);
- outProto.set_vsync_id(args.vsyncId);
- outProto.set_window_id(args.windowId);
- outProto.set_resolved_flags(args.resolvedFlags);
-
- if (isRedacted) {
- return;
- }
- if (auto* motion = std::get_if<TracedMotionEvent>(&args.eventEntry); motion != nullptr) {
- for (size_t i = 0; i < motion->pointerProperties.size(); i++) {
- auto* pointerProto = outProto.add_dispatched_pointer();
- pointerProto->set_pointer_id(motion->pointerProperties[i].id);
- const auto rawXY =
- MotionEvent::calculateTransformedXY(motion->source, args.rawTransform,
- motion->pointerCoords[i].getXYValue());
- pointerProto->set_x_in_display(rawXY.x);
- pointerProto->set_y_in_display(rawXY.y);
-
- const auto& coords = motion->pointerCoords[i];
- const auto coordsInWindow =
- MotionEvent::calculateTransformedCoords(motion->source, motion->flags,
- args.transform, coords);
- auto bits = BitSet64(coords.bits);
- for (int32_t axisIndex = 0; !bits.isEmpty(); axisIndex++) {
- const uint32_t axis = bits.clearFirstMarkedBit();
- const float axisValueInWindow = coordsInWindow.values[axisIndex];
- if (coords.values[axisIndex] != axisValueInWindow) {
- auto* axisEntry = pointerProto->add_axis_value_in_window();
- axisEntry->set_axis(axis);
- axisEntry->set_value(axisValueInWindow);
- }
- }
- }
- }
-}
-
-impl::TraceConfig AndroidInputEventProtoConverter::parseConfig(
- proto::AndroidInputEventConfig::Decoder& protoConfig) {
- if (protoConfig.has_mode() &&
- protoConfig.mode() == proto::AndroidInputEventConfig::TRACE_MODE_TRACE_ALL) {
- // User has requested the preset for maximal tracing
- return CONFIG_TRACE_ALL;
- }
-
- impl::TraceConfig config;
-
- // Parse trace flags
- if (protoConfig.has_trace_dispatcher_input_events() &&
- protoConfig.trace_dispatcher_input_events()) {
- config.flags |= impl::TraceFlag::TRACE_DISPATCHER_INPUT_EVENTS;
- }
- if (protoConfig.has_trace_dispatcher_window_dispatch() &&
- protoConfig.trace_dispatcher_window_dispatch()) {
- config.flags |= impl::TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH;
- }
-
- // Parse trace rules
- auto rulesIt = protoConfig.rules();
- while (rulesIt) {
- proto::AndroidInputEventConfig::TraceRule::Decoder protoRule{rulesIt->as_bytes()};
- config.rules.emplace_back();
- auto& rule = config.rules.back();
-
- rule.level = protoRule.has_trace_level()
- ? static_cast<impl::TraceLevel>(protoRule.trace_level())
- : impl::TraceLevel::TRACE_LEVEL_NONE;
-
- if (protoRule.has_match_all_packages()) {
- auto pkgIt = protoRule.match_all_packages();
- while (pkgIt) {
- rule.matchAllPackages.emplace_back(pkgIt->as_std_string());
- pkgIt++;
- }
- }
-
- if (protoRule.has_match_any_packages()) {
- auto pkgIt = protoRule.match_any_packages();
- while (pkgIt) {
- rule.matchAnyPackages.emplace_back(pkgIt->as_std_string());
- pkgIt++;
- }
- }
-
- if (protoRule.has_match_secure()) {
- rule.matchSecure = protoRule.match_secure();
- }
-
- if (protoRule.has_match_ime_connection_active()) {
- rule.matchImeConnectionActive = protoRule.match_ime_connection_active();
- }
-
- rulesIt++;
- }
-
- return config;
-}
-
-} // namespace android::inputdispatcher::trace
diff --git a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h
index 887913f..c19d278 100644
--- a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h
+++ b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h
@@ -26,20 +26,214 @@
namespace android::inputdispatcher::trace {
+namespace internal {
+
+using namespace ftl::flag_operators;
+
+// The trace config to use for maximal tracing.
+const impl::TraceConfig CONFIG_TRACE_ALL{
+ .flags = impl::TraceFlag::TRACE_DISPATCHER_INPUT_EVENTS |
+ impl::TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH,
+ .rules = {impl::TraceRule{.level = impl::TraceLevel::TRACE_LEVEL_COMPLETE,
+ .matchAllPackages = {},
+ .matchAnyPackages = {},
+ .matchSecure{},
+ .matchImeConnectionActive = {}}},
+};
+
+template <typename Pointer>
+void writeAxisValue(Pointer* pointer, int32_t axis, float value, bool isRedacted) {
+ auto* axisEntry = pointer->add_axis_value();
+ axisEntry->set_axis(axis);
+
+ if (!isRedacted) {
+ axisEntry->set_value(value);
+ }
+}
+
+} // namespace internal
+
/**
* Write traced events into Perfetto protos.
+ *
+ * This class is templated so that the logic can be tested while substituting the proto classes
+ * auto-generated by Perfetto's pbzero library with mock implementations.
*/
+template <typename ProtoMotion, typename ProtoKey, typename ProtoDispatch,
+ typename ProtoConfigDecoder>
class AndroidInputEventProtoConverter {
public:
- static void toProtoMotionEvent(const TracedMotionEvent& event,
- proto::AndroidMotionEvent& outProto, bool isRedacted);
- static void toProtoKeyEvent(const TracedKeyEvent& event, proto::AndroidKeyEvent& outProto,
- bool isRedacted);
- static void toProtoWindowDispatchEvent(const WindowDispatchArgs&,
- proto::AndroidWindowInputDispatchEvent& outProto,
- bool isRedacted);
+ static void toProtoMotionEvent(const TracedMotionEvent& event, ProtoMotion& outProto,
+ bool isRedacted) {
+ outProto.set_event_id(event.id);
+ outProto.set_event_time_nanos(event.eventTime);
+ outProto.set_down_time_nanos(event.downTime);
+ outProto.set_source(event.source);
+ outProto.set_action(event.action);
+ outProto.set_device_id(event.deviceId);
+ outProto.set_display_id(event.displayId.val());
+ outProto.set_classification(static_cast<int32_t>(event.classification));
+ outProto.set_flags(event.flags);
+ outProto.set_policy_flags(event.policyFlags);
+ outProto.set_button_state(event.buttonState);
+ outProto.set_action_button(event.actionButton);
- static impl::TraceConfig parseConfig(proto::AndroidInputEventConfig::Decoder& protoConfig);
+ if (!isRedacted) {
+ outProto.set_cursor_position_x(event.xCursorPosition);
+ outProto.set_cursor_position_y(event.yCursorPosition);
+ outProto.set_meta_state(event.metaState);
+ outProto.set_precision_x(event.xPrecision);
+ outProto.set_precision_y(event.yPrecision);
+ }
+
+ for (uint32_t i = 0; i < event.pointerProperties.size(); i++) {
+ auto* pointer = outProto.add_pointer();
+
+ const auto& props = event.pointerProperties[i];
+ pointer->set_pointer_id(props.id);
+ pointer->set_tool_type(static_cast<int32_t>(props.toolType));
+
+ const auto& coords = event.pointerCoords[i];
+ auto bits = BitSet64(coords.bits);
+
+ if (isFromSource(event.source, AINPUT_SOURCE_CLASS_POINTER)) {
+ // Always include the X and Y axes for pointer events, since the
+ // bits will not be marked if the value is 0.
+ for (const auto axis : {AMOTION_EVENT_AXIS_X, AMOTION_EVENT_AXIS_Y}) {
+ if (!bits.hasBit(axis)) {
+ internal::writeAxisValue(pointer, axis, 0.0f, isRedacted);
+ }
+ }
+ }
+
+ for (int32_t axisIndex = 0; !bits.isEmpty(); axisIndex++) {
+ const auto axis = bits.clearFirstMarkedBit();
+ internal::writeAxisValue(pointer, axis, coords.values[axisIndex], isRedacted);
+ }
+ }
+ }
+
+ static void toProtoKeyEvent(const TracedKeyEvent& event, ProtoKey& outProto, bool isRedacted) {
+ outProto.set_event_id(event.id);
+ outProto.set_event_time_nanos(event.eventTime);
+ outProto.set_down_time_nanos(event.downTime);
+ outProto.set_source(event.source);
+ outProto.set_action(event.action);
+ outProto.set_device_id(event.deviceId);
+ outProto.set_display_id(event.displayId.val());
+ outProto.set_repeat_count(event.repeatCount);
+ outProto.set_flags(event.flags);
+ outProto.set_policy_flags(event.policyFlags);
+
+ if (!isRedacted) {
+ outProto.set_key_code(event.keyCode);
+ outProto.set_scan_code(event.scanCode);
+ outProto.set_meta_state(event.metaState);
+ }
+ }
+
+ static void toProtoWindowDispatchEvent(const WindowDispatchArgs& args, ProtoDispatch& outProto,
+ bool isRedacted) {
+ std::visit([&](auto entry) { outProto.set_event_id(entry.id); }, args.eventEntry);
+ outProto.set_vsync_id(args.vsyncId);
+ outProto.set_window_id(args.windowId);
+ outProto.set_resolved_flags(args.resolvedFlags);
+
+ if (isRedacted) {
+ return;
+ }
+ if (auto* motion = std::get_if<TracedMotionEvent>(&args.eventEntry); motion != nullptr) {
+ for (size_t i = 0; i < motion->pointerProperties.size(); i++) {
+ auto* pointerProto = outProto.add_dispatched_pointer();
+ pointerProto->set_pointer_id(motion->pointerProperties[i].id);
+ const auto& coords = motion->pointerCoords[i];
+ const auto rawXY =
+ MotionEvent::calculateTransformedXY(motion->source, args.rawTransform,
+ coords.getXYValue());
+ if (coords.getXYValue() != rawXY) {
+ // These values are only traced if they were modified by the raw transform
+ // to save space. Trace consumers should be aware of this optimization.
+ pointerProto->set_x_in_display(rawXY.x);
+ pointerProto->set_y_in_display(rawXY.y);
+ }
+
+ const auto coordsInWindow =
+ MotionEvent::calculateTransformedCoords(motion->source, motion->flags,
+ args.transform, coords);
+ auto bits = BitSet64(coords.bits);
+ for (int32_t axisIndex = 0; !bits.isEmpty(); axisIndex++) {
+ const uint32_t axis = bits.clearFirstMarkedBit();
+ const float axisValueInWindow = coordsInWindow.values[axisIndex];
+ // Only values that are modified by the window transform are traced.
+ if (coords.values[axisIndex] != axisValueInWindow) {
+ auto* axisEntry = pointerProto->add_axis_value_in_window();
+ axisEntry->set_axis(axis);
+ axisEntry->set_value(axisValueInWindow);
+ }
+ }
+ }
+ }
+ }
+
+ static impl::TraceConfig parseConfig(ProtoConfigDecoder& protoConfig) {
+ if (protoConfig.has_mode() &&
+ protoConfig.mode() == proto::AndroidInputEventConfig::TRACE_MODE_TRACE_ALL) {
+ // User has requested the preset for maximal tracing
+ return internal::CONFIG_TRACE_ALL;
+ }
+
+ impl::TraceConfig config;
+
+ // Parse trace flags
+ if (protoConfig.has_trace_dispatcher_input_events() &&
+ protoConfig.trace_dispatcher_input_events()) {
+ config.flags |= impl::TraceFlag::TRACE_DISPATCHER_INPUT_EVENTS;
+ }
+ if (protoConfig.has_trace_dispatcher_window_dispatch() &&
+ protoConfig.trace_dispatcher_window_dispatch()) {
+ config.flags |= impl::TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH;
+ }
+
+ // Parse trace rules
+ auto rulesIt = protoConfig.rules();
+ while (rulesIt) {
+ proto::AndroidInputEventConfig::TraceRule::Decoder protoRule{rulesIt->as_bytes()};
+ config.rules.emplace_back();
+ auto& rule = config.rules.back();
+
+ rule.level = protoRule.has_trace_level()
+ ? static_cast<impl::TraceLevel>(protoRule.trace_level())
+ : impl::TraceLevel::TRACE_LEVEL_NONE;
+
+ if (protoRule.has_match_all_packages()) {
+ auto pkgIt = protoRule.match_all_packages();
+ while (pkgIt) {
+ rule.matchAllPackages.emplace_back(pkgIt->as_std_string());
+ pkgIt++;
+ }
+ }
+
+ if (protoRule.has_match_any_packages()) {
+ auto pkgIt = protoRule.match_any_packages();
+ while (pkgIt) {
+ rule.matchAnyPackages.emplace_back(pkgIt->as_std_string());
+ pkgIt++;
+ }
+ }
+
+ if (protoRule.has_match_secure()) {
+ rule.matchSecure = protoRule.match_secure();
+ }
+
+ if (protoRule.has_match_ime_connection_active()) {
+ rule.matchImeConnectionActive = protoRule.match_ime_connection_active();
+ }
+
+ rulesIt++;
+ }
+
+ return config;
+ }
};
} // namespace android::inputdispatcher::trace
diff --git a/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h b/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h
index 761d619..2ff6e1c 100644
--- a/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h
+++ b/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h
@@ -50,7 +50,7 @@
uint32_t policyFlags;
int32_t deviceId;
uint32_t source;
- ui::LogicalDisplayId displayId;
+ ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID;
int32_t action;
int32_t keyCode;
int32_t scanCode;
@@ -70,7 +70,7 @@
uint32_t policyFlags;
int32_t deviceId;
uint32_t source;
- ui::LogicalDisplayId displayId;
+ ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID;
int32_t action;
int32_t actionButton;
int32_t flags;
@@ -108,7 +108,7 @@
TracedEvent eventEntry;
nsecs_t deliveryTime;
int32_t resolvedFlags;
- gui::Uid targetUid;
+ gui::Uid targetUid = gui::Uid::INVALID;
int64_t vsyncId;
int32_t windowId;
ui::Transform transform;
diff --git a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp
index 77b5c2e..ebcd9c9 100644
--- a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp
+++ b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp
@@ -34,6 +34,11 @@
constexpr auto INPUT_EVENT_TRACE_DATA_SOURCE_NAME = "android.input.inputevent";
+using ProtoConverter =
+ AndroidInputEventProtoConverter<proto::AndroidMotionEvent, proto::AndroidKeyEvent,
+ proto::AndroidWindowInputDispatchEvent,
+ proto::AndroidInputEventConfig::Decoder>;
+
bool isPermanentlyAllowed(gui::Uid uid) {
switch (uid.val()) {
case AID_SYSTEM:
@@ -85,7 +90,7 @@
const auto rawConfig = args.config->android_input_event_config_raw();
auto protoConfig = perfetto::protos::pbzero::AndroidInputEventConfig::Decoder{rawConfig};
- mConfig = AndroidInputEventProtoConverter::parseConfig(protoConfig);
+ mConfig = ProtoConverter::parseConfig(protoConfig);
}
void PerfettoBackend::InputEventDataSource::OnStart(const InputEventDataSource::StartArgs&) {
@@ -238,7 +243,7 @@
auto* inputEvent = winscopeExtensions->set_android_input_event();
auto* dispatchMotion = isRedacted ? inputEvent->set_dispatcher_motion_event_redacted()
: inputEvent->set_dispatcher_motion_event();
- AndroidInputEventProtoConverter::toProtoMotionEvent(event, *dispatchMotion, isRedacted);
+ ProtoConverter::toProtoMotionEvent(event, *dispatchMotion, isRedacted);
});
}
@@ -266,7 +271,7 @@
auto* inputEvent = winscopeExtensions->set_android_input_event();
auto* dispatchKey = isRedacted ? inputEvent->set_dispatcher_key_event_redacted()
: inputEvent->set_dispatcher_key_event();
- AndroidInputEventProtoConverter::toProtoKeyEvent(event, *dispatchKey, isRedacted);
+ ProtoConverter::toProtoKeyEvent(event, *dispatchKey, isRedacted);
});
}
@@ -295,8 +300,7 @@
auto* dispatchEvent = isRedacted
? inputEvent->set_dispatcher_window_dispatch_event_redacted()
: inputEvent->set_dispatcher_window_dispatch_event();
- AndroidInputEventProtoConverter::toProtoWindowDispatchEvent(dispatchArgs, *dispatchEvent,
- isRedacted);
+ ProtoConverter::toProtoWindowDispatchEvent(dispatchArgs, *dispatchEvent, isRedacted);
});
}
diff --git a/services/inputflinger/docs/device_configuration.md b/services/inputflinger/docs/device_configuration.md
new file mode 100644
index 0000000..0b75eb2
--- /dev/null
+++ b/services/inputflinger/docs/device_configuration.md
@@ -0,0 +1,10 @@
+# Input Device Configuration
+
+There are a number of properties that can be specified for an input device.
+
+|Property|Value|
+|---|----|
+|`audio.mic`|A boolean (`0` or `1`) that indicates whether the device has a microphone.|
+|`device.additionalSysfsLedsNode`|A string representing the path to search for device lights to be used in addition to searching the device node itself for lights.|
+|`device.internal`|A boolean (`0` or `1`) that indicates if this input device is part of the device as opposed to be externally attached.|
+|`device.type`|A string representing if the device is of a certain type. Valid values include `rotaryEncoder` and `externalStylus`.
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index 756a29b..608bec4 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -137,19 +137,31 @@
ui::LogicalDisplayId defaultPointerDisplayId;
// The mouse pointer speed, as a number from -7 (slowest) to 7 (fastest).
- //
- // Currently only used when the enable_new_mouse_pointer_ballistics flag is enabled.
int32_t mousePointerSpeed;
- // Displays on which an acceleration curve shouldn't be applied for pointer movements from mice.
- //
- // Currently only used when the enable_new_mouse_pointer_ballistics flag is enabled.
- std::set<ui::LogicalDisplayId> displaysWithMousePointerAccelerationDisabled;
+ // Displays on which all pointer scaling, including linear scaling based on the
+ // user's pointer speed setting, should be disabled for mice. This differs from
+ // disabling acceleration via the 'mousePointerAccelerationEnabled' setting, where
+ // the pointer speed setting still influences the scaling factor.
+ std::set<ui::LogicalDisplayId> displaysWithMouseScalingDisabled;
- // Velocity control parameters for mouse pointer movements.
+ // True if the connected mouse should exhibit pointer acceleration. If false,
+ // a flat acceleration curve (linear scaling) is used, but the user's pointer
+ // speed setting still affects the scaling factor.
+ bool mousePointerAccelerationEnabled;
+
+ // True if the touchpad should exhibit pointer acceleration. If false,
+ // a flat acceleration curve (linear scaling) is used, but the user's pointer
+ // speed setting still affects the scaling factor.
+ bool touchpadAccelerationEnabled;
+
+ // Velocity control parameters for touchpad pointer movements on the old touchpad stack (based
+ // on TouchInputMapper).
//
- // If the enable_new_mouse_pointer_ballistics flag is enabled, these are ignored and the values
- // of mousePointerSpeed and mousePointerAccelerationEnabled used instead.
+ // For mice, these are ignored and the values of mousePointerSpeed and
+ // mousePointerAccelerationEnabled used instead.
+ //
+ // TODO(b/281840344): remove this.
VelocityControlParameters pointerVelocityControlParameters;
// Velocity control parameters for mouse wheel movements.
@@ -243,6 +255,12 @@
// context (a.k.a. "right") clicks.
bool touchpadRightClickZoneEnabled;
+ // True to use three-finger tap as a customizable shortcut; false to use it as a middle-click.
+ bool touchpadThreeFingerTapShortcutEnabled;
+
+ // True to enable system gestures (three- and four-finger swipes) on touchpads.
+ bool touchpadSystemGesturesEnabled;
+
// The set of currently disabled input devices.
std::set<int32_t> disabledDevices;
@@ -269,12 +287,17 @@
: virtualKeyQuietTime(0),
defaultPointerDisplayId(ui::LogicalDisplayId::DEFAULT),
mousePointerSpeed(0),
- displaysWithMousePointerAccelerationDisabled(),
+ displaysWithMouseScalingDisabled(),
+ mousePointerAccelerationEnabled(true),
+ touchpadAccelerationEnabled(true),
pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f,
static_cast<float>(
android::os::IInputConstants::
DEFAULT_POINTER_ACCELERATION)),
- wheelVelocityControlParameters(1.0f, 15.0f, 50.0f, 4.0f),
+ wheelVelocityControlParameters(1.0f, 15.0f, 50.0f,
+ static_cast<float>(
+ android::os::IInputConstants::
+ DEFAULT_MOUSE_WHEEL_ACCELERATION)),
pointerGesturesEnabled(true),
pointerGestureQuietInterval(100 * 1000000LL), // 100 ms
pointerGestureDragMinSwitchSpeed(50), // 50 pixels per second
@@ -294,6 +317,8 @@
touchpadTapDraggingEnabled(false),
shouldNotifyTouchpadHardwareState(false),
touchpadRightClickZoneEnabled(false),
+ touchpadThreeFingerTapShortcutEnabled(false),
+ touchpadSystemGesturesEnabled(true),
stylusButtonMotionEventsEnabled(true),
stylusPointerIconEnabled(false),
mouseReverseVerticalScrollingEnabled(false),
@@ -359,6 +384,9 @@
/* Toggle Caps Lock */
virtual void toggleCapsLockState(int32_t deviceId) = 0;
+ /* Resets locked modifier state */
+ virtual void resetLockedModifierState() = 0;
+
/* Determine whether physical keys exist for the given framework-domain key codes. */
virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
const std::vector<int32_t>& keyCodes, uint8_t* outFlags) = 0;
@@ -426,6 +454,16 @@
/* Notifies that mouse cursor faded due to typing. */
virtual void notifyMouseCursorFadedOnTyping() = 0;
+
+ /* Set whether the given input device can wake up the kernel from sleep
+ * when it generates input events. By default, usually only internal (built-in)
+ * input devices can wake the kernel from sleep. For an external input device
+ * that supports remote wakeup to be able to wake the kernel, this must be called
+ * after each time the device is connected/added.
+ *
+ * Returns true if setting power wakeup was successful.
+ */
+ virtual bool setKernelWakeEnabled(int32_t deviceId, bool enabled) = 0;
};
// --- TouchAffineTransformation ---
@@ -487,6 +525,9 @@
/* Sends the Info of gestures that happen on the touchpad. */
virtual void notifyTouchpadGestureInfo(GestureType type, int32_t deviceId) = 0;
+ /* Notifies the policy that the user has performed a three-finger touchpad tap. */
+ virtual void notifyTouchpadThreeFingerTap() = 0;
+
/* Gets the keyboard layout for a particular input device. */
virtual std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay(
const InputDeviceIdentifier& identifier,
diff --git a/services/inputflinger/include/NotifyArgs.h b/services/inputflinger/include/NotifyArgs.h
index 14487fe..c513bfc 100644
--- a/services/inputflinger/include/NotifyArgs.h
+++ b/services/inputflinger/include/NotifyArgs.h
@@ -225,4 +225,6 @@
const char* toString(const NotifyArgs& args);
+std::ostream& operator<<(std::ostream& out, const NotifyArgs& args);
+
} // namespace android
diff --git a/services/inputflinger/include/NotifyArgsBuilders.h b/services/inputflinger/include/NotifyArgsBuilders.h
index 5b94d57..13eaaf3 100644
--- a/services/inputflinger/include/NotifyArgsBuilders.h
+++ b/services/inputflinger/include/NotifyArgsBuilders.h
@@ -24,13 +24,15 @@
#include <input/Keyboard.h>
#include <utils/Timers.h> // for nsecs_t, systemTime
+#include <cstdint>
#include <vector>
namespace android {
class MotionArgsBuilder {
public:
- MotionArgsBuilder(int32_t action, int32_t source) : mEventId(InputEvent::nextId()) {
+ MotionArgsBuilder(int32_t action, int32_t source, int32_t eventId = InputEvent::nextId())
+ : mEventId(eventId) {
mAction = action;
if (mAction == AMOTION_EVENT_ACTION_CANCEL) {
addFlag(AMOTION_EVENT_FLAG_CANCELED);
@@ -55,6 +57,11 @@
return *this;
}
+ MotionArgsBuilder& readTime(nsecs_t readTime) {
+ mReadTime = readTime;
+ return *this;
+ }
+
MotionArgsBuilder& displayId(ui::LogicalDisplayId displayId) {
mDisplayId = displayId;
return *this;
@@ -121,7 +128,7 @@
return {mEventId,
mEventTime,
- /*readTime=*/mEventTime,
+ mReadTime.value_or(mEventTime),
mDeviceId,
mSource,
mDisplayId,
@@ -151,6 +158,7 @@
uint32_t mSource;
nsecs_t mDownTime;
nsecs_t mEventTime;
+ std::optional<nsecs_t> mReadTime;
ui::LogicalDisplayId mDisplayId{ui::LogicalDisplayId::DEFAULT};
uint32_t mPolicyFlags = DEFAULT_POLICY_FLAGS;
int32_t mActionButton{0};
@@ -165,7 +173,8 @@
class KeyArgsBuilder {
public:
- KeyArgsBuilder(int32_t action, int32_t source) : mEventId(InputEvent::nextId()) {
+ KeyArgsBuilder(int32_t action, int32_t source, int32_t eventId = InputEvent::nextId())
+ : mEventId(eventId) {
mAction = action;
mSource = source;
mEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -187,6 +196,11 @@
return *this;
}
+ KeyArgsBuilder& readTime(nsecs_t readTime) {
+ mReadTime = readTime;
+ return *this;
+ }
+
KeyArgsBuilder& displayId(ui::LogicalDisplayId displayId) {
mDisplayId = displayId;
return *this;
@@ -214,18 +228,10 @@
}
NotifyKeyArgs build() const {
- return {mEventId,
- mEventTime,
- /*readTime=*/mEventTime,
- mDeviceId,
- mSource,
- mDisplayId,
- mPolicyFlags,
- mAction,
- mFlags,
- mKeyCode,
- mScanCode,
- mMetaState,
+ return {mEventId, mEventTime, mReadTime.value_or(mEventTime),
+ mDeviceId, mSource, mDisplayId,
+ mPolicyFlags, mAction, mFlags,
+ mKeyCode, mScanCode, mMetaState,
mDownTime};
}
@@ -236,6 +242,7 @@
uint32_t mSource;
nsecs_t mDownTime;
nsecs_t mEventTime;
+ std::optional<nsecs_t> mReadTime;
ui::LogicalDisplayId mDisplayId{ui::LogicalDisplayId::DEFAULT};
uint32_t mPolicyFlags = DEFAULT_POLICY_FLAGS;
int32_t mFlags{0};
diff --git a/services/inputflinger/include/PointerChoreographerPolicyInterface.h b/services/inputflinger/include/PointerChoreographerPolicyInterface.h
index e1f8fda..c805b74 100644
--- a/services/inputflinger/include/PointerChoreographerPolicyInterface.h
+++ b/services/inputflinger/include/PointerChoreographerPolicyInterface.h
@@ -54,13 +54,23 @@
* @param position The new position of the mouse cursor on the logical display
*/
virtual void notifyPointerDisplayIdChanged(ui::LogicalDisplayId displayId,
- const FloatPoint& position) = 0;
+ const vec2& position) = 0;
/* Returns true if any InputConnection is currently active. */
virtual bool isInputMethodConnectionActive() = 0;
/* Notifies that mouse cursor faded due to typing. */
virtual void notifyMouseCursorFadedOnTyping() = 0;
+
+ /**
+ * Give accessibility a chance to filter motion event by pointer devices.
+ * The return values denotes the delta x and y after filtering it.
+ *
+ * This call happens on the input hot path and it is extremely performance sensitive.
+ * This also must not call back into native code.
+ */
+ virtual std::optional<vec2> filterPointerMotionForAccessibility(
+ const vec2& current, const vec2& delta, const ui::LogicalDisplayId& displayId) = 0;
};
} // namespace android
diff --git a/services/inputflinger/include/PointerControllerInterface.h b/services/inputflinger/include/PointerControllerInterface.h
index 8f3d9ca..bd46490 100644
--- a/services/inputflinger/include/PointerControllerInterface.h
+++ b/services/inputflinger/include/PointerControllerInterface.h
@@ -24,20 +24,6 @@
struct SpriteIcon;
-struct FloatPoint {
- float x;
- float y;
-
- inline FloatPoint(float x, float y) : x(x), y(y) {}
-
- inline explicit FloatPoint(vec2 p) : x(p.x), y(p.y) {}
-
- template <typename T, typename U>
- operator std::tuple<T, U>() {
- return {x, y};
- }
-};
-
/**
* Interface for tracking a mouse / touch pad pointer and touch pad spots.
*
@@ -72,14 +58,18 @@
/* Dumps the state of the pointer controller. */
virtual std::string dump() = 0;
- /* Move the pointer. */
- virtual void move(float deltaX, float deltaY) = 0;
+ /* Move the pointer and return unconsumed delta if the pointer has crossed the current
+ * viewport bounds.
+ *
+ * Return value may be used to move pointer to corresponding adjacent display, if it exists in
+ * the display-topology */
+ [[nodiscard]] virtual vec2 move(float deltaX, float deltaY) = 0;
/* Sets the absolute location of the pointer. */
virtual void setPosition(float x, float y) = 0;
/* Gets the absolute location of the pointer. */
- virtual FloatPoint getPosition() const = 0;
+ virtual vec2 getPosition() const = 0;
enum class Transition {
// Fade/unfade immediately.
@@ -145,6 +135,8 @@
/* Resets the flag to skip screenshot of the pointer indicators for all displays. */
virtual void clearSkipScreenshotFlags() = 0;
+
+ virtual ui::Transform getDisplayTransform() const = 0;
};
} // namespace android
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index b3cd35c..dc7f7c1 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -66,9 +66,10 @@
"mapper/accumulator/SingleTouchMotionAccumulator.cpp",
"mapper/accumulator/TouchButtonAccumulator.cpp",
"mapper/gestures/GestureConverter.cpp",
- "mapper/gestures/GesturesLogging.cpp",
+ "mapper/gestures/GesturesLogcatAdapter.cpp",
"mapper/gestures/HardwareProperties.cpp",
"mapper/gestures/HardwareStateConverter.cpp",
+ "mapper/gestures/Logging.cpp",
"mapper/gestures/PropertyProvider.cpp",
"mapper/gestures/TimerProvider.cpp",
],
@@ -79,25 +80,25 @@
srcs: [":libinputreader_sources"],
shared_libs: [
"android.companion.virtualdevice.flags-aconfig-cc",
+ "libPlatformProperties",
"libbase",
"libcap",
"libcrypto",
"libcutils",
- "libjsoncpp",
"libinput",
+ "libjsoncpp",
"liblog",
- "libPlatformProperties",
"libstatslog",
"libstatspull",
- "libutils",
"libstatssocket",
+ "libutils",
],
static_libs: [
"libchrome-gestures",
- "libui-types",
"libexpresslog",
- "libtextclassifier_hash_static",
"libstatslog_express",
+ "libtextclassifier_hash_static",
+ "libui-types",
],
header_libs: [
"libbatteryservice_headers",
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index f8cd973..2fcb5d8 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -43,6 +43,7 @@
#include <android-base/strings.h>
#include <cutils/properties.h>
#include <ftl/enum.h>
+#include <input/InputEventLabels.h>
#include <input/KeyCharacterMap.h>
#include <input/KeyLayoutMap.h>
#include <input/PrintTools.h>
@@ -128,7 +129,8 @@
{"multi_intensity", InputLightClass::MULTI_INTENSITY},
{"max_brightness", InputLightClass::MAX_BRIGHTNESS},
{"kbd_backlight", InputLightClass::KEYBOARD_BACKLIGHT},
- {"mic_mute", InputLightClass::KEYBOARD_MIC_MUTE}};
+ {"mic_mute", InputLightClass::KEYBOARD_MIC_MUTE},
+ {"mute", InputLightClass::KEYBOARD_VOLUME_MUTE}};
// Mapping for input multicolor led class node names.
// https://www.kernel.org/doc/html/latest/leds/leds-class-multicolor.html
@@ -349,6 +351,22 @@
return colors;
}
+static base::Result<std::shared_ptr<PropertyMap>> loadConfiguration(
+ const InputDeviceIdentifier& ident) {
+ std::string configurationFile =
+ getInputDeviceConfigurationFilePathByDeviceIdentifier(ident,
+ InputDeviceConfigurationFileType::
+ CONFIGURATION);
+ if (configurationFile.empty()) {
+ ALOGD("No input device configuration file found for device '%s'.", ident.name.c_str());
+ return base::Result<std::shared_ptr<PropertyMap>>(nullptr);
+ }
+ base::Result<std::shared_ptr<PropertyMap>> propertyMap =
+ PropertyMap::load(configurationFile.c_str());
+
+ return propertyMap;
+}
+
/**
* Read country code information exposed through the sysfs path and convert it to Layout info.
*/
@@ -407,11 +425,22 @@
* Read information about lights exposed through the sysfs path.
*/
static std::unordered_map<int32_t /*lightId*/, RawLightInfo> readLightsConfiguration(
- const std::filesystem::path& sysfsRootPath) {
+ const std::filesystem::path& sysfsRootPath, const std::shared_ptr<PropertyMap>& config) {
std::unordered_map<int32_t, RawLightInfo> lightInfos;
int32_t nextLightId = 0;
- // Check if device has any lights.
- const auto& paths = findSysfsNodes(sysfsRootPath, SysfsClass::LEDS);
+ // Check if device has any lights. If the Input Device Configuration file specifies any lights,
+ // use those in addition to searching the device node itself for lights.
+ std::vector<std::filesystem::path> paths = findSysfsNodes(sysfsRootPath, SysfsClass::LEDS);
+
+ if (config) {
+ auto additionalLights = config->getString("device.additionalSysfsLedsNode");
+ if (additionalLights) {
+ ALOGI("IDC specifies additional path for lights at '%s'",
+ additionalLights.value().c_str());
+ paths.push_back(std::filesystem::path(additionalLights.value()));
+ }
+ }
+
for (const auto& nodePath : paths) {
RawLightInfo info;
info.id = ++nextLightId;
@@ -530,17 +559,16 @@
// --- EventHub::Device ---
EventHub::Device::Device(int fd, int32_t id, std::string path, InputDeviceIdentifier identifier,
- std::shared_ptr<const AssociatedDevice> assocDev)
+ std::shared_ptr<PropertyMap> config)
: fd(fd),
id(id),
path(std::move(path)),
identifier(std::move(identifier)),
classes(0),
- configuration(nullptr),
+ configuration(std::move(config)),
virtualKeyMap(nullptr),
ffEffectPlaying(false),
ffEffectId(-1),
- associatedDevice(std::move(assocDev)),
controllerNumber(0),
enabled(true),
isVirtual(fd < 0),
@@ -694,26 +722,6 @@
return false;
}
-void EventHub::Device::loadConfigurationLocked() {
- configurationFile =
- getInputDeviceConfigurationFilePathByDeviceIdentifier(identifier,
- InputDeviceConfigurationFileType::
- CONFIGURATION);
- if (configurationFile.empty()) {
- ALOGD("No input device configuration file found for device '%s'.", identifier.name.c_str());
- } else {
- android::base::Result<std::unique_ptr<PropertyMap>> propertyMap =
- PropertyMap::load(configurationFile.c_str());
- if (!propertyMap.ok()) {
- ALOGE("Error loading input device configuration file for device '%s'. "
- "Using default configuration.",
- identifier.name.c_str());
- } else {
- configuration = std::move(*propertyMap);
- }
- }
-}
-
bool EventHub::Device::loadVirtualKeyMapLocked() {
// The virtual key map is supplied by the kernel as a system board property file.
std::string propPath = "/sys/board_properties/virtualkeys.";
@@ -1021,6 +1029,8 @@
std::scoped_lock _l(mLock);
const Device* device = getDeviceLocked(deviceId);
if (device == nullptr) {
+ ALOGE("Couldn't find device with ID %d, so returning null axis info for axis %s", deviceId,
+ InputEventLookup::getLinuxEvdevLabel(EV_ABS, axis, 0).code.c_str());
return std::nullopt;
}
// We can read the RawAbsoluteAxisInfo even if the device is disabled and doesn't have a valid
@@ -1607,7 +1617,7 @@
}
std::shared_ptr<const EventHub::AssociatedDevice> EventHub::obtainAssociatedDeviceLocked(
- const std::filesystem::path& devicePath) const {
+ const std::filesystem::path& devicePath, const std::shared_ptr<PropertyMap>& config) const {
const std::optional<std::filesystem::path> sysfsRootPathOpt =
getSysfsRootPath(devicePath.c_str());
if (!sysfsRootPathOpt) {
@@ -1616,41 +1626,50 @@
const auto& path = *sysfsRootPathOpt;
- std::shared_ptr<const AssociatedDevice> associatedDevice = std::make_shared<AssociatedDevice>(
- AssociatedDevice{.sysfsRootPath = path,
- .batteryInfos = readBatteryConfiguration(path),
- .lightInfos = readLightsConfiguration(path),
- .layoutInfo = readLayoutConfiguration(path)});
-
- bool associatedDeviceChanged = false;
+ std::shared_ptr<const AssociatedDevice> associatedDevice;
for (const auto& [id, dev] : mDevices) {
- if (dev->associatedDevice && dev->associatedDevice->sysfsRootPath == path) {
- if (*associatedDevice != *dev->associatedDevice) {
- associatedDeviceChanged = true;
- dev->associatedDevice = associatedDevice;
- }
- associatedDevice = dev->associatedDevice;
+ if (!dev->associatedDevice || dev->associatedDevice->sysfsRootPath != path) {
+ continue;
}
+ if (!associatedDevice) {
+ // Found matching associated device for the first time.
+ associatedDevice = dev->associatedDevice;
+ // Reload this associated device if needed. Use the base device
+ // config. Note that this will essentially arbitrarily pick one
+ // Device as the base for the AssociatedDevice configuration. If
+ // there are multiple Device's that have a configuration for the
+ // AssociatedDevice, only one configuration will be chosen and will
+ // be used for all other AssociatedDevices for the same sysfs path.
+ const auto reloadedDevice = AssociatedDevice(path, associatedDevice->baseDevConfig);
+ if (reloadedDevice != *dev->associatedDevice) {
+ ALOGI("The AssociatedDevice changed for path '%s'. Using new AssociatedDevice: %s",
+ path.c_str(), associatedDevice->dump().c_str());
+ associatedDevice = std::make_shared<AssociatedDevice>(std::move(reloadedDevice));
+ }
+ }
+ // Update the associatedDevice.
+ dev->associatedDevice = associatedDevice;
}
- ALOGI_IF(associatedDeviceChanged,
- "The AssociatedDevice changed for path '%s'. Using new AssociatedDevice: %s",
- path.c_str(), associatedDevice->dump().c_str());
+
+ if (!associatedDevice) {
+ // No existing associated device found for this path, so create a new one.
+ associatedDevice = std::make_shared<AssociatedDevice>(path, config);
+ }
return associatedDevice;
}
-bool EventHub::AssociatedDevice::isChanged() const {
- std::unordered_map<int32_t, RawBatteryInfo> newBatteryInfos =
- readBatteryConfiguration(sysfsRootPath);
- std::unordered_map<int32_t, RawLightInfo> newLightInfos =
- readLightsConfiguration(sysfsRootPath);
- std::optional<RawLayoutInfo> newLayoutInfo = readLayoutConfiguration(sysfsRootPath);
+EventHub::AssociatedDevice::AssociatedDevice(const std::filesystem::path& sysfsRootPath,
+ std::shared_ptr<PropertyMap> config)
+ : sysfsRootPath(sysfsRootPath),
+ baseDevConfig(std::move(config)),
+ batteryInfos(readBatteryConfiguration(sysfsRootPath)),
+ lightInfos(readLightsConfiguration(sysfsRootPath, baseDevConfig)),
+ layoutInfo(readLayoutConfiguration(sysfsRootPath)) {}
- if (newBatteryInfos == batteryInfos && newLightInfos == lightInfos &&
- newLayoutInfo == layoutInfo) {
- return false;
- }
- return true;
+std::string EventHub::AssociatedDevice::dump() const {
+ return StringPrintf("path=%s, numBatteries=%zu, numLight=%zu", sysfsRootPath.c_str(),
+ batteryInfos.size(), lightInfos.size());
}
void EventHub::vibrate(int32_t deviceId, const VibrationElement& element) {
@@ -2331,11 +2350,21 @@
// Fill in the descriptor.
assignDescriptorLocked(identifier);
+ // Load the configuration file for the device.
+ std::shared_ptr<PropertyMap> configuration = nullptr;
+ base::Result<std::shared_ptr<PropertyMap>> propertyMapResult = loadConfiguration(identifier);
+ if (!propertyMapResult.ok()) {
+ ALOGE("Error loading input device configuration file for device '%s'. "
+ "Using default configuration. Error: %s",
+ identifier.name.c_str(), propertyMapResult.error().message().c_str());
+ } else {
+ configuration = propertyMapResult.value();
+ }
+
// Allocate device. (The device object takes ownership of the fd at this point.)
int32_t deviceId = mNextDeviceId++;
std::unique_ptr<Device> device =
- std::make_unique<Device>(fd, deviceId, devicePath, identifier,
- obtainAssociatedDeviceLocked(devicePath));
+ std::make_unique<Device>(fd, deviceId, devicePath, identifier, configuration);
ALOGV("add device %d: %s\n", deviceId, devicePath.c_str());
ALOGV(" bus: %04x\n"
@@ -2350,8 +2379,8 @@
ALOGV(" driver: v%d.%d.%d\n", driverVersion >> 16, (driverVersion >> 8) & 0xff,
driverVersion & 0xff);
- // Load the configuration file for the device.
- device->loadConfigurationLocked();
+ // Obtain the associated device, if any.
+ device->associatedDevice = obtainAssociatedDeviceLocked(devicePath, device->configuration);
// Figure out the kinds of events the device reports.
device->readDeviceBitMask(EVIOCGBIT(EV_KEY, 0), device->keyBitmask);
@@ -2642,33 +2671,57 @@
void EventHub::sysfsNodeChanged(const std::string& sysfsNodePath) {
std::scoped_lock _l(mLock);
- // Check in opening devices
- for (auto it = mOpeningDevices.begin(); it != mOpeningDevices.end(); it++) {
- std::unique_ptr<Device>& device = *it;
- if (device->associatedDevice &&
- sysfsNodePath.find(device->associatedDevice->sysfsRootPath.string()) !=
- std::string::npos &&
- device->associatedDevice->isChanged()) {
- it = mOpeningDevices.erase(it);
- openDeviceLocked(device->path);
+ // Testing whether a sysfs node changed involves several syscalls, so use a cache to avoid
+ // testing the same node multiple times.
+ std::map<std::shared_ptr<const AssociatedDevice>, bool /*changed*/> testedDevices;
+ auto isAssociatedDeviceChanged = [&testedDevices, &sysfsNodePath](const Device& dev) {
+ if (!dev.associatedDevice) {
+ return false;
+ }
+ if (auto testedIt = testedDevices.find(dev.associatedDevice);
+ testedIt != testedDevices.end()) {
+ return testedIt->second;
+ }
+ // Cache miss
+ if (sysfsNodePath.find(dev.associatedDevice->sysfsRootPath.string()) == std::string::npos) {
+ testedDevices.emplace(dev.associatedDevice, false);
+ return false;
+ }
+ auto reloadedDevice = AssociatedDevice(dev.associatedDevice->sysfsRootPath,
+ dev.associatedDevice->baseDevConfig);
+ const bool changed = *dev.associatedDevice != reloadedDevice;
+ testedDevices.emplace(dev.associatedDevice, changed);
+ return changed;
+ };
+
+ std::set<Device*> devicesToClose;
+ std::set<std::string /*path*/> devicesToOpen;
+
+ // Check in opening devices. If its associated device changed,
+ // the device should be removed from mOpeningDevices and needs to be opened again.
+ std::erase_if(mOpeningDevices, [&](const auto& dev) {
+ if (isAssociatedDeviceChanged(*dev)) {
+ devicesToOpen.emplace(dev->path);
+ return true;
+ }
+ return false;
+ });
+
+ // Check in already added device. If its associated device changed,
+ // the device needs to be re-opened.
+ for (const auto& [id, dev] : mDevices) {
+ if (isAssociatedDeviceChanged(*dev)) {
+ devicesToOpen.emplace(dev->path);
+ devicesToClose.emplace(dev.get());
}
}
- // Check in already added device
- std::vector<Device*> devicesToReopen;
- for (const auto& [id, device] : mDevices) {
- if (device->associatedDevice &&
- sysfsNodePath.find(device->associatedDevice->sysfsRootPath.string()) !=
- std::string::npos &&
- device->associatedDevice->isChanged()) {
- devicesToReopen.push_back(device.get());
- }
- }
- for (const auto& device : devicesToReopen) {
+ for (auto* device : devicesToClose) {
closeDeviceLocked(*device);
- openDeviceLocked(device->path);
}
- devicesToReopen.clear();
+ for (const auto& path : devicesToOpen) {
+ openDeviceLocked(path);
+ }
}
void EventHub::createVirtualKeyboardLocked() {
@@ -2848,6 +2901,35 @@
mNeedToReopenDevices = true;
}
+bool EventHub::setKernelWakeEnabled(int32_t deviceId, bool enabled) {
+ std::scoped_lock _l(mLock);
+ std::string enabledStr = enabled ? "enabled" : "disabled";
+ Device* device = getDeviceLocked(deviceId);
+ if (device == nullptr) {
+ ALOGE("Device Id %d does not exist for setting power wakeup", deviceId);
+ return false;
+ }
+ if (device->associatedDevice == nullptr) {
+ return false;
+ }
+ std::filesystem::path currentPath = device->associatedDevice->sysfsRootPath;
+ while (!currentPath.empty() && currentPath != "/") {
+ std::string nodePath = currentPath / "power/wakeup";
+ if (std::filesystem::exists(nodePath)) {
+ if (base::WriteStringToFile(enabledStr, nodePath)) {
+ return true;
+
+ }
+ // No need to continue searching in parent directories as power/wakeup nodes
+ // higher up may control other subdevices.
+ ALOGW("Failed to set power/wakeup node at %s", nodePath.c_str());
+ return false;
+ }
+ currentPath = currentPath.parent_path();
+ }
+ return false;
+}
+
void EventHub::dump(std::string& dump) const {
dump += "Event Hub State:\n";
@@ -2939,9 +3021,4 @@
std::unique_lock<std::mutex> lock(mLock);
}
-std::string EventHub::AssociatedDevice::dump() const {
- return StringPrintf("path=%s, numBatteries=%zu, numLight=%zu", sysfsRootPath.c_str(),
- batteryInfos.size(), lightInfos.size());
-}
-
} // namespace android
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 02eeb0a..5e42d57 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -745,6 +745,14 @@
}
}
+bool InputDevice::setKernelWakeEnabled(bool enabled) {
+ bool success = false;
+ for_each_subdevice([&enabled, &success](InputDeviceContext& context) {
+ success |= context.setKernelWakeEnabled(enabled);
+ });
+ return success;
+}
+
InputDeviceContext::InputDeviceContext(InputDevice& device, int32_t eventHubId)
: mDevice(device),
mContext(device.getContext()),
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index ab27042..845cab0 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -19,6 +19,7 @@
#include "InputReader.h"
#include <android-base/stringprintf.h>
+#include <com_android_input_flags.h>
#include <errno.h>
#include <input/Keyboard.h>
#include <input/VirtualKeyMap.h>
@@ -61,6 +62,28 @@
identifier1.location == identifier2.location);
}
+/**
+ * Determines if the device classes passed for two devices represent incompatible combinations
+ * that should not be merged into into a single InputDevice.
+ */
+
+bool isCompatibleSubDevice(ftl::Flags<InputDeviceClass> classes1,
+ ftl::Flags<InputDeviceClass> classes2) {
+ if (!com::android::input::flags::prevent_merging_input_pointer_devices()) {
+ return true;
+ }
+
+ const ftl::Flags<InputDeviceClass> pointerFlags =
+ ftl::Flags<InputDeviceClass>{InputDeviceClass::TOUCH, InputDeviceClass::TOUCH_MT,
+ InputDeviceClass::CURSOR, InputDeviceClass::TOUCHPAD};
+
+ // Do not merge devices that both have any type of pointer event.
+ if (classes1.any(pointerFlags) && classes2.any(pointerFlags)) return false;
+
+ // Safe to merge
+ return true;
+}
+
bool isStylusPointerGestureStart(const NotifyMotionArgs& motionArgs) {
const auto actionMasked = MotionEvent::getActionMasked(motionArgs.action);
if (actionMasked != AMOTION_EVENT_ACTION_HOVER_ENTER &&
@@ -173,9 +196,8 @@
if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
if (now >= mNextTimeout) {
- if (debugRawEvents()) {
- ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
- }
+ ALOGD_IF(debugRawEvents(), "Timeout expired, latency=%0.3fms",
+ (now - mNextTimeout) * 0.000001f);
mNextTimeout = LLONG_MAX;
mPendingArgs += timeoutExpiredLocked(now);
}
@@ -240,9 +262,7 @@
}
batchSize += 1;
}
- if (debugRawEvents()) {
- ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
- }
+ ALOGD_IF(debugRawEvents(), "BatchSize: %zu Count: %zu", batchSize, count);
out += processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
} else {
switch (rawEvent->type) {
@@ -270,7 +290,8 @@
}
InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(eventHubId);
- std::shared_ptr<InputDevice> device = createDeviceLocked(when, eventHubId, identifier);
+ ftl::Flags<InputDeviceClass> classes = mEventHub->getDeviceClasses(eventHubId);
+ std::shared_ptr<InputDevice> device = createDeviceLocked(when, eventHubId, identifier, classes);
mPendingArgs += device->configure(when, mConfig, /*changes=*/{});
mPendingArgs += device->reset(when);
@@ -353,12 +374,16 @@
}
std::shared_ptr<InputDevice> InputReader::createDeviceLocked(
- nsecs_t when, int32_t eventHubId, const InputDeviceIdentifier& identifier) {
- auto deviceIt = std::find_if(mDevices.begin(), mDevices.end(), [identifier](auto& devicePair) {
- const InputDeviceIdentifier identifier2 =
- devicePair.second->getDeviceInfo().getIdentifier();
- return isSubDevice(identifier, identifier2);
- });
+ nsecs_t when, int32_t eventHubId, const InputDeviceIdentifier& identifier,
+ ftl::Flags<InputDeviceClass> classes) {
+ auto deviceIt =
+ std::find_if(mDevices.begin(), mDevices.end(), [identifier, classes](auto& devicePair) {
+ const InputDeviceIdentifier identifier2 =
+ devicePair.second->getDeviceInfo().getIdentifier();
+ const ftl::Flags<InputDeviceClass> classes2 = devicePair.second->getClasses();
+ return isSubDevice(identifier, identifier2) &&
+ isCompatibleSubDevice(classes, classes2);
+ });
std::shared_ptr<InputDevice> device;
if (deviceIt != mDevices.end()) {
@@ -589,6 +614,11 @@
}
}
+void InputReader::resetLockedModifierState() {
+ std::scoped_lock _l(mLock);
+ updateLedMetaStateLocked(0);
+}
+
bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
const std::vector<int32_t>& keyCodes, uint8_t* outFlags) {
std::scoped_lock _l(mLock);
@@ -901,6 +931,18 @@
mPreventingTouchpadTaps = true;
}
+bool InputReader::setKernelWakeEnabled(int32_t deviceId, bool enabled) {
+ std::scoped_lock _l(mLock);
+ if (!com::android::input::flags::set_input_device_kernel_wake()){
+ return false;
+ }
+ InputDevice* device = findInputDeviceLocked(deviceId);
+ if (device) {
+ return device->setKernelWakeEnabled(enabled);
+ }
+ return false;
+}
+
void InputReader::dump(std::string& dump) {
std::scoped_lock _l(mLock);
@@ -1067,7 +1109,7 @@
return mReader->mEventHub.get();
}
-int32_t InputReader::ContextImpl::getNextId() {
+int32_t InputReader::ContextImpl::getNextId() const {
return mIdGenerator.nextId();
}
diff --git a/services/inputflinger/reader/controller/PeripheralController.cpp b/services/inputflinger/reader/controller/PeripheralController.cpp
index 49ad8b5..df22890 100644
--- a/services/inputflinger/reader/controller/PeripheralController.cpp
+++ b/services/inputflinger/reader/controller/PeripheralController.cpp
@@ -47,10 +47,6 @@
return (brightness & 0xff) << 24 | (red & 0xff) << 16 | (green & 0xff) << 8 | (blue & 0xff);
}
-static inline bool isKeyboardBacklightCustomLevelsEnabled() {
- return sysprop::InputProperties::enable_keyboard_backlight_custom_levels().value_or(true);
-}
-
/**
* Input controller owned by InputReader device, implements the native API for querying input
* lights, getting and setting the lights brightness and color, by interacting with EventHub
@@ -82,10 +78,8 @@
if (rawMaxBrightness != MAX_BRIGHTNESS) {
brightness = brightness * ratio;
}
- if (DEBUG_LIGHT_DETAILS) {
- ALOGD("getRawLightBrightness rawLightId %d brightness 0x%x ratio %.2f", rawLightId,
- brightness, ratio);
- }
+ ALOGD_IF(DEBUG_LIGHT_DETAILS, "getRawLightBrightness rawLightId %d brightness 0x%x ratio %.2f",
+ rawLightId, brightness, ratio);
return brightness;
}
@@ -101,10 +95,8 @@
if (rawMaxBrightness != MAX_BRIGHTNESS) {
brightness = ceil(brightness / ratio);
}
- if (DEBUG_LIGHT_DETAILS) {
- ALOGD("setRawLightBrightness rawLightId %d brightness 0x%x ratio %.2f", rawLightId,
- brightness, ratio);
- }
+ ALOGD_IF(DEBUG_LIGHT_DETAILS, "setRawLightBrightness rawLightId %d brightness 0x%x ratio %.2f",
+ rawLightId, brightness, ratio);
context.setLightBrightness(rawLightId, brightness);
}
@@ -289,8 +281,7 @@
std::set<BrightnessLevel> PeripheralController::getPreferredBrightnessLevels(
const Light* light) const {
std::set<BrightnessLevel> levels;
- if (!isKeyboardBacklightCustomLevelsEnabled() ||
- light->type != InputDeviceLightType::KEYBOARD_BACKLIGHT) {
+ if (light->type != InputDeviceLightType::KEYBOARD_BACKLIGHT) {
return levels;
}
std::optional<std::string> keyboardBacklightLevels =
@@ -458,10 +449,9 @@
if (rawInfo->flags.test(InputLightClass::GLOBAL)) {
rawGlobalId = rawId;
}
- if (DEBUG_LIGHT_DETAILS) {
- ALOGD("Light rawId %d name %s max %d flags %s \n", rawInfo->id, rawInfo->name.c_str(),
- rawInfo->maxBrightness.value_or(MAX_BRIGHTNESS), rawInfo->flags.string().c_str());
- }
+ ALOGD_IF(DEBUG_LIGHT_DETAILS, "Light rawId %d name %s max %d flags %s\n", rawInfo->id,
+ rawInfo->name.c_str(), rawInfo->maxBrightness.value_or(MAX_BRIGHTNESS),
+ rawInfo->flags.string().c_str());
}
// Construct a player ID light
@@ -478,10 +468,8 @@
}
// Construct a RGB light for composed RGB light
if (hasRedLed && hasGreenLed && hasBlueLed) {
- if (DEBUG_LIGHT_DETAILS) {
- ALOGD("Rgb light ids [%d, %d, %d] \n", rawRgbIds.at(LightColor::RED),
- rawRgbIds.at(LightColor::GREEN), rawRgbIds.at(LightColor::BLUE));
- }
+ ALOGD_IF(DEBUG_LIGHT_DETAILS, "Rgb light ids [%d, %d, %d]\n", rawRgbIds.at(LightColor::RED),
+ rawRgbIds.at(LightColor::GREEN), rawRgbIds.at(LightColor::BLUE));
bool isKeyboardBacklight = keyboardBacklightIds.find(rawRgbIds.at(LightColor::RED)) !=
keyboardBacklightIds.end() &&
keyboardBacklightIds.find(rawRgbIds.at(LightColor::GREEN)) !=
@@ -514,6 +502,8 @@
type = InputDeviceLightType::KEYBOARD_BACKLIGHT;
} else if (rawInfo.flags.test(InputLightClass::KEYBOARD_MIC_MUTE)) {
type = InputDeviceLightType::KEYBOARD_MIC_MUTE;
+ } else if (rawInfo.flags.test(InputLightClass::KEYBOARD_VOLUME_MUTE)) {
+ type = InputDeviceLightType::KEYBOARD_VOLUME_MUTE;
} else {
type = InputDeviceLightType::INPUT;
}
@@ -521,9 +511,8 @@
// If the node is multi-color led, construct a MULTI_COLOR light
if (rawInfo.flags.test(InputLightClass::MULTI_INDEX) &&
rawInfo.flags.test(InputLightClass::MULTI_INTENSITY)) {
- if (DEBUG_LIGHT_DETAILS) {
- ALOGD("Multicolor light Id %d name %s \n", rawInfo.id, rawInfo.name.c_str());
- }
+ ALOGD_IF(DEBUG_LIGHT_DETAILS, "Multicolor light Id %d name %s\n", rawInfo.id,
+ rawInfo.name.c_str());
std::unique_ptr<Light> light =
std::make_unique<MultiColorLight>(getDeviceContext(), rawInfo.name, ++mNextId,
type, rawInfo.id);
@@ -531,9 +520,8 @@
continue;
}
// Construct a Mono LED light
- if (DEBUG_LIGHT_DETAILS) {
- ALOGD("Mono light Id %d name %s \n", rawInfo.id, rawInfo.name.c_str());
- }
+ ALOGD_IF(DEBUG_LIGHT_DETAILS, "Mono light Id %d name %s\n", rawInfo.id,
+ rawInfo.name.c_str());
std::unique_ptr<Light> light = std::make_unique<MonoLight>(getDeviceContext(), rawInfo.name,
++mNextId, type, rawInfo.id);
@@ -555,10 +543,8 @@
return false;
}
auto& light = it->second;
- if (DEBUG_LIGHT_DETAILS) {
- ALOGD("setLightColor lightId %d type %s color 0x%x", lightId,
- ftl::enum_string(light->type).c_str(), color);
- }
+ ALOGD_IF(DEBUG_LIGHT_DETAILS, "setLightColor lightId %d type %s color 0x%x", lightId,
+ ftl::enum_string(light->type).c_str(), color);
return light->setLightColor(color);
}
@@ -569,10 +555,8 @@
}
auto& light = it->second;
std::optional<int32_t> color = light->getLightColor();
- if (DEBUG_LIGHT_DETAILS) {
- ALOGD("getLightColor lightId %d type %s color 0x%x", lightId,
- ftl::enum_string(light->type).c_str(), color.value_or(0));
- }
+ ALOGD_IF(DEBUG_LIGHT_DETAILS, "getLightColor lightId %d type %s color 0x%x", lightId,
+ ftl::enum_string(light->type).c_str(), color.value_or(0));
return color;
}
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index dffd8e3..adbfdeb 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -21,6 +21,7 @@
#include <filesystem>
#include <functional>
#include <map>
+#include <memory>
#include <optional>
#include <ostream>
#include <string>
@@ -87,6 +88,7 @@
* If any new classes are added, we need to add them in rust input side too.
*/
enum class InputDeviceClass : uint32_t {
+ // LINT.IfChange
/* The input device is a keyboard or has buttons. */
KEYBOARD = android::os::IInputConstants::DEVICE_CLASS_KEYBOARD,
@@ -143,6 +145,7 @@
/* The input device is external (not built-in). */
EXTERNAL = android::os::IInputConstants::DEVICE_CLASS_EXTERNAL,
+ // LINT.ThenChange(frameworks/native/services/inputflinger/tests/fuzzers/MapperHelpers.h)
};
enum class SysfsClass : uint32_t {
@@ -179,6 +182,8 @@
KEYBOARD_BACKLIGHT = 0x00000100,
/* The input light has mic_mute name */
KEYBOARD_MIC_MUTE = 0x00000200,
+ /* The input light has mute name */
+ KEYBOARD_VOLUME_MUTE = 0x00000400,
};
enum class InputBatteryClass : uint32_t {
@@ -396,6 +401,13 @@
/* Sysfs node changed. Reopen the Eventhub device if any new Peripheral like Light, Battery,
* etc. is detected. */
virtual void sysfsNodeChanged(const std::string& sysfsNodePath) = 0;
+
+ /* Set whether the given input device can wake up the kernel from sleep
+ * when it generates input events. By default, usually only internal (built-in)
+ * input devices can wake the kernel from sleep. For an external input device
+ * that supports remote wakeup to be able to wake the kernel, this must be called
+ * after each time the device is connected/added. */
+ virtual bool setKernelWakeEnabled(int32_t deviceId, bool enabled) = 0;
};
template <std::size_t BITS>
@@ -603,18 +615,23 @@
void sysfsNodeChanged(const std::string& sysfsNodePath) override final;
+ bool setKernelWakeEnabled(int32_t deviceId, bool enabled) override final;
+
~EventHub() override;
private:
// Holds information about the sysfs device associated with the Device.
struct AssociatedDevice {
+ AssociatedDevice(const std::filesystem::path& sysfsRootPath,
+ std::shared_ptr<PropertyMap> baseDevConfig);
// The sysfs root path of the misc device.
std::filesystem::path sysfsRootPath;
+ // The configuration of the base device.
+ std::shared_ptr<PropertyMap> baseDevConfig;
std::unordered_map<int32_t /*batteryId*/, RawBatteryInfo> batteryInfos;
std::unordered_map<int32_t /*lightId*/, RawLightInfo> lightInfos;
std::optional<RawLayoutInfo> layoutInfo;
- bool isChanged() const;
bool operator==(const AssociatedDevice&) const = default;
bool operator!=(const AssociatedDevice&) const = default;
std::string dump() const;
@@ -647,7 +664,7 @@
std::map<int /*axis*/, AxisState> absState;
std::string configurationFile;
- std::unique_ptr<PropertyMap> configuration;
+ std::shared_ptr<PropertyMap> configuration;
std::unique_ptr<VirtualKeyMap> virtualKeyMap;
KeyMap keyMap;
@@ -661,7 +678,7 @@
int32_t controllerNumber;
Device(int fd, int32_t id, std::string path, InputDeviceIdentifier identifier,
- std::shared_ptr<const AssociatedDevice> assocDev);
+ std::shared_ptr<PropertyMap> config);
~Device();
void close();
@@ -681,7 +698,6 @@
void populateAbsoluteAxisStates();
bool hasKeycodeLocked(int keycode) const;
bool hasKeycodeInternalLocked(int keycode) const;
- void loadConfigurationLocked();
bool loadVirtualKeyMapLocked();
status_t loadKeyMapLocked();
bool isExternalDeviceLocked();
@@ -713,7 +729,8 @@
void addDeviceLocked(std::unique_ptr<Device> device) REQUIRES(mLock);
void assignDescriptorLocked(InputDeviceIdentifier& identifier) REQUIRES(mLock);
std::shared_ptr<const AssociatedDevice> obtainAssociatedDeviceLocked(
- const std::filesystem::path& devicePath) const REQUIRES(mLock);
+ const std::filesystem::path& devicePath,
+ const std::shared_ptr<PropertyMap>& config) const REQUIRES(mLock);
void closeDeviceByPathLocked(const std::string& devicePath) REQUIRES(mLock);
void closeVideoDeviceByPathLocked(const std::string& devicePath) REQUIRES(mLock);
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index 8958d9e..4744dd0 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -48,7 +48,7 @@
inline InputReaderContext* getContext() { return mContext; }
inline int32_t getId() const { return mId; }
inline int32_t getControllerNumber() const { return mControllerNumber; }
- inline int32_t getGeneration() const { return mGeneration; }
+ inline virtual int32_t getGeneration() const { return mGeneration; }
inline const std::string getName() const { return mIdentifier.name; }
inline const std::string getDescriptor() { return mIdentifier.descriptor; }
inline std::optional<std::string> getBluetoothAddress() const {
@@ -59,7 +59,7 @@
inline virtual uint32_t getSources() const { return mSources; }
inline bool hasEventHubDevices() const { return !mDevices.empty(); }
- inline bool isExternal() { return mIsExternal; }
+ inline virtual bool isExternal() { return mIsExternal; }
inline std::optional<uint8_t> getAssociatedDisplayPort() const {
return mAssociatedDisplayPort;
}
@@ -79,7 +79,7 @@
inline bool isIgnored() { return !getMapperCount() && !mController; }
- inline KeyboardType getKeyboardType() const { return mKeyboardType; }
+ inline virtual KeyboardType getKeyboardType() const { return mKeyboardType; }
bool isEnabled();
@@ -124,7 +124,7 @@
int32_t getMetaState();
void setKeyboardType(KeyboardType keyboardType);
- void bumpGeneration();
+ virtual void bumpGeneration();
[[nodiscard]] NotifyDeviceResetArgs notifyReset(nsecs_t when);
@@ -139,6 +139,8 @@
std::optional<HardwareProperties> getTouchpadHardwareProperties();
+ bool setKernelWakeEnabled(bool enabled);
+
// construct and add a mapper to the input device
template <class T, typename... Args>
T& addMapper(int32_t eventHubId, Args... args) {
@@ -469,6 +471,9 @@
inline void setKeyboardType(KeyboardType keyboardType) {
return mDevice.setKeyboardType(keyboardType);
}
+ inline bool setKernelWakeEnabled(bool enabled) {
+ return mEventHub->setKernelWakeEnabled(mId, enabled);
+ }
private:
InputDevice& mDevice;
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 1003871..0d6e102 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -25,6 +25,7 @@
#include <vector>
#include "EventHub.h"
+#include "InputDevice.h"
#include "InputListener.h"
#include "InputReaderBase.h"
#include "InputReaderContext.h"
@@ -69,6 +70,8 @@
void toggleCapsLockState(int32_t deviceId) override;
+ void resetLockedModifierState() override;
+
bool hasKeys(int32_t deviceId, uint32_t sourceMask, const std::vector<int32_t>& keyCodes,
uint8_t* outFlags) override;
@@ -120,10 +123,13 @@
void notifyMouseCursorFadedOnTyping() override;
+ bool setKernelWakeEnabled(int32_t deviceId, bool enabled) override;
+
protected:
// These members are protected so they can be instrumented by test cases.
virtual std::shared_ptr<InputDevice> createDeviceLocked(nsecs_t when, int32_t deviceId,
- const InputDeviceIdentifier& identifier)
+ const InputDeviceIdentifier& identifier,
+ ftl::Flags<InputDeviceClass> classes)
REQUIRES(mLock);
// With each iteration of the loop, InputReader reads and processes one incoming message from
@@ -150,7 +156,7 @@
REQUIRES(mReader->mLock) override;
InputReaderPolicyInterface* getPolicy() REQUIRES(mReader->mLock) override;
EventHubInterface* getEventHub() REQUIRES(mReader->mLock) override;
- int32_t getNextId() NO_THREAD_SAFETY_ANALYSIS override;
+ int32_t getNextId() const NO_THREAD_SAFETY_ANALYSIS override;
void updateLedMetaState(int32_t metaState) REQUIRES(mReader->mLock) override;
int32_t getLedMetaState() REQUIRES(mReader->mLock) REQUIRES(mLock) override;
void setPreventingTouchpadTaps(bool prevent) REQUIRES(mReader->mLock)
diff --git a/services/inputflinger/reader/include/InputReaderContext.h b/services/inputflinger/reader/include/InputReaderContext.h
index e0e0ac2..20ed74f 100644
--- a/services/inputflinger/reader/include/InputReaderContext.h
+++ b/services/inputflinger/reader/include/InputReaderContext.h
@@ -55,7 +55,7 @@
virtual InputReaderPolicyInterface* getPolicy() = 0;
virtual EventHubInterface* getEventHub() = 0;
- virtual int32_t getNextId() = 0;
+ virtual int32_t getNextId() const = 0;
virtual void updateLedMetaState(int32_t metaState) = 0;
virtual int32_t getLedMetaState() = 0;
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index 630bd9b..e21c2f9 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -33,8 +33,6 @@
#include "input/PrintTools.h"
-namespace input_flags = com::android::input::flags;
-
namespace android {
// The default velocity control parameters that has no effect.
@@ -77,8 +75,7 @@
CursorInputMapper::CursorInputMapper(InputDeviceContext& deviceContext,
const InputReaderConfiguration& readerConfig)
: InputMapper(deviceContext, readerConfig),
- mLastEventTime(std::numeric_limits<nsecs_t>::min()),
- mEnableNewMousePointerBallistics(input_flags::enable_new_mouse_pointer_ballistics()) {}
+ mLastEventTime(std::numeric_limits<nsecs_t>::min()) {}
uint32_t CursorInputMapper::getSources() const {
return mSource;
@@ -207,8 +204,7 @@
mDownTime = 0;
mLastEventTime = std::numeric_limits<nsecs_t>::min();
- mOldPointerVelocityControl.reset();
- mNewPointerVelocityControl.reset();
+ mPointerVelocityControl.reset();
mWheelXVelocityControl.reset();
mWheelYVelocityControl.reset();
@@ -291,11 +287,7 @@
mWheelYVelocityControl.move(when, nullptr, &vscroll);
mWheelXVelocityControl.move(when, &hscroll, nullptr);
- if (mEnableNewMousePointerBallistics) {
- mNewPointerVelocityControl.move(when, &deltaX, &deltaY);
- } else {
- mOldPointerVelocityControl.move(when, &deltaX, &deltaY);
- }
+ mPointerVelocityControl.move(when, &deltaX, &deltaY);
float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
@@ -427,7 +419,7 @@
}
}
-std::optional<ui::LogicalDisplayId> CursorInputMapper::getAssociatedDisplayId() {
+std::optional<ui::LogicalDisplayId> CursorInputMapper::getAssociatedDisplayId() const {
return mDisplayId;
}
@@ -486,30 +478,24 @@
void CursorInputMapper::configureOnChangePointerSpeed(const InputReaderConfiguration& config) {
if (mParameters.mode == Parameters::Mode::POINTER_RELATIVE) {
// Disable any acceleration or scaling for the pointer when Pointer Capture is enabled.
- if (mEnableNewMousePointerBallistics) {
- mNewPointerVelocityControl.setAccelerationEnabled(false);
- } else {
- mOldPointerVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS);
- }
+ mPointerVelocityControl.setAccelerationEnabled(false);
mWheelXVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS);
mWheelYVelocityControl.setParameters(FLAT_VELOCITY_CONTROL_PARAMS);
- } else {
- if (mEnableNewMousePointerBallistics) {
- mNewPointerVelocityControl.setAccelerationEnabled(
- config.displaysWithMousePointerAccelerationDisabled.count(
- mDisplayId.value_or(ui::LogicalDisplayId::INVALID)) == 0);
- mNewPointerVelocityControl.setCurve(
- createAccelerationCurveForPointerSensitivity(config.mousePointerSpeed));
- } else {
- mOldPointerVelocityControl.setParameters(
- (config.displaysWithMousePointerAccelerationDisabled.count(
- mDisplayId.value_or(ui::LogicalDisplayId::INVALID)) == 0)
- ? config.pointerVelocityControlParameters
- : FLAT_VELOCITY_CONTROL_PARAMS);
- }
- mWheelXVelocityControl.setParameters(config.wheelVelocityControlParameters);
- mWheelYVelocityControl.setParameters(config.wheelVelocityControlParameters);
+ return;
}
+
+ bool disableAllScaling = config.displaysWithMouseScalingDisabled.count(
+ mDisplayId.value_or(ui::LogicalDisplayId::INVALID)) != 0;
+
+ mPointerVelocityControl.setAccelerationEnabled(!disableAllScaling);
+
+ mPointerVelocityControl.setCurve(
+ config.mousePointerAccelerationEnabled
+ ? createAccelerationCurveForPointerSensitivity(config.mousePointerSpeed)
+ : createFlatAccelerationCurve(config.mousePointerSpeed));
+
+ mWheelXVelocityControl.setParameters(config.wheelVelocityControlParameters);
+ mWheelYVelocityControl.setParameters(config.wheelVelocityControlParameters);
}
void CursorInputMapper::configureOnChangeDisplayInfo(const InputReaderConfiguration& config) {
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.h b/services/inputflinger/reader/mapper/CursorInputMapper.h
index 403e96d..f2b2b6f 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.h
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.h
@@ -63,7 +63,7 @@
virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) override;
- virtual std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() override;
+ virtual std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() const override;
private:
// Amount that trackball needs to move in order to generate a key event.
@@ -104,8 +104,7 @@
// Velocity controls for mouse pointer and wheel movements.
// The controls for X and Y wheel movements are separate to keep them decoupled.
- SimpleVelocityControl mOldPointerVelocityControl;
- CurvedVelocityControl mNewPointerVelocityControl;
+ CurvedVelocityControl mPointerVelocityControl;
SimpleVelocityControl mWheelXVelocityControl;
SimpleVelocityControl mWheelYVelocityControl;
@@ -116,11 +115,11 @@
ui::Rotation mOrientation{ui::ROTATION_0};
FloatRect mBoundsInLogicalDisplay{};
+ // The button state as of the last sync.
int32_t mButtonState;
nsecs_t mDownTime;
nsecs_t mLastEventTime;
- const bool mEnableNewMousePointerBallistics;
bool mMouseReverseVerticalScrolling = false;
explicit CursorInputMapper(InputDeviceContext& deviceContext,
diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h
index d4a86ac..630c3d9 100644
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ b/services/inputflinger/reader/mapper/InputMapper.h
@@ -66,11 +66,12 @@
virtual ~InputMapper();
- inline int32_t getDeviceId() { return mDeviceContext.getId(); }
+ inline int32_t getDeviceId() const { return mDeviceContext.getId(); }
inline InputDeviceContext& getDeviceContext() { return mDeviceContext; }
inline InputDeviceContext& getDeviceContext() const { return mDeviceContext; };
inline const std::string getDeviceName() const { return mDeviceContext.getName(); }
inline InputReaderContext* getContext() { return mDeviceContext.getContext(); }
+ inline const InputReaderContext* getContext() const { return mDeviceContext.getContext(); }
inline InputReaderPolicyInterface* getPolicy() { return getContext()->getPolicy(); }
virtual uint32_t getSources() const = 0;
@@ -114,7 +115,9 @@
[[nodiscard]] virtual std::list<NotifyArgs> updateExternalStylusState(const StylusState& state);
- virtual std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() { return std::nullopt; }
+ virtual std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() const {
+ return std::nullopt;
+ }
virtual void updateLedState(bool reset) {}
virtual std::optional<HardwareProperties> getTouchpadHardwareProperties();
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
index 567a3e2..400792b 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -104,14 +104,14 @@
return mMapperSource;
}
-ui::Rotation KeyboardInputMapper::getOrientation() {
+ui::Rotation KeyboardInputMapper::getOrientation() const {
if (mViewport) {
return mViewport->orientation;
}
return ui::ROTATION_0;
}
-ui::LogicalDisplayId KeyboardInputMapper::getDisplayId() {
+ui::LogicalDisplayId KeyboardInputMapper::getDisplayId() const {
if (mViewport) {
return mViewport->displayId;
}
@@ -132,7 +132,9 @@
void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo& info) {
InputMapper::populateDeviceInfo(info);
- info.setKeyCharacterMap(getDeviceContext().getKeyCharacterMap());
+ if (const auto kcm = getDeviceContext().getKeyCharacterMap(); kcm != nullptr) {
+ info.setKeyCharacterMap(std::make_unique<KeyCharacterMap>(*kcm));
+ }
std::optional keyboardLayoutInfo = getKeyboardLayoutInfo();
if (keyboardLayoutInfo) {
@@ -241,11 +243,16 @@
mHidUsageAccumulator.process(rawEvent);
switch (rawEvent.type) {
case EV_KEY: {
- int32_t scanCode = rawEvent.code;
+ // Skip processing repeated keys (value == 2) since auto repeat is handled by Android
+ // internally.
+ if (rawEvent.value == 2) {
+ break;
+ }
+ const int32_t scanCode = rawEvent.code;
if (isSupportedScanCode(scanCode)) {
- out += processKey(rawEvent.when, rawEvent.readTime, rawEvent.value != 0,
- scanCode, mHidUsageAccumulator.consumeCurrentHidUsage());
+ out += processKey(rawEvent.when, rawEvent.readTime, rawEvent.value != 0, scanCode,
+ mHidUsageAccumulator.consumeCurrentHidUsage());
}
break;
}
@@ -337,12 +344,14 @@
}
KeyboardType keyboardType = getDeviceContext().getKeyboardType();
- // Any key down on an external keyboard should wake the device.
- // We don't do this for internal keyboards to prevent them from waking up in your pocket.
+ // Any key down on an external keyboard or internal alphanumeric keyboard should wake the
+ // device. We don't do this for non-alphanumeric internal keyboards to prevent them from
+ // waking up in your pocket.
// For internal keyboards and devices for which the default wake behavior is explicitly
// prevented (e.g. TV remotes), the key layout file should specify the policy flags for each
// wake key individually.
- if (down && getDeviceContext().isExternal() && !mParameters.doNotWakeByDefault &&
+ if (down && !mParameters.doNotWakeByDefault &&
+ (getDeviceContext().isExternal() || wakeOnAlphabeticKeyboard(keyboardType)) &&
!(keyboardType != KeyboardType::ALPHABETIC && isMediaKey(keyCode))) {
policyFlags |= POLICY_FLAG_WAKE;
}
@@ -462,7 +471,7 @@
}
}
-std::optional<ui::LogicalDisplayId> KeyboardInputMapper::getAssociatedDisplayId() {
+std::optional<ui::LogicalDisplayId> KeyboardInputMapper::getAssociatedDisplayId() const {
if (mViewport) {
return std::make_optional(mViewport->displayId);
}
@@ -500,4 +509,8 @@
return deviceSources & ALL_KEYBOARD_SOURCES;
}
+bool KeyboardInputMapper::wakeOnAlphabeticKeyboard(const KeyboardType keyboardType) const {
+ return mEnableAlphabeticKeyboardWakeFlag && (KeyboardType::ALPHABETIC == keyboardType);
+}
+
} // namespace android
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.h b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
index 10bd424..9e2a81b 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
@@ -16,6 +16,8 @@
#pragma once
+#include <com_android_input_flags.h>
+
#include "HidUsageAccumulator.h"
#include "InputMapper.h"
@@ -45,7 +47,7 @@
int32_t getKeyCodeForKeyLocation(int32_t locationKeyCode) const override;
int32_t getMetaState() override;
- std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() override;
+ std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() const override;
void updateLedState(bool reset) override;
private:
@@ -85,13 +87,17 @@
bool doNotWakeByDefault{};
} mParameters{};
+ // Store the value of enable wake for alphanumeric keyboard flag.
+ const bool mEnableAlphabeticKeyboardWakeFlag =
+ com::android::input::flags::enable_alphabetic_keyboard_wake();
+
KeyboardInputMapper(InputDeviceContext& deviceContext,
const InputReaderConfiguration& readerConfig, uint32_t source);
void configureParameters();
void dumpParameters(std::string& dump) const;
- ui::Rotation getOrientation();
- ui::LogicalDisplayId getDisplayId();
+ ui::Rotation getOrientation() const;
+ ui::LogicalDisplayId getDisplayId() const;
[[nodiscard]] std::list<NotifyArgs> processKey(nsecs_t when, nsecs_t readTime, bool down,
int32_t scanCode, int32_t usageCode);
@@ -109,6 +115,8 @@
[[nodiscard]] std::list<NotifyArgs> cancelAllDownKeys(nsecs_t when);
void onKeyDownProcessed(nsecs_t downTime);
uint32_t getEventSource() const;
+
+ bool wakeOnAlphabeticKeyboard(const KeyboardType keyboardType) const;
};
} // namespace android
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
index fd8224a..4d08f19 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
@@ -79,19 +79,17 @@
if (id) {
outState->rawPointerData.canceledIdBits.markBit(id.value());
}
- if (DEBUG_POINTERS) {
- ALOGI("Stop processing slot %zu for it received a palm event from device %s",
- inIndex, getDeviceName().c_str());
- }
+ ALOGI_IF(DEBUG_POINTERS,
+ "Stop processing slot %zu for it received a palm event from device %s",
+ inIndex, getDeviceName().c_str());
continue;
}
if (outCount >= MAX_POINTERS) {
- if (DEBUG_POINTERS) {
- ALOGD("MultiTouch device %s emitted more than maximum of %zu pointers; "
- "ignoring the rest.",
- getDeviceName().c_str(), MAX_POINTERS);
- }
+ ALOGD_IF(DEBUG_POINTERS,
+ "MultiTouch device %s emitted more than maximum of %zu pointers; ignoring the "
+ "rest.",
+ getDeviceName().c_str(), MAX_POINTERS);
break; // too many fingers!
}
diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.cpp b/services/inputflinger/reader/mapper/SensorInputMapper.cpp
index 4233f78..0d1d884 100644
--- a/services/inputflinger/reader/mapper/SensorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/SensorInputMapper.cpp
@@ -212,7 +212,7 @@
// One input device can only have 1 sensor for each sensor Type.
InputDeviceSensorInfo sensorInfo(identifier.name, std::to_string(identifier.vendor),
identifier.version, sensorType,
- InputDeviceSensorAccuracy::ACCURACY_HIGH,
+ InputDeviceSensorAccuracy::HIGH,
/*maxRange=*/axis.max, /*resolution=*/axis.scale,
/*power=*/config.getFloat(prefix + ".power").value_or(0.0f),
/*minDelay=*/config.getInt(prefix + ".minDelay").value_or(0),
@@ -235,9 +235,8 @@
// else calculate difference between previous and current MSC_TIMESTAMP
if (mPrevMscTime == 0) {
mHardwareTimestamp = evTime;
- if (DEBUG_SENSOR_EVENT_DETAILS) {
- ALOGD("Initialize hardware timestamp = %" PRId64, mHardwareTimestamp);
- }
+ ALOGD_IF(DEBUG_SENSOR_EVENT_DETAILS, "Initialize hardware timestamp = %" PRId64,
+ mHardwareTimestamp);
} else {
// Calculate the difference between current msc_timestamp and
// previous msc_timestamp, including when msc_timestamp wraps around.
@@ -330,11 +329,10 @@
bool SensorInputMapper::enableSensor(InputDeviceSensorType sensorType,
std::chrono::microseconds samplingPeriod,
std::chrono::microseconds maxBatchReportLatency) {
- if (DEBUG_SENSOR_EVENT_DETAILS) {
- ALOGD("Enable Sensor %s samplingPeriod %lld maxBatchReportLatency %lld",
- ftl::enum_string(sensorType).c_str(), samplingPeriod.count(),
- maxBatchReportLatency.count());
- }
+ ALOGD_IF(DEBUG_SENSOR_EVENT_DETAILS,
+ "Enable Sensor %s samplingPeriod %lld maxBatchReportLatency %lld",
+ ftl::enum_string(sensorType).c_str(), samplingPeriod.count(),
+ maxBatchReportLatency.count());
if (!setSensorEnabled(sensorType, /*enabled=*/true)) {
return false;
@@ -355,9 +353,7 @@
}
void SensorInputMapper::disableSensor(InputDeviceSensorType sensorType) {
- if (DEBUG_SENSOR_EVENT_DETAILS) {
- ALOGD("Disable Sensor %s", ftl::enum_string(sensorType).c_str());
- }
+ ALOGD_IF(DEBUG_SENSOR_EVENT_DETAILS, "Disable Sensor %s", ftl::enum_string(sensorType).c_str());
if (!setSensorEnabled(sensorType, /*enabled=*/false)) {
return;
@@ -389,15 +385,12 @@
}
nsecs_t timestamp = mHasHardwareTimestamp ? mHardwareTimestamp : when;
- if (DEBUG_SENSOR_EVENT_DETAILS) {
- ALOGD("Sensor %s timestamp %" PRIu64 " values [%f %f %f]",
- ftl::enum_string(sensorType).c_str(), timestamp, values[0], values[1], values[2]);
- }
+ ALOGD_IF(DEBUG_SENSOR_EVENT_DETAILS, "Sensor %s timestamp %" PRIu64 " values [%f %f %f]",
+ ftl::enum_string(sensorType).c_str(), timestamp, values[0], values[1], values[2]);
if (sensor.lastSampleTimeNs.has_value() &&
timestamp - sensor.lastSampleTimeNs.value() < sensor.samplingPeriod.count()) {
- if (DEBUG_SENSOR_EVENT_DETAILS) {
- ALOGD("Sensor %s Skip a sample.", ftl::enum_string(sensorType).c_str());
- }
+ ALOGD_IF(DEBUG_SENSOR_EVENT_DETAILS, "Sensor %s Skip a sample.",
+ ftl::enum_string(sensorType).c_str());
} else {
// Convert to Android unit
convertFromLinuxToAndroid(values, sensorType);
diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.h b/services/inputflinger/reader/mapper/SensorInputMapper.h
index 63bc151..7974efe 100644
--- a/services/inputflinger/reader/mapper/SensorInputMapper.h
+++ b/services/inputflinger/reader/mapper/SensorInputMapper.h
@@ -101,7 +101,7 @@
std::array<int32_t, SENSOR_VEC_LEN> dataVec;
void resetValue() {
this->enabled = false;
- this->accuracy = InputDeviceSensorAccuracy::ACCURACY_NONE;
+ this->accuracy = InputDeviceSensorAccuracy::NONE;
this->samplingPeriod = std::chrono::nanoseconds(0);
this->maxBatchReportLatency = std::chrono::nanoseconds(0);
this->lastSampleTimeNs = std::nullopt;
diff --git a/services/inputflinger/reader/mapper/SlopController.cpp b/services/inputflinger/reader/mapper/SlopController.cpp
index 9ec02a6..d55df51 100644
--- a/services/inputflinger/reader/mapper/SlopController.cpp
+++ b/services/inputflinger/reader/mapper/SlopController.cpp
@@ -54,13 +54,13 @@
mCumulativeValue += value;
if (abs(mCumulativeValue) >= mSlopThreshold) {
- ALOGD("SlopController: did not drop event with value .%3f", value);
+ ALOGD("SlopController: did not drop event with value %.3f", value);
mHasSlopBeenMet = true;
// Return the amount of value that exceeds the slop.
return signOf(value) * (abs(mCumulativeValue) - mSlopThreshold);
}
- ALOGD("SlopController: dropping event with value .%3f", value);
+ ALOGD("SlopController: dropping event with value %.3f", value);
return 0;
}
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 5c90cbb..8deff6b 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -30,6 +30,7 @@
#include <android-base/stringprintf.h>
#include <android/input.h>
+#include <com_android_input_flags.h>
#include <ftl/enum.h>
#include <input/PrintTools.h>
#include <input/PropertyMap.h>
@@ -47,6 +48,8 @@
namespace android {
+namespace input_flags = com::android::input::flags;
+
// --- Constants ---
// Artificial latency on synthetic events created from stylus data without corresponding touch
@@ -299,6 +302,8 @@
ConfigurationChanges changes) {
std::list<NotifyArgs> out = InputMapper::reconfigure(when, config, changes);
+ std::optional<ui::LogicalDisplayId> previousDisplayId = getAssociatedDisplayId();
+
mConfig = config;
// Full configuration should happen the first time configure is called and
@@ -347,6 +352,8 @@
}
if (changes.any() && resetNeeded) {
+ // Touches should be aborted using the previous display id, so that the stream is consistent
+ out += abortTouches(when, when, /*policyFlags=*/0, previousDisplayId);
out += reset(when);
// Send reset, unless this is the first time the device has been configured,
@@ -1575,7 +1582,8 @@
mLastCookedState.buttonState, mCurrentCookedState.buttonState);
// Dispatch the touches either directly or by translation through a pointer on screen.
- if (mDeviceMode == DeviceMode::POINTER) {
+ if (!input_flags::disable_touch_input_mapper_pointer_usage() &&
+ mDeviceMode == DeviceMode::POINTER) {
for (BitSet32 idBits(mCurrentRawState.rawPointerData.touchingIdBits); !idBits.isEmpty();) {
uint32_t id = idBits.clearFirstMarkedBit();
const RawPointerData::Pointer& pointer =
@@ -1613,7 +1621,9 @@
}
out += dispatchPointerUsage(when, readTime, policyFlags, pointerUsage);
- } else {
+ }
+ if (input_flags::disable_touch_input_mapper_pointer_usage() ||
+ mDeviceMode != DeviceMode::POINTER) {
if (!mCurrentMotionAborted) {
out += dispatchButtonRelease(when, readTime, policyFlags);
out += dispatchHoverExit(when, readTime, policyFlags);
@@ -1651,6 +1661,10 @@
mParameters.hasAssociatedDisplay;
}
+ui::LogicalDisplayId TouchInputMapper::resolveDisplayId() const {
+ return getAssociatedDisplayId().value_or(ui::LogicalDisplayId::INVALID);
+};
+
void TouchInputMapper::applyExternalStylusButtonState(nsecs_t when) {
if (mDeviceMode == DeviceMode::DIRECT && hasExternalStylus()) {
// If any of the external buttons are already pressed by the touch device, ignore them.
@@ -1922,8 +1936,9 @@
keyEventFlags, keyCode, scanCode, metaState, downTime);
}
-std::list<NotifyArgs> TouchInputMapper::abortTouches(nsecs_t when, nsecs_t readTime,
- uint32_t policyFlags) {
+std::list<NotifyArgs> TouchInputMapper::abortTouches(
+ nsecs_t when, nsecs_t readTime, uint32_t policyFlags,
+ std::optional<ui::LogicalDisplayId> currentGestureDisplayId) {
std::list<NotifyArgs> out;
if (mCurrentMotionAborted) {
// Current motion event was already aborted.
@@ -1934,6 +1949,7 @@
int32_t metaState = getContext()->getGlobalMetaState();
int32_t buttonState = mCurrentCookedState.buttonState;
out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
+ currentGestureDisplayId.value_or(resolveDisplayId()),
AMOTION_EVENT_ACTION_CANCEL, 0, AMOTION_EVENT_FLAG_CANCELED,
metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
mCurrentCookedState.cookedPointerData.pointerProperties,
@@ -1988,14 +2004,15 @@
if (!currentIdBits.isEmpty()) {
// No pointer id changes so this is a move event.
// The listener takes care of batching moves so we don't have to deal with that here.
- out.push_back(
- dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE,
- 0, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- mCurrentCookedState.cookedPointerData.pointerProperties,
- mCurrentCookedState.cookedPointerData.pointerCoords,
- mCurrentCookedState.cookedPointerData.idToIndex, currentIdBits,
- -1, mOrientedXPrecision, mOrientedYPrecision, mDownTime,
- MotionClassification::NONE));
+ out.push_back(dispatchMotion(when, readTime, policyFlags, mSource, resolveDisplayId(),
+ AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
+ AMOTION_EVENT_EDGE_FLAG_NONE,
+ mCurrentCookedState.cookedPointerData.pointerProperties,
+ mCurrentCookedState.cookedPointerData.pointerCoords,
+ mCurrentCookedState.cookedPointerData.idToIndex,
+ currentIdBits, -1, mOrientedXPrecision,
+ mOrientedYPrecision, mDownTime,
+ MotionClassification::NONE));
}
} else {
// There may be pointers going up and pointers going down and pointers moving
@@ -2025,7 +2042,7 @@
if (isCanceled) {
ALOGI("Canceling pointer %d for the palm event was detected.", upId);
}
- out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
+ out.push_back(dispatchMotion(when, readTime, policyFlags, mSource, resolveDisplayId(),
AMOTION_EVENT_ACTION_POINTER_UP, 0,
isCanceled ? AMOTION_EVENT_FLAG_CANCELED : 0, metaState,
buttonState, 0,
@@ -2044,7 +2061,7 @@
// events, they do not generally handle them except when presented in a move event.
if (moveNeeded && !moveIdBits.isEmpty()) {
ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
- out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
+ out.push_back(dispatchMotion(when, readTime, policyFlags, mSource, resolveDisplayId(),
AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, 0,
mCurrentCookedState.cookedPointerData.pointerProperties,
mCurrentCookedState.cookedPointerData.pointerCoords,
@@ -2065,7 +2082,7 @@
}
out.push_back(
- dispatchMotion(when, readTime, policyFlags, mSource,
+ dispatchMotion(when, readTime, policyFlags, mSource, resolveDisplayId(),
AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState,
0, mCurrentCookedState.cookedPointerData.pointerProperties,
mCurrentCookedState.cookedPointerData.pointerCoords,
@@ -2084,7 +2101,7 @@
(mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty() ||
!mCurrentCookedState.cookedPointerData.touchingIdBits.isEmpty())) {
int32_t metaState = getContext()->getGlobalMetaState();
- out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
+ out.push_back(dispatchMotion(when, readTime, policyFlags, mSource, resolveDisplayId(),
AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState,
mLastCookedState.buttonState, 0,
mLastCookedState.cookedPointerData.pointerProperties,
@@ -2105,7 +2122,7 @@
!mCurrentCookedState.cookedPointerData.hoveringIdBits.isEmpty()) {
int32_t metaState = getContext()->getGlobalMetaState();
if (!mSentHoverEnter) {
- out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
+ out.push_back(dispatchMotion(when, readTime, policyFlags, mSource, resolveDisplayId(),
AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0, metaState,
mCurrentRawState.buttonState, 0,
mCurrentCookedState.cookedPointerData.pointerProperties,
@@ -2117,7 +2134,7 @@
mSentHoverEnter = true;
}
- out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
+ out.push_back(dispatchMotion(when, readTime, policyFlags, mSource, resolveDisplayId(),
AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
mCurrentRawState.buttonState, 0,
mCurrentCookedState.cookedPointerData.pointerProperties,
@@ -2140,7 +2157,7 @@
while (!releasedButtons.isEmpty()) {
int32_t actionButton = BitSet32::valueForBit(releasedButtons.clearFirstMarkedBit());
buttonState &= ~actionButton;
- out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
+ out.push_back(dispatchMotion(when, readTime, policyFlags, mSource, resolveDisplayId(),
AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
metaState, buttonState, 0,
mLastCookedState.cookedPointerData.pointerProperties,
@@ -2162,7 +2179,7 @@
while (!pressedButtons.isEmpty()) {
int32_t actionButton = BitSet32::valueForBit(pressedButtons.clearFirstMarkedBit());
buttonState |= actionButton;
- out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
+ out.push_back(dispatchMotion(when, readTime, policyFlags, mSource, resolveDisplayId(),
AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0, metaState,
buttonState, 0,
mCurrentCookedState.cookedPointerData.pointerProperties,
@@ -2186,7 +2203,7 @@
while (!releasedButtons.isEmpty()) {
int32_t actionButton = BitSet32::valueForBit(releasedButtons.clearFirstMarkedBit());
buttonState &= ~actionButton;
- out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
+ out.push_back(dispatchMotion(when, readTime, policyFlags, mSource, resolveDisplayId(),
AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
metaState, buttonState, 0,
mPointerGesture.lastGestureProperties,
@@ -2210,7 +2227,7 @@
while (!pressedButtons.isEmpty()) {
int32_t actionButton = BitSet32::valueForBit(pressedButtons.clearFirstMarkedBit());
buttonState |= actionButton;
- out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
+ out.push_back(dispatchMotion(when, readTime, policyFlags, mSource, resolveDisplayId(),
AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0, metaState,
buttonState, 0, mPointerGesture.currentGestureProperties,
mPointerGesture.currentGestureCoords,
@@ -2251,6 +2268,23 @@
for (uint32_t i = 0; i < currentPointerCount; i++) {
const RawPointerData::Pointer& in = mCurrentRawState.rawPointerData.pointers[i];
+ bool isHovering = in.isHovering;
+
+ // A tool MOUSE pointer is only down/touching when a mouse button is pressed.
+ if (input_flags::disable_touch_input_mapper_pointer_usage() &&
+ in.toolType == ToolType::MOUSE &&
+ !mCurrentRawState.rawPointerData.canceledIdBits.hasBit(in.id)) {
+ if (isPointerDown(mCurrentRawState.buttonState)) {
+ isHovering = false;
+ mCurrentCookedState.cookedPointerData.touchingIdBits.markBit(in.id);
+ mCurrentCookedState.cookedPointerData.hoveringIdBits.clearBit(in.id);
+ } else {
+ isHovering = true;
+ mCurrentCookedState.cookedPointerData.touchingIdBits.clearBit(in.id);
+ mCurrentCookedState.cookedPointerData.hoveringIdBits.markBit(in.id);
+ }
+ }
+
// Size
float touchMajor, touchMinor, toolMajor, toolMinor, size;
switch (mCalibration.sizeCalibration) {
@@ -2340,7 +2374,7 @@
pressure = in.pressure * mPressureScale;
break;
default:
- pressure = in.isHovering ? 0 : 1;
+ pressure = isHovering ? 0 : 1;
break;
}
@@ -2541,7 +2575,7 @@
if (!dispatchedGestureIdBits.isEmpty()) {
if (cancelPreviousGesture) {
const uint32_t cancelFlags = flags | AMOTION_EVENT_FLAG_CANCELED;
- out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
+ out.push_back(dispatchMotion(when, readTime, policyFlags, mSource, resolveDisplayId(),
AMOTION_EVENT_ACTION_CANCEL, 0, cancelFlags, metaState,
buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
mPointerGesture.lastGestureProperties,
@@ -2568,8 +2602,9 @@
}
const uint32_t id = upGestureIdBits.clearFirstMarkedBit();
out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
- AMOTION_EVENT_ACTION_POINTER_UP, 0, flags, metaState,
- buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+ resolveDisplayId(), AMOTION_EVENT_ACTION_POINTER_UP, 0,
+ flags, metaState, buttonState,
+ AMOTION_EVENT_EDGE_FLAG_NONE,
mPointerGesture.lastGestureProperties,
mPointerGesture.lastGestureCoords,
mPointerGesture.lastGestureIdToIndex,
@@ -2583,13 +2618,14 @@
// Send motion events for all pointers that moved.
if (moveNeeded) {
- out.push_back(
- dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0,
- flags, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- mPointerGesture.currentGestureProperties,
- mPointerGesture.currentGestureCoords,
- mPointerGesture.currentGestureIdToIndex, dispatchedGestureIdBits, -1,
- 0, 0, mPointerGesture.downTime, classification));
+ out.push_back(dispatchMotion(when, readTime, policyFlags, mSource, resolveDisplayId(),
+ AMOTION_EVENT_ACTION_MOVE, 0, flags, metaState, buttonState,
+ AMOTION_EVENT_EDGE_FLAG_NONE,
+ mPointerGesture.currentGestureProperties,
+ mPointerGesture.currentGestureCoords,
+ mPointerGesture.currentGestureIdToIndex,
+ dispatchedGestureIdBits, -1, 0, 0, mPointerGesture.downTime,
+ classification));
}
// Send motion events for all pointers that went down.
@@ -2604,7 +2640,7 @@
mPointerGesture.downTime = when;
}
- out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
+ out.push_back(dispatchMotion(when, readTime, policyFlags, mSource, resolveDisplayId(),
AMOTION_EVENT_ACTION_POINTER_DOWN, 0, flags, metaState,
buttonState, 0, mPointerGesture.currentGestureProperties,
mPointerGesture.currentGestureCoords,
@@ -2622,7 +2658,7 @@
// Send motion events for hover.
if (mPointerGesture.currentGestureMode == PointerGesture::Mode::HOVER) {
- out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
+ out.push_back(dispatchMotion(when, readTime, policyFlags, mSource, resolveDisplayId(),
AMOTION_EVENT_ACTION_HOVER_MOVE, 0, flags, metaState,
buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
mPointerGesture.currentGestureProperties,
@@ -2681,7 +2717,7 @@
if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
int32_t metaState = getContext()->getGlobalMetaState();
int32_t buttonState = mCurrentRawState.buttonState;
- out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
+ out.push_back(dispatchMotion(when, readTime, policyFlags, mSource, resolveDisplayId(),
AMOTION_EVENT_ACTION_CANCEL, 0, AMOTION_EVENT_FLAG_CANCELED,
metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
mPointerGesture.lastGestureProperties,
@@ -3475,8 +3511,7 @@
hovering = false;
}
- return dispatchPointerSimple(when, readTime, policyFlags, down, hovering,
- ui::LogicalDisplayId::INVALID);
+ return dispatchPointerSimple(when, readTime, policyFlags, down, hovering, resolveDisplayId());
}
std::list<NotifyArgs> TouchInputMapper::abortPointerMouse(nsecs_t when, nsecs_t readTime,
@@ -3639,11 +3674,12 @@
}
NotifyMotionArgs TouchInputMapper::dispatchMotion(
- nsecs_t when, nsecs_t readTime, uint32_t policyFlags, uint32_t source, int32_t action,
- int32_t actionButton, int32_t flags, int32_t metaState, int32_t buttonState,
- int32_t edgeFlags, const PropertiesArray& properties, const CoordsArray& coords,
+ nsecs_t when, nsecs_t readTime, uint32_t policyFlags, uint32_t source,
+ ui::LogicalDisplayId displayId, int32_t action, int32_t actionButton, int32_t flags,
+ int32_t metaState, int32_t buttonState, int32_t edgeFlags,
+ const PropertiesArray& properties, const CoordsArray& coords,
const IdToIndexArray& idToIndex, BitSet32 idBits, int32_t changedId, float xPrecision,
- float yPrecision, nsecs_t downTime, MotionClassification classification) {
+ float yPrecision, nsecs_t downTime, MotionClassification classification) const {
std::vector<PointerCoords> pointerCoords;
std::vector<PointerProperties> pointerProperties;
uint32_t pointerCount = 0;
@@ -3691,13 +3727,13 @@
}
}
- const ui::LogicalDisplayId displayId =
- getAssociatedDisplayId().value_or(ui::LogicalDisplayId::INVALID);
-
float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
if (mDeviceMode == DeviceMode::POINTER) {
- xCursorPosition = yCursorPosition = 0.f;
+ ALOGW_IF(pointerCount != 1,
+ "Only single pointer events are fully supported in POINTER mode");
+ xCursorPosition = pointerCoords[0].getX();
+ yCursorPosition = pointerCoords[0].getY();
}
const DeviceId deviceId = getDeviceId();
std::vector<TouchVideoFrame> frames = getDeviceContext().getVideoFrames();
@@ -3713,7 +3749,7 @@
std::list<NotifyArgs> TouchInputMapper::cancelTouch(nsecs_t when, nsecs_t readTime) {
std::list<NotifyArgs> out;
out += abortPointerUsage(when, readTime, /*policyFlags=*/0);
- out += abortTouches(when, readTime, /* policyFlags=*/0);
+ out += abortTouches(when, readTime, /* policyFlags=*/0, std::nullopt);
return out;
}
@@ -3966,15 +4002,9 @@
return true;
}
-std::optional<ui::LogicalDisplayId> TouchInputMapper::getAssociatedDisplayId() {
- if (mParameters.hasAssociatedDisplay) {
- if (mDeviceMode == DeviceMode::POINTER) {
- return ui::LogicalDisplayId::INVALID;
- } else {
- return std::make_optional(mViewport.displayId);
- }
- }
- return std::nullopt;
+std::optional<ui::LogicalDisplayId> TouchInputMapper::getAssociatedDisplayId() const {
+ return mParameters.hasAssociatedDisplay ? std::make_optional(mViewport.displayId)
+ : std::nullopt;
}
} // namespace android
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index ef0e02f..4ef0be8 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -185,7 +185,7 @@
[[nodiscard]] std::list<NotifyArgs> timeoutExpired(nsecs_t when) override;
[[nodiscard]] std::list<NotifyArgs> updateExternalStylusState(
const StylusState& state) override;
- std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() override;
+ std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() const override;
protected:
CursorButtonAccumulator mCursorButtonAccumulator;
@@ -215,7 +215,7 @@
DISABLED, // input is disabled
DIRECT, // direct mapping (touchscreen)
NAVIGATION, // unscaled mapping with assist gesture (touch navigation)
- POINTER, // pointer mapping (e.g. uncaptured touchpad, drawing tablet)
+ POINTER, // pointer mapping (e.g. absolute mouse, drawing tablet)
ftl_last = POINTER
};
@@ -234,8 +234,11 @@
ftl_last = POINTER
};
+ // TouchInputMapper will configure devices with INPUT_PROP_DIRECT as
+ // DeviceType::TOUCH_SCREEN, and will otherwise use DeviceType::POINTER by default.
+ // This can be overridden by IDC files, using the `touch.deviceType` config.
DeviceType deviceType;
- bool hasAssociatedDisplay;
+ bool hasAssociatedDisplay = false;
bool associatedDisplayIsExternal;
bool orientationAware;
@@ -776,8 +779,9 @@
nsecs_t readTime);
const BitSet32& findActiveIdBits(const CookedPointerData& cookedPointerData);
void cookPointerData();
- [[nodiscard]] std::list<NotifyArgs> abortTouches(nsecs_t when, nsecs_t readTime,
- uint32_t policyFlags);
+ [[nodiscard]] std::list<NotifyArgs> abortTouches(
+ nsecs_t when, nsecs_t readTime, uint32_t policyFlags,
+ std::optional<ui::LogicalDisplayId> gestureDisplayId);
[[nodiscard]] std::list<NotifyArgs> dispatchPointerUsage(nsecs_t when, nsecs_t readTime,
uint32_t policyFlags,
@@ -833,15 +837,18 @@
// method will take care of setting the index and transmuting the action to DOWN or UP
// it is the first / last pointer to go down / up.
[[nodiscard]] NotifyMotionArgs dispatchMotion(
- nsecs_t when, nsecs_t readTime, uint32_t policyFlags, uint32_t source, int32_t action,
- int32_t actionButton, int32_t flags, int32_t metaState, int32_t buttonState,
- int32_t edgeFlags, const PropertiesArray& properties, const CoordsArray& coords,
+ nsecs_t when, nsecs_t readTime, uint32_t policyFlags, uint32_t source,
+ ui::LogicalDisplayId displayId, int32_t action, int32_t actionButton, int32_t flags,
+ int32_t metaState, int32_t buttonState, int32_t edgeFlags,
+ const PropertiesArray& properties, const CoordsArray& coords,
const IdToIndexArray& idToIndex, BitSet32 idBits, int32_t changedId, float xPrecision,
- float yPrecision, nsecs_t downTime, MotionClassification classification);
+ float yPrecision, nsecs_t downTime, MotionClassification classification) const;
// Returns if this touch device is a touch screen with an associated display.
bool isTouchScreen();
+ ui::LogicalDisplayId resolveDisplayId() const;
+
bool isPointInsidePhysicalFrame(int32_t x, int32_t y) const;
const VirtualKey* findVirtualKeyHit(int32_t x, int32_t y);
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
index 9a36bfb..c982dab 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
@@ -40,6 +40,7 @@
#include "TouchCursorInputMapperCommon.h"
#include "TouchpadInputMapper.h"
#include "gestures/HardwareProperties.h"
+#include "gestures/Logging.h"
#include "gestures/TimerProvider.h"
#include "ui/Rotation.h"
@@ -49,19 +50,12 @@
namespace {
-/**
- * Log details of each gesture output by the gestures library.
- * Enable this via "adb shell setprop log.tag.TouchpadInputMapperGestures DEBUG" (requires
- * restarting the shell)
- */
-const bool DEBUG_TOUCHPAD_GESTURES =
- __android_log_is_loggable(ANDROID_LOG_DEBUG, "TouchpadInputMapperGestures",
- ANDROID_LOG_INFO);
-
std::vector<double> createAccelerationCurveForSensitivity(int32_t sensitivity,
+ bool accelerationEnabled,
size_t propertySize) {
- std::vector<AccelerationCurveSegment> segments =
- createAccelerationCurveForPointerSensitivity(sensitivity);
+ std::vector<AccelerationCurveSegment> segments = accelerationEnabled
+ ? createAccelerationCurveForPointerSensitivity(sensitivity)
+ : createFlatAccelerationCurve(sensitivity);
LOG_ALWAYS_FATAL_IF(propertySize < 4 * segments.size());
std::vector<double> output(propertySize, 0);
@@ -351,18 +345,21 @@
bumpGeneration();
}
+ std::list<NotifyArgs> out;
if (!changes.any() || changes.test(InputReaderConfiguration::Change::TOUCHPAD_SETTINGS)) {
mPropertyProvider.getProperty("Use Custom Touchpad Pointer Accel Curve")
.setBoolValues({true});
GesturesProp accelCurveProp = mPropertyProvider.getProperty("Pointer Accel Curve");
accelCurveProp.setRealValues(
createAccelerationCurveForSensitivity(config.touchpadPointerSpeed,
+ config.touchpadAccelerationEnabled,
accelCurveProp.getCount()));
mPropertyProvider.getProperty("Use Custom Touchpad Scroll Accel Curve")
.setBoolValues({true});
GesturesProp scrollCurveProp = mPropertyProvider.getProperty("Scroll Accel Curve");
scrollCurveProp.setRealValues(
createAccelerationCurveForSensitivity(config.touchpadPointerSpeed,
+ config.touchpadAccelerationEnabled,
scrollCurveProp.getCount()));
mPropertyProvider.getProperty("Scroll X Out Scale").setRealValues({1.0});
mPropertyProvider.getProperty("Scroll Y Out Scale").setRealValues({1.0});
@@ -375,8 +372,11 @@
mPropertyProvider.getProperty("Button Right Click Zone Enable")
.setBoolValues({config.touchpadRightClickZoneEnabled});
mTouchpadHardwareStateNotificationsEnabled = config.shouldNotifyTouchpadHardwareState;
+ mGestureConverter.setThreeFingerTapShortcutEnabled(
+ config.touchpadThreeFingerTapShortcutEnabled);
+ out += mGestureConverter.setEnableSystemGestures(when,
+ config.touchpadSystemGesturesEnabled);
}
- std::list<NotifyArgs> out;
if ((!changes.any() && config.pointerCaptureRequest.isEnable()) ||
changes.test(InputReaderConfiguration::Change::POINTER_CAPTURE)) {
mPointerCaptured = config.pointerCaptureRequest.isEnable();
@@ -462,7 +462,7 @@
std::list<NotifyArgs> TouchpadInputMapper::sendHardwareState(nsecs_t when, nsecs_t readTime,
SelfContainedHardwareState schs) {
- ALOGD_IF(DEBUG_TOUCHPAD_GESTURES, "New hardware state: %s", schs.state.String().c_str());
+ ALOGD_IF(debugTouchpadGestures(), "New hardware state: %s", schs.state.String().c_str());
mGestureInterpreter->PushHardwareState(&schs.state);
return processGestures(when, readTime);
}
@@ -473,7 +473,7 @@
}
void TouchpadInputMapper::consumeGesture(const Gesture* gesture) {
- ALOGD_IF(DEBUG_TOUCHPAD_GESTURES, "Gesture ready: %s", gesture->String().c_str());
+ ALOGD_IF(debugTouchpadGestures(), "Gesture ready: %s", gesture->String().c_str());
if (mResettingInterpreter) {
// We already handle tidying up fake fingers etc. in GestureConverter::reset, so we should
// ignore any gestures produced from the interpreter while we're resetting it.
@@ -498,7 +498,7 @@
return out;
}
-std::optional<ui::LogicalDisplayId> TouchpadInputMapper::getAssociatedDisplayId() {
+std::optional<ui::LogicalDisplayId> TouchpadInputMapper::getAssociatedDisplayId() const {
return mDisplayId;
}
@@ -506,4 +506,12 @@
return mHardwareProperties;
}
+std::optional<GesturesProp> TouchpadInputMapper::getGesturePropertyForTesting(
+ const std::string& name) {
+ if (!mPropertyProvider.hasProperty(name)) {
+ return std::nullopt;
+ }
+ return mPropertyProvider.getProperty(name);
+}
+
} // namespace android
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.h b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
index a2c4be9..9f53a7b 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
@@ -66,10 +66,12 @@
using MetricsIdentifier = std::tuple<uint16_t /*busId*/, uint16_t /*vendorId*/,
uint16_t /*productId*/, uint16_t /*version*/>;
- std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() override;
+ std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() const override;
std::optional<HardwareProperties> getTouchpadHardwareProperties() override;
+ std::optional<GesturesProp> getGesturePropertyForTesting(const std::string& name);
+
private:
void resetGestureInterpreter(nsecs_t when);
explicit TouchpadInputMapper(InputDeviceContext& deviceContext,
diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
index a3a48ef..264ef6f 100644
--- a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
@@ -43,10 +43,8 @@
std::list<NotifyArgs> VibratorInputMapper::vibrate(const VibrationSequence& sequence,
ssize_t repeat, int32_t token) {
- if (DEBUG_VIBRATOR) {
- ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%zd, token=%d", getDeviceId(),
- sequence.toString().c_str(), repeat, token);
- }
+ ALOGD_IF(DEBUG_VIBRATOR, "vibrate: deviceId=%d, pattern=[%s], repeat=%zd, token=%d",
+ getDeviceId(), sequence.toString().c_str(), repeat, token);
std::list<NotifyArgs> out;
mVibrating = true;
@@ -63,9 +61,7 @@
}
std::list<NotifyArgs> VibratorInputMapper::cancelVibrate(int32_t token) {
- if (DEBUG_VIBRATOR) {
- ALOGD("cancelVibrate: deviceId=%d, token=%d", getDeviceId(), token);
- }
+ ALOGD_IF(DEBUG_VIBRATOR, "cancelVibrate: deviceId=%d, token=%d", getDeviceId(), token);
std::list<NotifyArgs> out;
if (mVibrating && mToken == token) {
@@ -95,9 +91,7 @@
}
std::list<NotifyArgs> VibratorInputMapper::nextStep() {
- if (DEBUG_VIBRATOR) {
- ALOGD("nextStep: index=%d, vibrate deviceId=%d", (int)mIndex, getDeviceId());
- }
+ ALOGD_IF(DEBUG_VIBRATOR, "nextStep: index=%d, vibrate deviceId=%d", (int)mIndex, getDeviceId());
std::list<NotifyArgs> out;
mIndex += 1;
if (size_t(mIndex) >= mSequence.pattern.size()) {
@@ -111,16 +105,11 @@
const VibrationElement& element = mSequence.pattern[mIndex];
if (element.isOn()) {
- if (DEBUG_VIBRATOR) {
- std::string description = element.toString();
- ALOGD("nextStep: sending vibrate deviceId=%d, element=%s", getDeviceId(),
- description.c_str());
- }
+ ALOGD_IF(DEBUG_VIBRATOR, "nextStep: sending vibrate deviceId=%d, element=%s", getDeviceId(),
+ element.toString().c_str());
getDeviceContext().vibrate(element);
} else {
- if (DEBUG_VIBRATOR) {
- ALOGD("nextStep: sending cancel vibrate deviceId=%d", getDeviceId());
- }
+ ALOGD_IF(DEBUG_VIBRATOR, "nextStep: sending cancel vibrate deviceId=%d", getDeviceId());
getDeviceContext().cancelVibrate();
}
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -128,17 +117,13 @@
std::chrono::duration_cast<std::chrono::nanoseconds>(element.duration);
mNextStepTime = now + duration.count();
getContext()->requestTimeoutAtTime(mNextStepTime);
- if (DEBUG_VIBRATOR) {
- ALOGD("nextStep: scheduled timeout in %lldms", element.duration.count());
- }
+ ALOGD_IF(DEBUG_VIBRATOR, "nextStep: scheduled timeout in %lldms", element.duration.count());
return out;
}
NotifyVibratorStateArgs VibratorInputMapper::stopVibrating() {
mVibrating = false;
- if (DEBUG_VIBRATOR) {
- ALOGD("stopVibrating: sending cancel vibrate deviceId=%d", getDeviceId());
- }
+ ALOGD_IF(DEBUG_VIBRATOR, "stopVibrating: sending cancel vibrate deviceId=%d", getDeviceId());
getDeviceContext().cancelVibrate();
// Request InputReader to notify InputManagerService for vibration complete.
diff --git a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
index da2c683..480e276 100644
--- a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
+++ b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
@@ -14,11 +14,15 @@
* limitations under the License.
*/
+#include "../Macros.h"
+
#include "gestures/GestureConverter.h"
+#include <ios>
#include <optional>
#include <sstream>
+#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <com_android_input_flags.h>
#include <ftl/enum.h>
@@ -81,7 +85,6 @@
const InputDeviceContext& deviceContext, int32_t deviceId)
: mDeviceId(deviceId),
mReaderContext(readerContext),
- mEnableFlingStop(input_flags::enable_touchpad_fling_stop()),
mEnableNoFocusChange(input_flags::enable_touchpad_no_focus_change()),
// We can safely assume that ABS_MT_POSITION_X and _Y axes will be available, as EventHub
// won't classify a device as a touchpad if they're not present.
@@ -99,6 +102,8 @@
out << "Current classification: " << ftl::enum_string(mCurrentClassification) << "\n";
out << "Is hovering: " << mIsHovering << "\n";
out << "Enable Tap Timestamp: " << mWhenToEnableTapToClick << "\n";
+ out << "Three finger tap shortcut enabled: "
+ << (mThreeFingerTapShortcutEnabled ? "enabled" : "disabled") << "\n";
return out.str();
}
@@ -130,6 +135,15 @@
return out;
}
+std::list<NotifyArgs> GestureConverter::setEnableSystemGestures(nsecs_t when, bool enable) {
+ std::list<NotifyArgs> out;
+ if (!enable && mCurrentClassification == MotionClassification::MULTI_FINGER_SWIPE) {
+ out += handleMultiFingerSwipeLift(when, when);
+ }
+ mEnableSystemGestures = enable;
+ return out;
+}
+
void GestureConverter::populateMotionRanges(InputDeviceInfo& info) const {
info.addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, SOURCE, 0.0f, 1.0f, 0, 0, 0);
@@ -240,6 +254,18 @@
const Gesture& gesture) {
std::list<NotifyArgs> out = {};
+ if (mCurrentClassification != MotionClassification::NONE) {
+ // Handling button changes during an ongoing gesture would be tricky, as we'd have to avoid
+ // sending duplicate DOWN events or premature UP events (e.g. if the gesture ended but the
+ // button was still down). It would also make handling touchpad events more difficult for
+ // apps, which would have to handle cases where e.g. a scroll gesture ends (and therefore
+ // the event lose the TWO_FINGER_SWIPE classification) but there isn't an UP because the
+ // button's still down. It's unclear how one should even handle button changes during most
+ // gestures, and they're probably accidental anyway. So, instead, just ignore them.
+ LOG(INFO) << "Ignoring button change because a gesture is ongoing.";
+ return out;
+ }
+
PointerCoords coords;
coords.clear();
coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0);
@@ -261,6 +287,14 @@
}
const uint32_t buttonsPressed = gesture.details.buttons.down;
+ const uint32_t buttonsReleased = gesture.details.buttons.up;
+
+ if (mThreeFingerTapShortcutEnabled && gesture.details.buttons.is_tap &&
+ buttonsPressed == GESTURES_BUTTON_MIDDLE && buttonsReleased == GESTURES_BUTTON_MIDDLE) {
+ mReaderContext.getPolicy()->notifyTouchpadThreeFingerTap();
+ return out;
+ }
+
bool pointerDown = isPointerDown(mButtonState) ||
buttonsPressed &
(GESTURES_BUTTON_LEFT | GESTURES_BUTTON_MIDDLE | GESTURES_BUTTON_RIGHT);
@@ -291,10 +325,18 @@
// changes: a set of buttons going down, followed by a set of buttons going up.
mButtonState = newButtonState;
- const uint32_t buttonsReleased = gesture.details.buttons.up;
for (uint32_t button = 1; button <= GESTURES_BUTTON_FORWARD; button <<= 1) {
if (buttonsReleased & button) {
uint32_t actionButton = gesturesButtonToMotionEventButton(button);
+ if (!(newButtonState & actionButton)) {
+ // We must have received the ButtonsChange gesture that put this button down during
+ // another gesture, and therefore dropped the BUTTON_PRESS action for it, or
+ // released the button when another gesture began during its press. Drop the
+ // BUTTON_RELEASE too to keep the stream consistent.
+ LOG(INFO) << "Dropping release event for button 0x" << std::hex << actionButton
+ << " as it wasn't in the button state.";
+ continue;
+ }
newButtonState &= ~actionButton;
out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
actionButton, newButtonState, /* pointerCount= */ 1,
@@ -345,7 +387,7 @@
std::list<NotifyArgs> out;
PointerCoords& coords = mFakeFingerCoords[0];
if (mCurrentClassification != MotionClassification::TWO_FINGER_SWIPE) {
- out += exitHover(when, readTime);
+ out += prepareForFakeFingerGesture(when, readTime);
mCurrentClassification = MotionClassification::TWO_FINGER_SWIPE;
coords.clear();
@@ -388,7 +430,7 @@
break;
case GESTURES_FLING_TAP_DOWN:
if (mCurrentClassification == MotionClassification::NONE) {
- if (mEnableFlingStop && mFlingMayBeInProgress) {
+ if (mFlingMayBeInProgress) {
// The user has just touched the pad again after ending a two-finger scroll
// motion, which might have started a fling. We want to stop the fling, but
// unfortunately there's currently no API for doing so. Instead, send and
@@ -404,7 +446,7 @@
std::list<NotifyArgs> out;
mDownTime = when;
mCurrentClassification = MotionClassification::TWO_FINGER_SWIPE;
- out += exitHover(when, readTime);
+ out += prepareForFakeFingerGesture(when, readTime);
out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_DOWN,
/*actionButton=*/0, /*buttonState=*/0,
/*pointerCount=*/1, &coords));
@@ -452,6 +494,9 @@
uint32_t fingerCount,
float dx, float dy) {
std::list<NotifyArgs> out = {};
+ if (!mEnableSystemGestures) {
+ return out;
+ }
if (mCurrentClassification != MotionClassification::MULTI_FINGER_SWIPE) {
// If the user changes the number of fingers mid-way through a swipe (e.g. they start with
@@ -459,7 +504,7 @@
// separate swipes with an appropriate lift event between them, so we don't have to worry
// about the finger count changing mid-swipe.
- out += exitHover(when, readTime);
+ out += prepareForFakeFingerGesture(when, readTime);
mCurrentClassification = MotionClassification::MULTI_FINGER_SWIPE;
@@ -547,9 +592,7 @@
LOG_ALWAYS_FATAL_IF(gesture.details.pinch.zoom_state != GESTURES_ZOOM_START,
"First pinch gesture does not have the START zoom state (%d instead).",
gesture.details.pinch.zoom_state);
- std::list<NotifyArgs> out;
-
- out += exitHover(when, readTime);
+ std::list<NotifyArgs> out = prepareForFakeFingerGesture(when, readTime);
mCurrentClassification = MotionClassification::PINCH;
mPinchFingerSeparation = INITIAL_PINCH_SEPARATION_PX;
@@ -624,6 +667,16 @@
}
}
+std::list<NotifyArgs> GestureConverter::prepareForFakeFingerGesture(nsecs_t when,
+ nsecs_t readTime) {
+ std::list<NotifyArgs> out;
+ if (isPointerDown(mButtonState)) {
+ out += releaseAllButtons(when, readTime);
+ }
+ out += exitHover(when, readTime);
+ return out;
+}
+
NotifyMotionArgs GestureConverter::makeHoverEvent(nsecs_t when, nsecs_t readTime, int32_t action) {
PointerCoords coords;
coords.clear();
diff --git a/services/inputflinger/reader/mapper/gestures/GestureConverter.h b/services/inputflinger/reader/mapper/gestures/GestureConverter.h
index c9a35c1..ae85e3a 100644
--- a/services/inputflinger/reader/mapper/gestures/GestureConverter.h
+++ b/services/inputflinger/reader/mapper/gestures/GestureConverter.h
@@ -55,6 +55,12 @@
void setBoundsInLogicalDisplay(FloatRect bounds) { mBoundsInLogicalDisplay = bounds; }
+ void setThreeFingerTapShortcutEnabled(bool enabled) {
+ mThreeFingerTapShortcutEnabled = enabled;
+ }
+
+ [[nodiscard]] std::list<NotifyArgs> setEnableSystemGestures(nsecs_t when, bool enable);
+
void populateMotionRanges(InputDeviceInfo& info) const;
[[nodiscard]] std::list<NotifyArgs> handleGesture(nsecs_t when, nsecs_t readTime,
@@ -86,6 +92,8 @@
[[nodiscard]] std::list<NotifyArgs> enterHover(nsecs_t when, nsecs_t readTime);
[[nodiscard]] std::list<NotifyArgs> exitHover(nsecs_t when, nsecs_t readTime);
+ [[nodiscard]] std::list<NotifyArgs> prepareForFakeFingerGesture(nsecs_t when, nsecs_t readTime);
+
NotifyMotionArgs makeHoverEvent(nsecs_t when, nsecs_t readTime, int32_t action);
NotifyMotionArgs makeMotionArgs(nsecs_t when, nsecs_t readTime, int32_t action,
@@ -98,8 +106,10 @@
const int32_t mDeviceId;
InputReaderContext& mReaderContext;
- const bool mEnableFlingStop;
const bool mEnableNoFocusChange;
+ bool mEnableSystemGestures{true};
+
+ bool mThreeFingerTapShortcutEnabled{false};
std::optional<ui::LogicalDisplayId> mDisplayId;
FloatRect mBoundsInLogicalDisplay{};
diff --git a/services/inputflinger/reader/mapper/gestures/GesturesLogging.cpp b/services/inputflinger/reader/mapper/gestures/GesturesLogcatAdapter.cpp
similarity index 72%
rename from services/inputflinger/reader/mapper/gestures/GesturesLogging.cpp
rename to services/inputflinger/reader/mapper/gestures/GesturesLogcatAdapter.cpp
index 26028c5..51905f9 100644
--- a/services/inputflinger/reader/mapper/gestures/GesturesLogging.cpp
+++ b/services/inputflinger/reader/mapper/gestures/GesturesLogcatAdapter.cpp
@@ -22,29 +22,17 @@
#include <log/log.h>
+#include "Logging.h"
#include "include/gestures.h"
extern "C" {
-namespace {
-
-/**
- * Log details of each gesture output by the gestures library.
- * Enable this via "adb shell setprop log.tag.TouchpadInputMapperGestures DEBUG" (requires
- * restarting the shell)
- */
-const bool DEBUG_TOUCHPAD_GESTURES =
- __android_log_is_loggable(ANDROID_LOG_DEBUG, "TouchpadInputMapperGestures",
- ANDROID_LOG_INFO);
-
-} // namespace
-
void gestures_log(int verb, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
if (verb == GESTURES_LOG_ERROR) {
LOG_PRI_VA(ANDROID_LOG_ERROR, LOG_TAG, fmt, args);
- } else if (DEBUG_TOUCHPAD_GESTURES) {
+ } else if (android::debugTouchpadGestures()) {
if (verb == GESTURES_LOG_INFO) {
LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, fmt, args);
} else {
diff --git a/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.cpp b/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.cpp
index 6885adb..3e62f36 100644
--- a/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.cpp
+++ b/services/inputflinger/reader/mapper/gestures/HardwareStateConverter.cpp
@@ -25,12 +25,8 @@
#include <com_android_input_flags.h>
#include <linux/input-event-codes.h>
-namespace input_flags = com::android::input::flags;
-
namespace android {
-const bool REPORT_PALMS_TO_GESTURES_LIBRARY = input_flags::report_palms_to_gestures_library();
-
HardwareStateConverter::HardwareStateConverter(const InputDeviceContext& deviceContext,
MultiTouchMotionAccumulator& motionAccumulator)
: mDeviceContext(deviceContext),
@@ -81,18 +77,11 @@
}
schs.fingers.clear();
- size_t numPalms = 0;
for (size_t i = 0; i < mMotionAccumulator.getSlotCount(); i++) {
MultiTouchMotionAccumulator::Slot slot = mMotionAccumulator.getSlot(i);
if (!slot.isInUse()) {
continue;
}
- // Some touchpads continue to report contacts even after they've identified them as palms.
- // We want to exclude these contacts from the HardwareStates.
- if (!REPORT_PALMS_TO_GESTURES_LIBRARY && slot.getToolType() == ToolType::PALM) {
- numPalms++;
- continue;
- }
FingerState& fingerState = schs.fingers.emplace_back();
fingerState = {};
@@ -105,15 +94,13 @@
fingerState.position_x = slot.getX();
fingerState.position_y = slot.getY();
fingerState.tracking_id = slot.getTrackingId();
- if (REPORT_PALMS_TO_GESTURES_LIBRARY) {
- fingerState.tool_type = slot.getToolType() == ToolType::PALM
- ? FingerState::ToolType::kPalm
- : FingerState::ToolType::kFinger;
- }
+ fingerState.tool_type = slot.getToolType() == ToolType::PALM
+ ? FingerState::ToolType::kPalm
+ : FingerState::ToolType::kFinger;
}
schs.state.fingers = schs.fingers.data();
schs.state.finger_cnt = schs.fingers.size();
- schs.state.touch_cnt = mTouchButtonAccumulator.getTouchCount() - numPalms;
+ schs.state.touch_cnt = mTouchButtonAccumulator.getTouchCount();
return schs;
}
diff --git a/services/inputflinger/reader/mapper/gestures/Logging.cpp b/services/inputflinger/reader/mapper/gestures/Logging.cpp
new file mode 100644
index 0000000..b9b97c3
--- /dev/null
+++ b/services/inputflinger/reader/mapper/gestures/Logging.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2025 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 "Logging.h"
+
+#include <android-base/properties.h>
+#include <log/log.h>
+
+namespace {
+
+const bool IS_DEBUGGABLE_BUILD =
+#if defined(__ANDROID__)
+ android::base::GetBoolProperty("ro.debuggable", false);
+#else
+ true;
+#endif
+
+} // namespace
+
+namespace android {
+
+bool debugTouchpadGestures() {
+ if (!IS_DEBUGGABLE_BUILD) {
+ static const bool DEBUG_RAW_EVENTS =
+ __android_log_is_loggable(ANDROID_LOG_DEBUG, "TouchpadInputMapperGestures",
+ ANDROID_LOG_INFO);
+ return DEBUG_RAW_EVENTS;
+ }
+ return __android_log_is_loggable(ANDROID_LOG_DEBUG, "TouchpadInputMapperGestures",
+ ANDROID_LOG_INFO);
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/inputflinger/reader/mapper/gestures/Logging.h b/services/inputflinger/reader/mapper/gestures/Logging.h
new file mode 100644
index 0000000..db59fb3
--- /dev/null
+++ b/services/inputflinger/reader/mapper/gestures/Logging.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2025 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
+
+namespace android {
+
+/**
+ * Log details of touchpad gesture library input, output, and processing.
+ * Enable this via "adb shell setprop log.tag.TouchpadInputMapperGestures DEBUG".
+ * This requires a restart on non-debuggable (e.g. user) builds, but should take effect immediately
+ * on debuggable builds (e.g. userdebug).
+ */
+bool debugTouchpadGestures();
+
+} // namespace android
\ No newline at end of file
diff --git a/services/inputflinger/rust/Android.bp b/services/inputflinger/rust/Android.bp
index 5b7cc2d..78674e5 100644
--- a/services/inputflinger/rust/Android.bp
+++ b/services/inputflinger/rust/Android.bp
@@ -40,14 +40,14 @@
crate_name: "inputflinger",
srcs: ["lib.rs"],
rustlibs: [
- "libcxx",
- "com.android.server.inputflinger-rust",
"android.hardware.input.common-V1-rust",
+ "com.android.server.inputflinger-rust",
"libbinder_rs",
+ "libcxx",
+ "libinput_rust",
"liblog_rust",
"liblogger",
"libnix",
- "libinput_rust",
],
host_supported: true,
}
diff --git a/services/inputflinger/rust/sticky_keys_filter.rs b/services/inputflinger/rust/sticky_keys_filter.rs
index 7a1d0ec..3c7f432 100644
--- a/services/inputflinger/rust/sticky_keys_filter.rs
+++ b/services/inputflinger/rust/sticky_keys_filter.rs
@@ -47,6 +47,7 @@
next: Box<dyn Filter + Send + Sync>,
listener: ModifierStateListener,
data: Data,
+ down_key_map: HashMap<i32, HashSet<i32>>,
}
#[derive(Default)]
@@ -69,15 +70,34 @@
next: Box<dyn Filter + Send + Sync>,
listener: ModifierStateListener,
) -> StickyKeysFilter {
- Self { next, listener, data: Default::default() }
+ Self { next, listener, data: Default::default(), down_key_map: HashMap::new() }
}
}
impl Filter for StickyKeysFilter {
fn notify_key(&mut self, event: &KeyEvent) {
+ let down = event.action == KeyEventAction::DOWN;
let up = event.action == KeyEventAction::UP;
let mut modifier_state = self.data.modifier_state;
let mut locked_modifier_state = self.data.locked_modifier_state;
+ if down {
+ let down_keys = self.down_key_map.entry(event.deviceId).or_default();
+ down_keys.insert(event.keyCode);
+ } else {
+ if !self.down_key_map.contains_key(&event.deviceId) {
+ self.next.notify_key(event);
+ return;
+ }
+ let down_keys = self.down_key_map.get_mut(&event.deviceId).unwrap();
+ if !down_keys.contains(&event.keyCode) {
+ self.next.notify_key(event);
+ return;
+ }
+ down_keys.remove(&event.keyCode);
+ if down_keys.is_empty() {
+ self.down_key_map.remove(&event.deviceId);
+ }
+ }
if !is_ephemeral_modifier_key(event.keyCode) {
// If non-ephemeral modifier key (i.e. non-modifier keys + toggle modifier keys like
// CAPS_LOCK, NUM_LOCK etc.), don't block key and pass in the sticky modifier state with
@@ -130,6 +150,7 @@
self.data.locked_modifier_state = ModifierState::None;
self.listener.modifier_state_changed(ModifierState::None, ModifierState::None);
}
+ self.down_key_map.retain(|key, _| device_infos.iter().any(|x| *key == x.deviceId));
self.next.notify_devices_changed(device_infos);
}
@@ -166,6 +187,7 @@
result += &format!("\tmodifier_state = {:?}\n", self.data.modifier_state);
result += &format!("\tlocked_modifier_state = {:?}\n", self.data.locked_modifier_state);
result += &format!("\tcontributing_devices = {:?}\n", self.data.contributing_devices);
+ result += &format!("\tdown_key_map = {:?}\n", self.down_key_map);
self.next.dump(dump_str + &result)
}
}
@@ -322,6 +344,31 @@
}
#[test]
+ fn test_notify_key_passes_ephemeral_modifier_keys_if_only_key_up_occurs() {
+ let test_filter = TestFilter::new();
+ let test_callbacks = TestCallbacks::new();
+ let mut sticky_keys_filter = setup_filter(
+ Box::new(test_filter.clone()),
+ Arc::new(RwLock::new(Strong::new(Box::new(test_callbacks.clone())))),
+ );
+ let key_codes = &[
+ KEYCODE_ALT_LEFT,
+ KEYCODE_ALT_RIGHT,
+ KEYCODE_CTRL_LEFT,
+ KEYCODE_CTRL_RIGHT,
+ KEYCODE_SHIFT_LEFT,
+ KEYCODE_SHIFT_RIGHT,
+ KEYCODE_META_LEFT,
+ KEYCODE_META_RIGHT,
+ ];
+ for key_code in key_codes.iter() {
+ let event = KeyEvent { keyCode: *key_code, ..BASE_KEY_UP };
+ sticky_keys_filter.notify_key(&event);
+ assert_eq!(test_filter.last_event().unwrap(), event);
+ }
+ }
+
+ #[test]
fn test_notify_key_passes_non_ephemeral_modifier_keys() {
let test_filter = TestFilter::new();
let test_callbacks = TestCallbacks::new();
@@ -437,6 +484,26 @@
}
#[test]
+ fn test_modifier_state_unchanged_on_non_modifier_key_up_without_down() {
+ let test_filter = TestFilter::new();
+ let test_callbacks = TestCallbacks::new();
+ let mut sticky_keys_filter = setup_filter(
+ Box::new(test_filter.clone()),
+ Arc::new(RwLock::new(Strong::new(Box::new(test_callbacks.clone())))),
+ );
+ sticky_keys_filter.notify_key(&KeyEvent { keyCode: KEYCODE_CTRL_LEFT, ..BASE_KEY_DOWN });
+ sticky_keys_filter.notify_key(&KeyEvent { keyCode: KEYCODE_CTRL_LEFT, ..BASE_KEY_UP });
+
+ sticky_keys_filter.notify_key(&KeyEvent { keyCode: KEY_A, ..BASE_KEY_UP });
+
+ assert_eq!(
+ test_callbacks.get_last_modifier_state(),
+ ModifierState::CtrlLeftOn | ModifierState::CtrlOn
+ );
+ assert_eq!(test_callbacks.get_last_locked_modifier_state(), ModifierState::None);
+ }
+
+ #[test]
fn test_locked_modifier_state_not_cleared_on_non_modifier_key_press() {
let test_filter = TestFilter::new();
let test_callbacks = TestCallbacks::new();
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index 744cf4a..18d47f6 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -40,14 +40,15 @@
// defaults rather than including them as shared or static libraries. By doing so, the tests
// will always run against the compiled version of the inputflinger code rather than the
// version on the device.
+ "libinputdispatcher_defaults",
"libinputflinger_base_defaults",
+ "libinputflinger_defaults",
"libinputreader_defaults",
"libinputreporter_defaults",
- "libinputdispatcher_defaults",
- "libinputflinger_defaults",
],
srcs: [
":inputdispatcher_common_test_sources",
+ "AndroidInputEventProtoConverter_test.cpp",
"AnrTracker_test.cpp",
"CapturedTouchpadEventConverter_test.cpp",
"CursorInputMapper_test.cpp",
@@ -62,33 +63,34 @@
"HardwareStateConverter_test.cpp",
"InputDeviceMetricsCollector_test.cpp",
"InputDeviceMetricsSource_test.cpp",
- "InputMapperTest.cpp",
- "InputProcessor_test.cpp",
- "InputProcessorConverter_test.cpp",
"InputDispatcher_test.cpp",
+ "InputMapperTest.cpp",
+ "InputProcessorConverter_test.cpp",
+ "InputProcessor_test.cpp",
"InputReader_test.cpp",
"InputTraceSession.cpp",
"InputTracingTest.cpp",
"InstrumentedInputReader.cpp",
"JoystickInputMapper_test.cpp",
+ "KeyboardInputMapper_test.cpp",
"LatencyTracker_test.cpp",
+ "MultiTouchInputMapper_test.cpp",
"MultiTouchMotionAccumulator_test.cpp",
"NotifyArgs_test.cpp",
"PointerChoreographer_test.cpp",
"PreferStylusOverTouch_test.cpp",
"PropertyProvider_test.cpp",
"RotaryEncoderInputMapper_test.cpp",
+ "SensorInputMapper_test.cpp",
"SlopController_test.cpp",
"SwitchInputMapper_test.cpp",
"SyncQueue_test.cpp",
- "TimerProvider_test.cpp",
"TestInputListener.cpp",
+ "TimerProvider_test.cpp",
"TouchpadInputMapper_test.cpp",
- "VibratorInputMapper_test.cpp",
- "MultiTouchInputMapper_test.cpp",
- "KeyboardInputMapper_test.cpp",
"UinputDevice.cpp",
"UnwantedInteractionBlocker_test.cpp",
+ "VibratorInputMapper_test.cpp",
],
aidl: {
include_dirs: [
@@ -108,7 +110,14 @@
undefined: true,
all_undefined: true,
diag: {
+ cfi: true,
+ integer_overflow: true,
+ memtag_heap: true,
undefined: true,
+ misc_undefined: [
+ "all",
+ "bounds",
+ ],
},
},
static_libs: [
@@ -120,8 +129,8 @@
unit_test: true,
},
test_suites: [
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
native_coverage: false,
}
diff --git a/services/inputflinger/tests/AndroidInputEventProtoConverter_test.cpp b/services/inputflinger/tests/AndroidInputEventProtoConverter_test.cpp
new file mode 100644
index 0000000..1fd6cee
--- /dev/null
+++ b/services/inputflinger/tests/AndroidInputEventProtoConverter_test.cpp
@@ -0,0 +1,586 @@
+/*
+ * Copyright 2025 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 "../dispatcher/trace/AndroidInputEventProtoConverter.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+namespace android::inputdispatcher::trace {
+
+namespace {
+
+using testing::Return, testing::_;
+
+class MockProtoAxisValue {
+public:
+ MOCK_METHOD(void, set_axis, (int32_t));
+ MOCK_METHOD(void, set_value, (float));
+};
+
+class MockProtoPointer {
+public:
+ MOCK_METHOD(void, set_pointer_id, (uint32_t));
+ MOCK_METHOD(void, set_tool_type, (int32_t));
+ MOCK_METHOD(MockProtoAxisValue*, add_axis_value, ());
+};
+
+class MockProtoMotion {
+public:
+ MOCK_METHOD(void, set_event_id, (uint32_t));
+ MOCK_METHOD(void, set_event_time_nanos, (int64_t));
+ MOCK_METHOD(void, set_down_time_nanos, (int64_t));
+ MOCK_METHOD(void, set_source, (uint32_t));
+ MOCK_METHOD(void, set_action, (int32_t));
+ MOCK_METHOD(void, set_device_id, (uint32_t));
+ MOCK_METHOD(void, set_display_id, (uint32_t));
+ MOCK_METHOD(void, set_classification, (int32_t));
+ MOCK_METHOD(void, set_flags, (uint32_t));
+ MOCK_METHOD(void, set_policy_flags, (uint32_t));
+ MOCK_METHOD(void, set_button_state, (uint32_t));
+ MOCK_METHOD(void, set_action_button, (uint32_t));
+ MOCK_METHOD(void, set_cursor_position_x, (float));
+ MOCK_METHOD(void, set_cursor_position_y, (float));
+ MOCK_METHOD(void, set_meta_state, (uint32_t));
+ MOCK_METHOD(void, set_precision_x, (float));
+ MOCK_METHOD(void, set_precision_y, (float));
+ MOCK_METHOD(MockProtoPointer*, add_pointer, ());
+};
+
+class MockProtoKey {
+public:
+ MOCK_METHOD(void, set_event_id, (uint32_t));
+ MOCK_METHOD(void, set_event_time_nanos, (int64_t));
+ MOCK_METHOD(void, set_down_time_nanos, (int64_t));
+ MOCK_METHOD(void, set_source, (uint32_t));
+ MOCK_METHOD(void, set_action, (int32_t));
+ MOCK_METHOD(void, set_device_id, (uint32_t));
+ MOCK_METHOD(void, set_display_id, (uint32_t));
+ MOCK_METHOD(void, set_repeat_count, (uint32_t));
+ MOCK_METHOD(void, set_flags, (uint32_t));
+ MOCK_METHOD(void, set_policy_flags, (uint32_t));
+ MOCK_METHOD(void, set_key_code, (uint32_t));
+ MOCK_METHOD(void, set_scan_code, (uint32_t));
+ MOCK_METHOD(void, set_meta_state, (uint32_t));
+};
+
+class MockProtoDispatchPointer {
+public:
+ MOCK_METHOD(void, set_pointer_id, (uint32_t));
+ MOCK_METHOD(void, set_x_in_display, (float));
+ MOCK_METHOD(void, set_y_in_display, (float));
+ MOCK_METHOD(MockProtoAxisValue*, add_axis_value_in_window, ());
+};
+
+class MockProtoDispatch {
+public:
+ MOCK_METHOD(void, set_event_id, (uint32_t));
+ MOCK_METHOD(void, set_vsync_id, (uint32_t));
+ MOCK_METHOD(void, set_window_id, (uint32_t));
+ MOCK_METHOD(void, set_resolved_flags, (uint32_t));
+ MOCK_METHOD(MockProtoDispatchPointer*, add_dispatched_pointer, ());
+};
+
+using TestProtoConverter =
+ AndroidInputEventProtoConverter<MockProtoMotion, MockProtoKey, MockProtoDispatch,
+ proto::AndroidInputEventConfig::Decoder>;
+
+TEST(AndroidInputEventProtoConverterTest, ToProtoMotionEvent) {
+ TracedMotionEvent event{};
+ event.id = 1;
+ event.eventTime = 2;
+ event.downTime = 3;
+ event.source = AINPUT_SOURCE_MOUSE;
+ event.action = AMOTION_EVENT_ACTION_BUTTON_PRESS;
+ event.deviceId = 4;
+ event.displayId = ui::LogicalDisplayId(5);
+ event.classification = MotionClassification::PINCH;
+ event.flags = 6;
+ event.policyFlags = 7;
+ event.buttonState = 8;
+ event.actionButton = 9;
+ event.xCursorPosition = 10.0f;
+ event.yCursorPosition = 11.0f;
+ event.metaState = 12;
+ event.xPrecision = 13.0f;
+ event.yPrecision = 14.0f;
+ event.pointerProperties.emplace_back(PointerProperties{
+ .id = 15,
+ .toolType = ToolType::MOUSE,
+ });
+ event.pointerProperties.emplace_back(PointerProperties{
+ .id = 16,
+ .toolType = ToolType::FINGER,
+ });
+ event.pointerCoords.emplace_back();
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, 17.0f);
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, 18.0f);
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 19.0f);
+ event.pointerCoords.emplace_back();
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, 20.0f);
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, 21.0f);
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 22.0f);
+
+ testing::StrictMock<MockProtoMotion> proto;
+ testing::StrictMock<MockProtoPointer> pointer1;
+ testing::StrictMock<MockProtoPointer> pointer2;
+ testing::StrictMock<MockProtoAxisValue> axisValue1;
+ testing::StrictMock<MockProtoAxisValue> axisValue2;
+ testing::StrictMock<MockProtoAxisValue> axisValue3;
+ testing::StrictMock<MockProtoAxisValue> axisValue4;
+ testing::StrictMock<MockProtoAxisValue> axisValue5;
+ testing::StrictMock<MockProtoAxisValue> axisValue6;
+
+ EXPECT_CALL(proto, set_event_id(1));
+ EXPECT_CALL(proto, set_event_time_nanos(2));
+ EXPECT_CALL(proto, set_down_time_nanos(3));
+ EXPECT_CALL(proto, set_source(AINPUT_SOURCE_MOUSE));
+ EXPECT_CALL(proto, set_action(AMOTION_EVENT_ACTION_BUTTON_PRESS));
+ EXPECT_CALL(proto, set_device_id(4));
+ EXPECT_CALL(proto, set_display_id(5));
+ EXPECT_CALL(proto, set_classification(AMOTION_EVENT_CLASSIFICATION_PINCH));
+ EXPECT_CALL(proto, set_flags(6));
+ EXPECT_CALL(proto, set_policy_flags(7));
+ EXPECT_CALL(proto, set_button_state(8));
+ EXPECT_CALL(proto, set_action_button(9));
+ EXPECT_CALL(proto, set_cursor_position_x(10.0f));
+ EXPECT_CALL(proto, set_cursor_position_y(11.0f));
+ EXPECT_CALL(proto, set_meta_state(12));
+ EXPECT_CALL(proto, set_precision_x(13.0f));
+ EXPECT_CALL(proto, set_precision_y(14.0f));
+
+ EXPECT_CALL(proto, add_pointer()).WillOnce(Return(&pointer1)).WillOnce(Return(&pointer2));
+
+ EXPECT_CALL(pointer1, set_pointer_id(15));
+ EXPECT_CALL(pointer1, set_tool_type(AMOTION_EVENT_TOOL_TYPE_MOUSE));
+ EXPECT_CALL(pointer1, add_axis_value())
+ .WillOnce(Return(&axisValue1))
+ .WillOnce(Return(&axisValue2))
+ .WillOnce(Return(&axisValue3));
+ EXPECT_CALL(axisValue1, set_axis(AMOTION_EVENT_AXIS_X));
+ EXPECT_CALL(axisValue1, set_value(17.0f));
+ EXPECT_CALL(axisValue2, set_axis(AMOTION_EVENT_AXIS_Y));
+ EXPECT_CALL(axisValue2, set_value(18.0f));
+ EXPECT_CALL(axisValue3, set_axis(AMOTION_EVENT_AXIS_PRESSURE));
+ EXPECT_CALL(axisValue3, set_value(19.0f));
+
+ EXPECT_CALL(pointer2, set_pointer_id(16));
+ EXPECT_CALL(pointer2, set_tool_type(AMOTION_EVENT_TOOL_TYPE_FINGER));
+ EXPECT_CALL(pointer2, add_axis_value())
+ .WillOnce(Return(&axisValue4))
+ .WillOnce(Return(&axisValue5))
+ .WillOnce(Return(&axisValue6));
+ EXPECT_CALL(axisValue4, set_axis(AMOTION_EVENT_AXIS_X));
+ EXPECT_CALL(axisValue4, set_value(20.0f));
+ EXPECT_CALL(axisValue5, set_axis(AMOTION_EVENT_AXIS_Y));
+ EXPECT_CALL(axisValue5, set_value(21.0f));
+ EXPECT_CALL(axisValue6, set_axis(AMOTION_EVENT_AXIS_PRESSURE));
+ EXPECT_CALL(axisValue6, set_value(22.0f));
+
+ TestProtoConverter::toProtoMotionEvent(event, proto, /*isRedacted=*/false);
+}
+
+TEST(AndroidInputEventProtoConverterTest, ToProtoMotionEvent_Redacted) {
+ TracedMotionEvent event{};
+ event.id = 1;
+ event.eventTime = 2;
+ event.downTime = 3;
+ event.source = AINPUT_SOURCE_MOUSE;
+ event.action = AMOTION_EVENT_ACTION_BUTTON_PRESS;
+ event.deviceId = 4;
+ event.displayId = ui::LogicalDisplayId(5);
+ event.classification = MotionClassification::PINCH;
+ event.flags = 6;
+ event.policyFlags = 7;
+ event.buttonState = 8;
+ event.actionButton = 9;
+ event.xCursorPosition = 10.0f;
+ event.yCursorPosition = 11.0f;
+ event.metaState = 12;
+ event.xPrecision = 13.0f;
+ event.yPrecision = 14.0f;
+ event.pointerProperties.emplace_back(PointerProperties{
+ .id = 15,
+ .toolType = ToolType::MOUSE,
+ });
+ event.pointerProperties.emplace_back(PointerProperties{
+ .id = 16,
+ .toolType = ToolType::FINGER,
+ });
+ event.pointerCoords.emplace_back();
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, 17.0f);
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, 18.0f);
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 19.0f);
+ event.pointerCoords.emplace_back();
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, 20.0f);
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, 21.0f);
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 22.0f);
+
+ testing::StrictMock<MockProtoMotion> proto;
+ testing::StrictMock<MockProtoPointer> pointer1;
+ testing::StrictMock<MockProtoPointer> pointer2;
+ testing::StrictMock<MockProtoAxisValue> axisValue1;
+ testing::StrictMock<MockProtoAxisValue> axisValue2;
+ testing::StrictMock<MockProtoAxisValue> axisValue3;
+ testing::StrictMock<MockProtoAxisValue> axisValue4;
+ testing::StrictMock<MockProtoAxisValue> axisValue5;
+ testing::StrictMock<MockProtoAxisValue> axisValue6;
+
+ EXPECT_CALL(proto, set_event_id(1));
+ EXPECT_CALL(proto, set_event_time_nanos(2));
+ EXPECT_CALL(proto, set_down_time_nanos(3));
+ EXPECT_CALL(proto, set_source(AINPUT_SOURCE_MOUSE));
+ EXPECT_CALL(proto, set_action(AMOTION_EVENT_ACTION_BUTTON_PRESS));
+ EXPECT_CALL(proto, set_device_id(4));
+ EXPECT_CALL(proto, set_display_id(5));
+ EXPECT_CALL(proto, set_classification(AMOTION_EVENT_CLASSIFICATION_PINCH));
+ EXPECT_CALL(proto, set_flags(6));
+ EXPECT_CALL(proto, set_policy_flags(7));
+ EXPECT_CALL(proto, set_button_state(8));
+ EXPECT_CALL(proto, set_action_button(9));
+
+ EXPECT_CALL(proto, add_pointer()).WillOnce(Return(&pointer1)).WillOnce(Return(&pointer2));
+
+ EXPECT_CALL(pointer1, set_pointer_id(15));
+ EXPECT_CALL(pointer1, set_tool_type(AMOTION_EVENT_TOOL_TYPE_MOUSE));
+ EXPECT_CALL(pointer1, add_axis_value())
+ .WillOnce(Return(&axisValue1))
+ .WillOnce(Return(&axisValue2))
+ .WillOnce(Return(&axisValue3));
+ EXPECT_CALL(axisValue1, set_axis(AMOTION_EVENT_AXIS_X));
+ EXPECT_CALL(axisValue2, set_axis(AMOTION_EVENT_AXIS_Y));
+ EXPECT_CALL(axisValue3, set_axis(AMOTION_EVENT_AXIS_PRESSURE));
+
+ EXPECT_CALL(pointer2, set_pointer_id(16));
+ EXPECT_CALL(pointer2, set_tool_type(AMOTION_EVENT_TOOL_TYPE_FINGER));
+ EXPECT_CALL(pointer2, add_axis_value())
+ .WillOnce(Return(&axisValue4))
+ .WillOnce(Return(&axisValue5))
+ .WillOnce(Return(&axisValue6));
+ EXPECT_CALL(axisValue4, set_axis(AMOTION_EVENT_AXIS_X));
+ EXPECT_CALL(axisValue5, set_axis(AMOTION_EVENT_AXIS_Y));
+ EXPECT_CALL(axisValue6, set_axis(AMOTION_EVENT_AXIS_PRESSURE));
+
+ // Redacted fields
+ EXPECT_CALL(proto, set_meta_state(_)).Times(0);
+ EXPECT_CALL(proto, set_cursor_position_x(_)).Times(0);
+ EXPECT_CALL(proto, set_cursor_position_y(_)).Times(0);
+ EXPECT_CALL(proto, set_precision_x(_)).Times(0);
+ EXPECT_CALL(proto, set_precision_y(_)).Times(0);
+ EXPECT_CALL(axisValue1, set_value(_)).Times(0);
+ EXPECT_CALL(axisValue2, set_value(_)).Times(0);
+ EXPECT_CALL(axisValue3, set_value(_)).Times(0);
+ EXPECT_CALL(axisValue4, set_value(_)).Times(0);
+ EXPECT_CALL(axisValue5, set_value(_)).Times(0);
+ EXPECT_CALL(axisValue6, set_value(_)).Times(0);
+
+ TestProtoConverter::toProtoMotionEvent(event, proto, /*isRedacted=*/true);
+}
+
+// Test any special handling for zero values for pointer events.
+TEST(AndroidInputEventProtoConverterTest, ToProtoMotionEvent_ZeroValues) {
+ TracedMotionEvent event{};
+ event.id = 0;
+ event.eventTime = 0;
+ event.downTime = 0;
+ event.source = AINPUT_SOURCE_MOUSE;
+ event.action = AMOTION_EVENT_ACTION_BUTTON_PRESS;
+ event.deviceId = 0;
+ event.displayId = ui::LogicalDisplayId(0);
+ event.classification = {};
+ event.flags = 0;
+ event.policyFlags = 0;
+ event.buttonState = 0;
+ event.actionButton = 0;
+ event.xCursorPosition = 0.0f;
+ event.yCursorPosition = 0.0f;
+ event.metaState = 0;
+ event.xPrecision = 0.0f;
+ event.yPrecision = 0.0f;
+ event.pointerProperties.emplace_back(PointerProperties{
+ .id = 0,
+ .toolType = ToolType::MOUSE,
+ });
+ event.pointerProperties.emplace_back(PointerProperties{
+ .id = 1,
+ .toolType = ToolType::FINGER,
+ });
+ // Zero values for x and y axes are always traced for pointer events.
+ // However, zero values for other axes may not necessarily be traced.
+ event.pointerCoords.emplace_back();
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, 0.0f);
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, 1.0f);
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 0.0f);
+ event.pointerCoords.emplace_back();
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, 0.0f);
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, 0.0f);
+ event.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 0.0f);
+
+ testing::StrictMock<MockProtoMotion> proto;
+ testing::StrictMock<MockProtoPointer> pointer1;
+ testing::StrictMock<MockProtoPointer> pointer2;
+ testing::StrictMock<MockProtoAxisValue> axisValue1;
+ testing::StrictMock<MockProtoAxisValue> axisValue2;
+ testing::StrictMock<MockProtoAxisValue> axisValue3;
+ testing::StrictMock<MockProtoAxisValue> axisValue4;
+
+ EXPECT_CALL(proto, set_event_id(0));
+ EXPECT_CALL(proto, set_event_time_nanos(0));
+ EXPECT_CALL(proto, set_down_time_nanos(0));
+ EXPECT_CALL(proto, set_source(AINPUT_SOURCE_MOUSE));
+ EXPECT_CALL(proto, set_action(AMOTION_EVENT_ACTION_BUTTON_PRESS));
+ EXPECT_CALL(proto, set_device_id(0));
+ EXPECT_CALL(proto, set_display_id(0));
+ EXPECT_CALL(proto, set_classification(0));
+ EXPECT_CALL(proto, set_flags(0));
+ EXPECT_CALL(proto, set_policy_flags(0));
+ EXPECT_CALL(proto, set_button_state(0));
+ EXPECT_CALL(proto, set_action_button(0));
+ EXPECT_CALL(proto, set_cursor_position_x(0.0f));
+ EXPECT_CALL(proto, set_cursor_position_y(0.0f));
+ EXPECT_CALL(proto, set_meta_state(0));
+ EXPECT_CALL(proto, set_precision_x(0.0f));
+ EXPECT_CALL(proto, set_precision_y(0.0f));
+
+ EXPECT_CALL(proto, add_pointer()).WillOnce(Return(&pointer1)).WillOnce(Return(&pointer2));
+
+ EXPECT_CALL(pointer1, set_pointer_id(0));
+ EXPECT_CALL(pointer1, set_tool_type(AMOTION_EVENT_TOOL_TYPE_MOUSE));
+ EXPECT_CALL(pointer1, add_axis_value())
+ .WillOnce(Return(&axisValue1))
+ .WillOnce(Return(&axisValue2));
+ EXPECT_CALL(axisValue1, set_axis(AMOTION_EVENT_AXIS_X));
+ EXPECT_CALL(axisValue1, set_value(0.0f));
+ EXPECT_CALL(axisValue2, set_axis(AMOTION_EVENT_AXIS_Y));
+ EXPECT_CALL(axisValue2, set_value(1.0f));
+
+ EXPECT_CALL(pointer2, set_pointer_id(1));
+ EXPECT_CALL(pointer2, set_tool_type(AMOTION_EVENT_TOOL_TYPE_FINGER));
+ EXPECT_CALL(pointer2, add_axis_value())
+ .WillOnce(Return(&axisValue3))
+ .WillOnce(Return(&axisValue4));
+ EXPECT_CALL(axisValue3, set_axis(AMOTION_EVENT_AXIS_X));
+ EXPECT_CALL(axisValue3, set_value(0.0f));
+ EXPECT_CALL(axisValue4, set_axis(AMOTION_EVENT_AXIS_Y));
+ EXPECT_CALL(axisValue4, set_value(0.0f));
+
+ TestProtoConverter::toProtoMotionEvent(event, proto, /*isRedacted=*/false);
+}
+
+TEST(AndroidInputEventProtoConverterTest, ToProtoKeyEvent) {
+ TracedKeyEvent event{};
+ event.id = 1;
+ event.eventTime = 2;
+ event.downTime = 3;
+ event.source = AINPUT_SOURCE_KEYBOARD;
+ event.action = AKEY_EVENT_ACTION_DOWN;
+ event.deviceId = 4;
+ event.displayId = ui::LogicalDisplayId(5);
+ event.repeatCount = 6;
+ event.flags = 7;
+ event.policyFlags = 8;
+ event.keyCode = 9;
+ event.scanCode = 10;
+ event.metaState = 11;
+
+ testing::StrictMock<MockProtoKey> proto;
+
+ EXPECT_CALL(proto, set_event_id(1));
+ EXPECT_CALL(proto, set_event_time_nanos(2));
+ EXPECT_CALL(proto, set_down_time_nanos(3));
+ EXPECT_CALL(proto, set_source(AINPUT_SOURCE_KEYBOARD));
+ EXPECT_CALL(proto, set_action(AKEY_EVENT_ACTION_DOWN));
+ EXPECT_CALL(proto, set_device_id(4));
+ EXPECT_CALL(proto, set_display_id(5));
+ EXPECT_CALL(proto, set_repeat_count(6));
+ EXPECT_CALL(proto, set_flags(7));
+ EXPECT_CALL(proto, set_policy_flags(8));
+ EXPECT_CALL(proto, set_key_code(9));
+ EXPECT_CALL(proto, set_scan_code(10));
+ EXPECT_CALL(proto, set_meta_state(11));
+
+ TestProtoConverter::toProtoKeyEvent(event, proto, /*isRedacted=*/false);
+}
+
+TEST(AndroidInputEventProtoConverterTest, ToProtoKeyEvent_Redacted) {
+ TracedKeyEvent event{};
+ event.id = 1;
+ event.eventTime = 2;
+ event.downTime = 3;
+ event.source = AINPUT_SOURCE_KEYBOARD;
+ event.action = AKEY_EVENT_ACTION_DOWN;
+ event.deviceId = 4;
+ event.displayId = ui::LogicalDisplayId(5);
+ event.repeatCount = 6;
+ event.flags = 7;
+ event.policyFlags = 8;
+ event.keyCode = 9;
+ event.scanCode = 10;
+ event.metaState = 11;
+
+ testing::StrictMock<MockProtoKey> proto;
+
+ EXPECT_CALL(proto, set_event_id(1));
+ EXPECT_CALL(proto, set_event_time_nanos(2));
+ EXPECT_CALL(proto, set_down_time_nanos(3));
+ EXPECT_CALL(proto, set_source(AINPUT_SOURCE_KEYBOARD));
+ EXPECT_CALL(proto, set_action(AKEY_EVENT_ACTION_DOWN));
+ EXPECT_CALL(proto, set_device_id(4));
+ EXPECT_CALL(proto, set_display_id(5));
+ EXPECT_CALL(proto, set_repeat_count(6));
+ EXPECT_CALL(proto, set_flags(7));
+ EXPECT_CALL(proto, set_policy_flags(8));
+
+ // Redacted fields
+ EXPECT_CALL(proto, set_key_code(_)).Times(0);
+ EXPECT_CALL(proto, set_scan_code(_)).Times(0);
+ EXPECT_CALL(proto, set_meta_state(_)).Times(0);
+
+ TestProtoConverter::toProtoKeyEvent(event, proto, /*isRedacted=*/true);
+}
+
+TEST(AndroidInputEventProtoConverterTest, ToProtoWindowDispatchEvent_Motion_IdentityTransform) {
+ TracedMotionEvent motion{};
+ motion.pointerProperties.emplace_back(PointerProperties{
+ .id = 4,
+ .toolType = ToolType::MOUSE,
+ });
+ motion.pointerCoords.emplace_back();
+ motion.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, 5.0f);
+ motion.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, 6.0f);
+
+ WindowDispatchArgs args{};
+ args.eventEntry = motion;
+ args.vsyncId = 1;
+ args.windowId = 2;
+ args.resolvedFlags = 3;
+ args.rawTransform = ui::Transform{};
+ args.transform = ui::Transform{};
+
+ testing::StrictMock<MockProtoDispatch> proto;
+ testing::StrictMock<MockProtoDispatchPointer> pointer;
+
+ EXPECT_CALL(proto, set_event_id(0));
+ EXPECT_CALL(proto, set_vsync_id(1));
+ EXPECT_CALL(proto, set_window_id(2));
+ EXPECT_CALL(proto, set_resolved_flags(3));
+ EXPECT_CALL(proto, add_dispatched_pointer()).WillOnce(Return(&pointer));
+ EXPECT_CALL(pointer, set_pointer_id(4));
+
+ // Since we are using identity transforms, the axis values will be identical to those in the
+ // traced event, so they should not be traced here.
+ EXPECT_CALL(pointer, add_axis_value_in_window()).Times(0);
+ EXPECT_CALL(pointer, set_x_in_display(_)).Times(0);
+ EXPECT_CALL(pointer, set_y_in_display(_)).Times(0);
+
+ TestProtoConverter::toProtoWindowDispatchEvent(args, proto, /*isRedacted=*/false);
+}
+
+TEST(AndroidInputEventProtoConverterTest, ToProtoWindowDispatchEvent_Motion_CustomTransform) {
+ TracedMotionEvent motion{};
+ motion.pointerProperties.emplace_back(PointerProperties{
+ .id = 4,
+ .toolType = ToolType::MOUSE,
+ });
+ motion.pointerCoords.emplace_back();
+ motion.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, 8.0f);
+ motion.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, 6.0f);
+
+ WindowDispatchArgs args{};
+ args.eventEntry = motion;
+ args.vsyncId = 1;
+ args.windowId = 2;
+ args.resolvedFlags = 3;
+ args.rawTransform.set(2, 0, 0, 0.5);
+ args.transform.set(1.0, 0, 0, 0.5);
+
+ testing::StrictMock<MockProtoDispatch> proto;
+ testing::StrictMock<MockProtoDispatchPointer> pointer;
+ testing::StrictMock<MockProtoAxisValue> axisValue1;
+
+ EXPECT_CALL(proto, set_event_id(0));
+ EXPECT_CALL(proto, set_vsync_id(1));
+ EXPECT_CALL(proto, set_window_id(2));
+ EXPECT_CALL(proto, set_resolved_flags(3));
+ EXPECT_CALL(proto, add_dispatched_pointer()).WillOnce(Return(&pointer));
+ EXPECT_CALL(pointer, set_pointer_id(4));
+
+ // Only the transformed axis-values that differ from the traced event will be traced.
+ EXPECT_CALL(pointer, add_axis_value_in_window()).WillOnce(Return(&axisValue1));
+ EXPECT_CALL(pointer, set_x_in_display(16.0f)); // MotionEvent::getRawX
+ EXPECT_CALL(pointer, set_y_in_display(3.0f)); // MotionEvent::getRawY
+
+ EXPECT_CALL(axisValue1, set_axis(AMOTION_EVENT_AXIS_Y));
+ EXPECT_CALL(axisValue1, set_value(3.0f));
+
+ TestProtoConverter::toProtoWindowDispatchEvent(args, proto, /*isRedacted=*/false);
+}
+
+TEST(AndroidInputEventProtoConverterTest, ToProtoWindowDispatchEvent_Motion_Redacted) {
+ TracedMotionEvent motion{};
+ motion.pointerProperties.emplace_back(PointerProperties{
+ .id = 4,
+ .toolType = ToolType::MOUSE,
+ });
+ motion.pointerCoords.emplace_back();
+ motion.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_X, 5.0f);
+ motion.pointerCoords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, 6.0f);
+
+ WindowDispatchArgs args{};
+ args.eventEntry = motion;
+ args.vsyncId = 1;
+ args.windowId = 2;
+ args.resolvedFlags = 3;
+ args.rawTransform = ui::Transform{};
+ args.transform = ui::Transform{};
+
+ testing::StrictMock<MockProtoDispatch> proto;
+
+ EXPECT_CALL(proto, set_event_id(0));
+ EXPECT_CALL(proto, set_vsync_id(1));
+ EXPECT_CALL(proto, set_window_id(2));
+ EXPECT_CALL(proto, set_resolved_flags(3));
+
+ // Redacted fields
+ EXPECT_CALL(proto, add_dispatched_pointer()).Times(0);
+
+ TestProtoConverter::toProtoWindowDispatchEvent(args, proto, /*isRedacted=*/true);
+}
+
+TEST(AndroidInputEventProtoConverterTest, ToProtoWindowDispatchEvent_Key) {
+ TracedKeyEvent key{};
+
+ WindowDispatchArgs args{};
+ args.eventEntry = key;
+ args.vsyncId = 1;
+ args.windowId = 2;
+ args.resolvedFlags = 3;
+ args.rawTransform = ui::Transform{};
+ args.transform = ui::Transform{};
+
+ testing::StrictMock<MockProtoDispatch> proto;
+
+ EXPECT_CALL(proto, set_event_id(0));
+ EXPECT_CALL(proto, set_vsync_id(1));
+ EXPECT_CALL(proto, set_window_id(2));
+ EXPECT_CALL(proto, set_resolved_flags(3));
+
+ TestProtoConverter::toProtoWindowDispatchEvent(args, proto, /*isRedacted=*/true);
+}
+
+} // namespace
+
+} // namespace android::inputdispatcher::trace
diff --git a/services/inputflinger/tests/CursorInputMapper_test.cpp b/services/inputflinger/tests/CursorInputMapper_test.cpp
index 1762a45..594ee3b 100644
--- a/services/inputflinger/tests/CursorInputMapper_test.cpp
+++ b/services/inputflinger/tests/CursorInputMapper_test.cpp
@@ -25,8 +25,11 @@
#include <android-base/logging.h>
#include <android_companion_virtualdevice_flags.h>
#include <com_android_input_flags.h>
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <input/AccelerationCurve.h>
#include <input/DisplayViewport.h>
+#include <input/InputEventLabels.h>
#include <linux/input-event-codes.h>
#include <linux/input.h>
#include <utils/Timers.h>
@@ -52,6 +55,8 @@
constexpr auto BUTTON_RELEASE = AMOTION_EVENT_ACTION_BUTTON_RELEASE;
constexpr auto HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
constexpr auto INVALID_CURSOR_POSITION = AMOTION_EVENT_INVALID_CURSOR_POSITION;
+constexpr auto AXIS_X = AMOTION_EVENT_AXIS_X;
+constexpr auto AXIS_Y = AMOTION_EVENT_AXIS_Y;
constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
constexpr ui::LogicalDisplayId SECONDARY_DISPLAY_ID = ui::LogicalDisplayId{DISPLAY_ID.val() + 1};
constexpr int32_t DISPLAY_WIDTH = 480;
@@ -94,9 +99,35 @@
return v;
}
+// In a number of these tests, we want to check that some pointer motion is reported without
+// specifying an exact value, as that would require updating the tests every time the pointer
+// ballistics was changed. To do this, we make some matchers that only check the sign of a
+// particular axis.
+MATCHER_P(WithPositiveAxis, axis, "MotionEvent with a positive axis value") {
+ *result_listener << "expected 1 pointer with a positive "
+ << InputEventLookup::getAxisLabel(axis) << " axis but got "
+ << arg.pointerCoords.size() << " pointers, with axis value "
+ << arg.pointerCoords[0].getAxisValue(axis);
+ return arg.pointerCoords.size() == 1 && arg.pointerCoords[0].getAxisValue(axis) > 0;
+}
+
+MATCHER_P(WithZeroAxis, axis, "MotionEvent with a zero axis value") {
+ *result_listener << "expected 1 pointer with a zero " << InputEventLookup::getAxisLabel(axis)
+ << " axis but got " << arg.pointerCoords.size()
+ << " pointers, with axis value " << arg.pointerCoords[0].getAxisValue(axis);
+ return arg.pointerCoords.size() == 1 && arg.pointerCoords[0].getAxisValue(axis) == 0;
+}
+
+MATCHER_P(WithNegativeAxis, axis, "MotionEvent with a negative axis value") {
+ *result_listener << "expected 1 pointer with a negative "
+ << InputEventLookup::getAxisLabel(axis) << " axis but got "
+ << arg.pointerCoords.size() << " pointers, with axis value "
+ << arg.pointerCoords[0].getAxisValue(axis);
+ return arg.pointerCoords.size() == 1 && arg.pointerCoords[0].getAxisValue(axis) < 0;
+}
+
} // namespace
-namespace input_flags = com::android::input::flags;
namespace vd_flags = android::companion::virtualdevice::flags;
/**
@@ -110,9 +141,9 @@
*/
class CursorInputMapperUnitTestBase : public InputMapperUnitTest {
protected:
- void SetUp() override { SetUpWithBus(BUS_USB); }
- void SetUpWithBus(int bus) override {
- InputMapperUnitTest::SetUpWithBus(bus);
+ void SetUp() override { SetUp(BUS_USB, /*isExternal=*/false); }
+ void SetUp(int bus, bool isExternal) override {
+ InputMapperUnitTest::SetUp(bus, isExternal);
// Current scan code state - all keys are UP by default
setScanCodeState(KeyState::UP,
@@ -150,24 +181,21 @@
ASSERT_GT(mDevice->getGeneration(), generation);
}
- void testMotionRotation(int32_t originalX, int32_t originalY, int32_t rotatedX,
- int32_t rotatedY) {
+ void testRotation(int32_t originalX, int32_t originalY,
+ const testing::Matcher<NotifyMotionArgs>& coordsMatcher) {
std::list<NotifyArgs> args;
args += process(ARBITRARY_TIME, EV_REL, REL_X, originalX);
args += process(ARBITRARY_TIME, EV_REL, REL_Y, originalY);
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
ASSERT_THAT(args,
ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(ACTION_MOVE),
- WithCoords(float(rotatedX) / TRACKBALL_MOVEMENT_THRESHOLD,
- float(rotatedY) / TRACKBALL_MOVEMENT_THRESHOLD)))));
+ AllOf(WithMotionAction(ACTION_MOVE), coordsMatcher))));
}
};
class CursorInputMapperUnitTest : public CursorInputMapperUnitTestBase {
protected:
void SetUp() override {
- input_flags::enable_new_mouse_pointer_ballistics(false);
vd_flags::high_resolution_scroll(false);
CursorInputMapperUnitTestBase::SetUp();
}
@@ -344,14 +372,12 @@
args += process(EV_KEY, BTN_MOUSE, 0);
args += process(EV_SYN, SYN_REPORT, 0);
ASSERT_THAT(args,
- ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(BUTTON_RELEASE),
- WithSource(AINPUT_SOURCE_MOUSE_RELATIVE),
- WithCoords(0.0f, 0.0f), WithPressure(0.0f))),
- VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(ACTION_UP),
- WithSource(AINPUT_SOURCE_MOUSE_RELATIVE),
- WithCoords(0.0f, 0.0f), WithPressure(0.0f)))));
+ ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
+ VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP))));
+ ASSERT_THAT(args,
+ Each(VariantWith<NotifyMotionArgs>(AllOf(WithSource(AINPUT_SOURCE_MOUSE_RELATIVE),
+ WithCoords(0.0f, 0.0f),
+ WithPressure(0.0f)))));
// Another move.
args.clear();
@@ -377,7 +403,8 @@
ElementsAre(VariantWith<NotifyMotionArgs>(
AllOf(WithMotionAction(HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE),
expectedCoords, expectedCursorPosition,
- WithRelativeMotion(10.0f, 20.0f)))));
+ WithPositiveAxis(AMOTION_EVENT_AXIS_RELATIVE_X),
+ WithPositiveAxis(AMOTION_EVENT_AXIS_RELATIVE_Y)))));
}
TEST_F(CursorInputMapperUnitTest, PopulateDeviceInfoReturnsScaledRangeInNavigationMode) {
@@ -411,64 +438,40 @@
args += process(ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 1);
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
- ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithEventTime(ARBITRARY_TIME), WithDeviceId(DEVICE_ID),
- WithSource(AINPUT_SOURCE_TRACKBALL), WithFlags(0),
- WithEdgeFlags(0), WithPolicyFlags(0),
- WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
- WithMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON),
- WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY),
- WithPointerCount(1), WithPointerId(0, 0),
- WithToolType(ToolType::MOUSE), WithCoords(0.0f, 0.0f),
- WithPressure(1.0f),
- WithPrecision(TRACKBALL_MOVEMENT_THRESHOLD,
- TRACKBALL_MOVEMENT_THRESHOLD),
- WithDownTime(ARBITRARY_TIME))),
- VariantWith<NotifyMotionArgs>(
- AllOf(WithEventTime(ARBITRARY_TIME), WithDeviceId(DEVICE_ID),
- WithSource(AINPUT_SOURCE_TRACKBALL), WithFlags(0),
- WithEdgeFlags(0), WithPolicyFlags(0),
- WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
- WithMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON),
- WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY),
- WithPointerCount(1), WithPointerId(0, 0),
- WithToolType(ToolType::MOUSE), WithCoords(0.0f, 0.0f),
- WithPressure(1.0f),
- WithPrecision(TRACKBALL_MOVEMENT_THRESHOLD,
- TRACKBALL_MOVEMENT_THRESHOLD),
- WithDownTime(ARBITRARY_TIME)))));
+ ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_DOWN)),
+ VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_PRESS))));
+ EXPECT_THAT(args,
+ Each(VariantWith<NotifyMotionArgs>(
+ AllOf(WithEventTime(ARBITRARY_TIME), WithDeviceId(DEVICE_ID),
+ WithSource(AINPUT_SOURCE_TRACKBALL), WithFlags(0), WithEdgeFlags(0),
+ WithPolicyFlags(0),
+ WithMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON),
+ WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY), WithPointerCount(1),
+ WithPointerId(0, 0), WithToolType(ToolType::MOUSE),
+ WithCoords(0.0f, 0.0f), WithPressure(1.0f),
+ WithPrecision(TRACKBALL_MOVEMENT_THRESHOLD,
+ TRACKBALL_MOVEMENT_THRESHOLD),
+ WithDownTime(ARBITRARY_TIME)))));
args.clear();
// Button release. Should have same down time.
args += process(ARBITRARY_TIME + 1, EV_KEY, BTN_MOUSE, 0);
args += process(ARBITRARY_TIME + 1, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
- ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithEventTime(ARBITRARY_TIME + 1),
- WithDeviceId(DEVICE_ID),
- WithSource(AINPUT_SOURCE_TRACKBALL), WithFlags(0),
- WithEdgeFlags(0), WithPolicyFlags(0),
- WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
- WithMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON),
- WithButtonState(0), WithPointerCount(1),
- WithPointerId(0, 0), WithToolType(ToolType::MOUSE),
- WithCoords(0.0f, 0.0f), WithPressure(0.0f),
- WithPrecision(TRACKBALL_MOVEMENT_THRESHOLD,
- TRACKBALL_MOVEMENT_THRESHOLD),
- WithDownTime(ARBITRARY_TIME))),
- VariantWith<NotifyMotionArgs>(
- AllOf(WithEventTime(ARBITRARY_TIME + 1),
- WithDeviceId(DEVICE_ID),
- WithSource(AINPUT_SOURCE_TRACKBALL), WithFlags(0),
- WithEdgeFlags(0), WithPolicyFlags(0),
- WithMotionAction(AMOTION_EVENT_ACTION_UP),
- WithMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON),
- WithButtonState(0), WithPointerCount(1),
- WithPointerId(0, 0), WithToolType(ToolType::MOUSE),
- WithCoords(0.0f, 0.0f), WithPressure(0.0f),
- WithPrecision(TRACKBALL_MOVEMENT_THRESHOLD,
- TRACKBALL_MOVEMENT_THRESHOLD),
- WithDownTime(ARBITRARY_TIME)))));
+ ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
+ VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP))));
+ EXPECT_THAT(args,
+ Each(VariantWith<NotifyMotionArgs>(
+ AllOf(WithEventTime(ARBITRARY_TIME + 1), WithDeviceId(DEVICE_ID),
+ WithSource(AINPUT_SOURCE_TRACKBALL), WithFlags(0), WithEdgeFlags(0),
+ WithPolicyFlags(0),
+ WithMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON),
+ WithButtonState(0), WithPointerCount(1), WithPointerId(0, 0),
+ WithToolType(ToolType::MOUSE), WithCoords(0.0f, 0.0f),
+ WithPressure(0.0f),
+ WithPrecision(TRACKBALL_MOVEMENT_THRESHOLD,
+ TRACKBALL_MOVEMENT_THRESHOLD),
+ WithDownTime(ARBITRARY_TIME)))));
}
TEST_F(CursorInputMapperUnitTest, ProcessShouldHandleIndependentXYUpdates) {
@@ -482,9 +485,8 @@
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
- WithCoords(1.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f),
- WithPressure(0.0f)))));
+ AllOf(WithMotionAction(ACTION_MOVE), WithPressure(0.0f),
+ WithPositiveAxis(AXIS_X), WithZeroAxis(AXIS_Y)))));
args.clear();
// Motion in Y but not X.
@@ -492,9 +494,8 @@
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
- WithCoords(0.0f, -2.0f / TRACKBALL_MOVEMENT_THRESHOLD),
- WithPressure(0.0f)))));
+ AllOf(WithMotionAction(ACTION_MOVE), WithPressure(0.0f),
+ WithZeroAxis(AXIS_X), WithNegativeAxis(AXIS_Y)))));
args.clear();
}
@@ -508,24 +509,22 @@
args += process(ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 1);
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
- ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
- WithCoords(0.0f, 0.0f), WithPressure(1.0f))),
- VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
- WithCoords(0.0f, 0.0f), WithPressure(1.0f)))));
+ ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_DOWN)),
+ VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_PRESS))));
+ EXPECT_THAT(args,
+ Each(VariantWith<NotifyMotionArgs>(
+ AllOf(WithCoords(0.0f, 0.0f), WithPressure(1.0f)))));
args.clear();
// Button release.
args += process(ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 0);
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
- ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
- WithCoords(0.0f, 0.0f), WithPressure(0.0f))),
- VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
- WithCoords(0.0f, 0.0f), WithPressure(0.0f)))));
+ ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
+ VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP))));
+ EXPECT_THAT(args,
+ Each(VariantWith<NotifyMotionArgs>(
+ AllOf(WithCoords(0.0f, 0.0f), WithPressure(0.0f)))));
}
TEST_F(CursorInputMapperUnitTest, ProcessShouldHandleCombinedXYAndButtonUpdates) {
@@ -540,16 +539,12 @@
args += process(ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 1);
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
- ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
- WithCoords(1.0f / TRACKBALL_MOVEMENT_THRESHOLD,
- -2.0f / TRACKBALL_MOVEMENT_THRESHOLD),
- WithPressure(1.0f))),
- VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
- WithCoords(1.0f / TRACKBALL_MOVEMENT_THRESHOLD,
- -2.0f / TRACKBALL_MOVEMENT_THRESHOLD),
- WithPressure(1.0f)))));
+ ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_DOWN)),
+ VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_PRESS))));
+ EXPECT_THAT(args,
+ Each(VariantWith<NotifyMotionArgs>(AllOf(WithPositiveAxis(AXIS_X),
+ WithNegativeAxis(AXIS_Y),
+ WithPressure(1.0f)))));
args.clear();
// Move X, Y a bit while pressed.
@@ -558,22 +553,19 @@
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
- WithCoords(2.0f / TRACKBALL_MOVEMENT_THRESHOLD,
- 1.0f / TRACKBALL_MOVEMENT_THRESHOLD),
- WithPressure(1.0f)))));
+ AllOf(WithMotionAction(ACTION_MOVE), WithPressure(1.0f),
+ WithPositiveAxis(AXIS_X), WithPositiveAxis(AXIS_Y)))));
args.clear();
// Release Button.
args += process(ARBITRARY_TIME, EV_KEY, BTN_MOUSE, 0);
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
- ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
- WithCoords(0.0f, 0.0f), WithPressure(0.0f))),
- VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
- WithCoords(0.0f, 0.0f), WithPressure(0.0f)))));
+ ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
+ VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP))));
+ EXPECT_THAT(args,
+ Each(VariantWith<NotifyMotionArgs>(
+ AllOf(WithCoords(0.0f, 0.0f), WithPressure(0.0f)))));
args.clear();
}
@@ -586,14 +578,16 @@
.WillRepeatedly(Return(createPrimaryViewport(ui::Rotation::Rotation90)));
mMapper = createInputMapper<CursorInputMapper>(*mDeviceContext, mReaderConfiguration);
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 0, 1, 0, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 1, 1, 1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 1, 0, 1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 1, -1, 1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 0, -1, 0, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(-1, -1, -1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(-1, 0, -1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(-1, 1, -1, 1));
+ constexpr auto X = AXIS_X;
+ constexpr auto Y = AXIS_Y;
+ ASSERT_NO_FATAL_FAILURE(testRotation( 0, 1, AllOf(WithZeroAxis(X), WithPositiveAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 1, 1, AllOf(WithPositiveAxis(X), WithPositiveAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 1, 0, AllOf(WithPositiveAxis(X), WithZeroAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 1, -1, AllOf(WithPositiveAxis(X), WithNegativeAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 0, -1, AllOf(WithZeroAxis(X), WithNegativeAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation(-1, -1, AllOf(WithNegativeAxis(X), WithNegativeAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation(-1, 0, AllOf(WithNegativeAxis(X), WithZeroAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation(-1, 1, AllOf(WithNegativeAxis(X), WithPositiveAxis(Y))));
}
TEST_F(CursorInputMapperUnitTest, ProcessShouldRotateMotionsWhenNotOrientationAware) {
@@ -604,54 +598,56 @@
.WillRepeatedly(Return(createPrimaryViewport(ui::Rotation::Rotation0)));
mMapper = createInputMapper<CursorInputMapper>(*mDeviceContext, mReaderConfiguration);
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 0, 1, 0, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 1, 1, 1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 1, 0, 1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 1, -1, 1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 0, -1, 0, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(-1, -1, -1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(-1, 0, -1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(-1, 1, -1, 1));
+ constexpr auto X = AXIS_X;
+ constexpr auto Y = AXIS_Y;
+ ASSERT_NO_FATAL_FAILURE(testRotation( 0, 1, AllOf(WithZeroAxis(X), WithPositiveAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 1, 1, AllOf(WithPositiveAxis(X), WithPositiveAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 1, 0, AllOf(WithPositiveAxis(X), WithZeroAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 1, -1, AllOf(WithPositiveAxis(X), WithNegativeAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 0, -1, AllOf(WithZeroAxis(X), WithNegativeAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation(-1, -1, AllOf(WithNegativeAxis(X), WithNegativeAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation(-1, 0, AllOf(WithNegativeAxis(X), WithZeroAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation(-1, 1, AllOf(WithNegativeAxis(X), WithPositiveAxis(Y))));
EXPECT_CALL((*mDevice), getAssociatedViewport)
.WillRepeatedly(Return(createPrimaryViewport(ui::Rotation::Rotation90)));
std::list<NotifyArgs> args =
mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration,
InputReaderConfiguration::Change::DISPLAY_INFO);
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 0, 1, -1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 1, 1, -1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 1, 0, 0, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 1, -1, 1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 0, -1, 1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(-1, -1, 1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(-1, 0, 0, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(-1, 1, -1, -1));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 0, 1, AllOf(WithNegativeAxis(X), WithZeroAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 1, 1, AllOf(WithNegativeAxis(X), WithPositiveAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 1, 0, AllOf(WithZeroAxis(X), WithPositiveAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 1, -1, AllOf(WithPositiveAxis(X), WithPositiveAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 0, -1, AllOf(WithPositiveAxis(X), WithZeroAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation(-1, -1, AllOf(WithPositiveAxis(X), WithNegativeAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation(-1, 0, AllOf(WithZeroAxis(X), WithNegativeAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation(-1, 1, AllOf(WithNegativeAxis(X), WithNegativeAxis(Y))));
EXPECT_CALL((*mDevice), getAssociatedViewport)
.WillRepeatedly(Return(createPrimaryViewport(ui::Rotation::Rotation180)));
args = mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration,
InputReaderConfiguration::Change::DISPLAY_INFO);
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 0, 1, 0, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 1, 1, -1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 1, 0, -1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 1, -1, -1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 0, -1, 0, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(-1, -1, 1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(-1, 0, 1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(-1, 1, 1, -1));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 0, 1, AllOf(WithZeroAxis(X), WithNegativeAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 1, 1, AllOf(WithNegativeAxis(X), WithNegativeAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 1, 0, AllOf(WithNegativeAxis(X), WithZeroAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 1, -1, AllOf(WithNegativeAxis(X), WithPositiveAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 0, -1, AllOf(WithZeroAxis(X), WithPositiveAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation(-1, -1, AllOf(WithPositiveAxis(X), WithPositiveAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation(-1, 0, AllOf(WithPositiveAxis(X), WithZeroAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation(-1, 1, AllOf(WithPositiveAxis(X), WithNegativeAxis(Y))));
EXPECT_CALL((*mDevice), getAssociatedViewport)
.WillRepeatedly(Return(createPrimaryViewport(ui::Rotation::Rotation270)));
args = mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration,
InputReaderConfiguration::Change::DISPLAY_INFO);
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 0, 1, 1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 1, 1, 1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 1, 0, 0, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 1, -1, -1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation( 0, -1, -1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(-1, -1, -1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(-1, 0, 0, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(-1, 1, 1, 1));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 0, 1, AllOf(WithPositiveAxis(X), WithZeroAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 1, 1, AllOf(WithPositiveAxis(X), WithNegativeAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 1, 0, AllOf(WithZeroAxis(X), WithNegativeAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 1, -1, AllOf(WithNegativeAxis(X), WithNegativeAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation( 0, -1, AllOf(WithNegativeAxis(X), WithZeroAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation(-1, -1, AllOf(WithNegativeAxis(X), WithPositiveAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation(-1, 0, AllOf(WithZeroAxis(X), WithPositiveAxis(Y))));
+ ASSERT_NO_FATAL_FAILURE(testRotation(-1, 1, AllOf(WithPositiveAxis(X), WithPositiveAxis(Y))));
}
TEST_F(CursorInputMapperUnitTest, PopulateDeviceInfoReturnsRangeFromPolicy) {
@@ -742,30 +738,22 @@
args += process(ARBITRARY_TIME, EV_KEY, BTN_LEFT, 1);
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
- ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
- WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY),
- WithCoords(0.0f, 0.0f), WithPressure(1.0f))),
- VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
- WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY),
- WithCoords(0.0f, 0.0f), WithPressure(1.0f)))));
+ ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_DOWN)),
+ VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_PRESS))));
+ EXPECT_THAT(args,
+ Each(VariantWith<NotifyMotionArgs>(
+ AllOf(WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY), WithCoords(0.0f, 0.0f),
+ WithPressure(1.0f)))));
args.clear();
args += process(ARBITRARY_TIME, EV_KEY, BTN_LEFT, 0);
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
- ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
- WithButtonState(0), WithCoords(0.0f, 0.0f),
- WithPressure(0.0f))),
- VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
- WithButtonState(0), WithCoords(0.0f, 0.0f),
- WithPressure(0.0f))),
- VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
- WithButtonState(0), WithCoords(0.0f, 0.0f),
- WithPressure(0.0f)))));
+ ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
+ VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP)),
+ VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE))));
+ EXPECT_THAT(args,
+ Each(VariantWith<NotifyMotionArgs>(
+ AllOf(WithButtonState(0), WithCoords(0.0f, 0.0f), WithPressure(0.0f)))));
args.clear();
// press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
@@ -774,49 +762,41 @@
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
+ AllOf(WithMotionAction(ACTION_DOWN),
WithButtonState(AMOTION_EVENT_BUTTON_SECONDARY |
- AMOTION_EVENT_BUTTON_TERTIARY),
- WithCoords(0.0f, 0.0f), WithPressure(1.0f))),
+ AMOTION_EVENT_BUTTON_TERTIARY))),
VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
- WithButtonState(AMOTION_EVENT_BUTTON_TERTIARY),
- WithCoords(0.0f, 0.0f), WithPressure(1.0f))),
+ AllOf(WithMotionAction(BUTTON_PRESS),
+ WithButtonState(AMOTION_EVENT_BUTTON_TERTIARY))),
VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
+ AllOf(WithMotionAction(BUTTON_PRESS),
WithButtonState(AMOTION_EVENT_BUTTON_SECONDARY |
- AMOTION_EVENT_BUTTON_TERTIARY),
- WithCoords(0.0f, 0.0f), WithPressure(1.0f)))));
+ AMOTION_EVENT_BUTTON_TERTIARY)))));
+ EXPECT_THAT(args,
+ Each(VariantWith<NotifyMotionArgs>(
+ AllOf(WithCoords(0.0f, 0.0f), WithPressure(1.0f)))));
args.clear();
args += process(ARBITRARY_TIME, EV_KEY, BTN_RIGHT, 0);
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
- ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
- WithButtonState(AMOTION_EVENT_BUTTON_TERTIARY),
- WithCoords(0.0f, 0.0f), WithPressure(1.0f))),
- VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
- WithButtonState(AMOTION_EVENT_BUTTON_TERTIARY),
- WithCoords(0.0f, 0.0f), WithPressure(1.0f)))));
+ ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
+ VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_MOVE))));
+ EXPECT_THAT(args,
+ Each(VariantWith<NotifyMotionArgs>(
+ AllOf(WithButtonState(AMOTION_EVENT_BUTTON_TERTIARY),
+ WithCoords(0.0f, 0.0f), WithPressure(1.0f)))));
args.clear();
args += process(ARBITRARY_TIME, EV_KEY, BTN_MIDDLE, 0);
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
- ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
- WithButtonState(0), WithCoords(0.0f, 0.0f),
- WithPressure(0.0f))),
- VariantWith<NotifyMotionArgs>(
- AllOf(WithButtonState(0),
- WithMotionAction(AMOTION_EVENT_ACTION_UP),
- WithCoords(0.0f, 0.0f), WithPressure(0.0f))),
- VariantWith<NotifyMotionArgs>(
- AllOf(WithButtonState(0),
- WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
- WithCoords(0.0f, 0.0f), WithPressure(0.0f)))));
+ ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(BUTTON_RELEASE)),
+ VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_UP)),
+ VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE))));
+ EXPECT_THAT(args,
+ Each(VariantWith<NotifyMotionArgs>(
+ AllOf(WithButtonState(0), WithCoords(0.0f, 0.0f), WithPressure(0.0f)))));
}
class CursorInputMapperButtonKeyTest
@@ -838,11 +818,11 @@
ElementsAre(VariantWith<NotifyKeyArgs>(AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN),
WithKeyCode(expectedKeyCode))),
VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
+ AllOf(WithMotionAction(HOVER_MOVE),
WithButtonState(expectedButtonState),
WithCoords(0.0f, 0.0f), WithPressure(0.0f))),
VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
+ AllOf(WithMotionAction(BUTTON_PRESS),
WithButtonState(expectedButtonState),
WithCoords(0.0f, 0.0f), WithPressure(0.0f)))));
args.clear();
@@ -851,13 +831,11 @@
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
- WithButtonState(0), WithCoords(0.0f, 0.0f),
- WithPressure(0.0f))),
+ AllOf(WithMotionAction(BUTTON_RELEASE), WithButtonState(0),
+ WithCoords(0.0f, 0.0f), WithPressure(0.0f))),
VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
- WithButtonState(0), WithCoords(0.0f, 0.0f),
- WithPressure(0.0f))),
+ AllOf(WithMotionAction(HOVER_MOVE), WithButtonState(0),
+ WithCoords(0.0f, 0.0f), WithPressure(0.0f))),
VariantWith<NotifyKeyArgs>(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
WithKeyCode(expectedKeyCode)))));
}
@@ -881,8 +859,7 @@
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithSource(AINPUT_SOURCE_MOUSE),
- WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
+ AllOf(WithSource(AINPUT_SOURCE_MOUSE), WithMotionAction(HOVER_MOVE),
WithCoords(0.0f, 0.0f), WithPressure(0.0f), WithSize(0.0f),
WithTouchDimensions(0.0f, 0.0f), WithToolDimensions(0.0f, 0.0f),
WithOrientation(0.0f), WithDistance(0.0f)))));
@@ -897,13 +874,11 @@
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
- ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithSource(AINPUT_SOURCE_MOUSE),
- WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))),
+ ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE)),
VariantWith<NotifyMotionArgs>(
- AllOf(WithSource(AINPUT_SOURCE_MOUSE),
- WithMotionAction(AMOTION_EVENT_ACTION_SCROLL),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_SCROLL),
WithScroll(1.0f, 1.0f)))));
+ EXPECT_THAT(args, Each(VariantWith<NotifyMotionArgs>(WithSource(AINPUT_SOURCE_MOUSE))));
}
TEST_F(CursorInputMapperUnitTest, ProcessHighResScroll) {
@@ -920,13 +895,11 @@
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
- ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithSource(AINPUT_SOURCE_MOUSE),
- WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))),
+ ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE)),
VariantWith<NotifyMotionArgs>(
- AllOf(WithSource(AINPUT_SOURCE_MOUSE),
- WithMotionAction(AMOTION_EVENT_ACTION_SCROLL),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_SCROLL),
WithScroll(0.5f, 0.5f)))));
+ EXPECT_THAT(args, Each(VariantWith<NotifyMotionArgs>(WithSource(AINPUT_SOURCE_MOUSE))));
}
TEST_F(CursorInputMapperUnitTest, HighResScrollIgnoresRegularScroll) {
@@ -945,13 +918,11 @@
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
- ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithSource(AINPUT_SOURCE_MOUSE),
- WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))),
+ ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE)),
VariantWith<NotifyMotionArgs>(
- AllOf(WithSource(AINPUT_SOURCE_MOUSE),
- WithMotionAction(AMOTION_EVENT_ACTION_SCROLL),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_SCROLL),
WithScroll(0.5f, 0.5f)))));
+ EXPECT_THAT(args, Each(VariantWith<NotifyMotionArgs>(WithSource(AINPUT_SOURCE_MOUSE))));
}
TEST_F(CursorInputMapperUnitTest, ProcessReversedVerticalScroll) {
@@ -966,13 +937,11 @@
// Reversed vertical scrolling only affects the y-axis, expect it to be -1.0f to indicate the
// inverted scroll direction.
EXPECT_THAT(args,
- ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithSource(AINPUT_SOURCE_MOUSE),
- WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))),
+ ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE)),
VariantWith<NotifyMotionArgs>(
- AllOf(WithSource(AINPUT_SOURCE_MOUSE),
- WithMotionAction(AMOTION_EVENT_ACTION_SCROLL),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_SCROLL),
WithScroll(1.0f, -1.0f)))));
+ EXPECT_THAT(args, Each(VariantWith<NotifyMotionArgs>(WithSource(AINPUT_SOURCE_MOUSE))));
}
TEST_F(CursorInputMapperUnitTest, ProcessHighResReversedVerticalScroll) {
@@ -990,13 +959,11 @@
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
- ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithSource(AINPUT_SOURCE_MOUSE),
- WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))),
+ ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(HOVER_MOVE)),
VariantWith<NotifyMotionArgs>(
- AllOf(WithSource(AINPUT_SOURCE_MOUSE),
- WithMotionAction(AMOTION_EVENT_ACTION_SCROLL),
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_SCROLL),
WithScroll(0.5f, -0.5f)))));
+ EXPECT_THAT(args, Each(VariantWith<NotifyMotionArgs>(WithSource(AINPUT_SOURCE_MOUSE))));
}
/**
@@ -1005,10 +972,6 @@
*/
TEST_F(CursorInputMapperUnitTest, PointerCaptureDisablesVelocityProcessing) {
mPropertyMap.addProperty("cursor.mode", "pointer");
- const VelocityControlParameters testParams(/*scale=*/5.f, /*lowThreshold=*/0.f,
- /*highThreshold=*/100.f, /*acceleration=*/10.f);
- mReaderConfiguration.pointerVelocityControlParameters = testParams;
- mFakePolicy->setVelocityControlParams(testParams);
createMapper();
NotifyMotionArgs motionArgs;
@@ -1020,8 +983,7 @@
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithSource(AINPUT_SOURCE_MOUSE),
- WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE)))));
+ AllOf(WithSource(AINPUT_SOURCE_MOUSE), WithMotionAction(HOVER_MOVE)))));
motionArgs = std::get<NotifyMotionArgs>(args.front());
const float relX = motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
const float relY = motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
@@ -1039,12 +1001,7 @@
EXPECT_THAT(args,
ElementsAre(VariantWith<NotifyMotionArgs>(
AllOf(WithSource(AINPUT_SOURCE_MOUSE_RELATIVE),
- WithMotionAction(AMOTION_EVENT_ACTION_MOVE)))));
- motionArgs = std::get<NotifyMotionArgs>(args.front());
- const float relX2 = motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
- const float relY2 = motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
- ASSERT_EQ(10, relX2);
- ASSERT_EQ(20, relY2);
+ WithMotionAction(ACTION_MOVE), WithRelativeMotion(10, 20)))));
}
TEST_F(CursorInputMapperUnitTest, ConfigureDisplayIdNoAssociatedViewport) {
@@ -1067,54 +1024,40 @@
args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(args,
ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
- WithSource(AINPUT_SOURCE_MOUSE),
+ AllOf(WithMotionAction(HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE),
WithDisplayId(ui::LogicalDisplayId::INVALID),
WithCoords(0.0f, 0.0f)))));
}
-// TODO(b/320433834): De-duplicate the test cases once the flag is removed.
-class CursorInputMapperUnitTestWithNewBallistics : public CursorInputMapperUnitTestBase {
-protected:
- void SetUp() override {
- input_flags::enable_new_mouse_pointer_ballistics(true);
- CursorInputMapperUnitTestBase::SetUp();
- }
-};
-
-TEST_F(CursorInputMapperUnitTestWithNewBallistics, PointerCaptureDisablesVelocityProcessing) {
+TEST_F(CursorInputMapperUnitTest, PointerAccelerationDisabled) {
+ mReaderConfiguration.mousePointerAccelerationEnabled = false;
+ mReaderConfiguration.mousePointerSpeed = 3;
mPropertyMap.addProperty("cursor.mode", "pointer");
createMapper();
- NotifyMotionArgs motionArgs;
- std::list<NotifyArgs> args;
+ std::list<NotifyArgs> reconfigureArgs;
- // Move and verify scale is applied.
- args += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
- args += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
- args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
- motionArgs = std::get<NotifyMotionArgs>(args.front());
- const float relX = motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
- const float relY = motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
- ASSERT_GT(relX, 10);
- ASSERT_GT(relY, 20);
- args.clear();
+ reconfigureArgs += mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration,
+ InputReaderConfiguration::Change::POINTER_SPEED);
- // Enable Pointer Capture
- setPointerCapture(true);
+ std::vector<AccelerationCurveSegment> curve =
+ createFlatAccelerationCurve(mReaderConfiguration.mousePointerSpeed);
+ double baseGain = curve[0].baseGain;
- // Move and verify scale is not applied.
- args += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
- args += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
- args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
- motionArgs = std::get<NotifyMotionArgs>(args.front());
- const float relX2 = motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X);
- const float relY2 = motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
- ASSERT_EQ(10, relX2);
- ASSERT_EQ(20, relY2);
+ std::list<NotifyArgs> motionArgs;
+ motionArgs += process(ARBITRARY_TIME, EV_REL, REL_X, 10);
+ motionArgs += process(ARBITRARY_TIME, EV_REL, REL_Y, 20);
+ motionArgs += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
+
+ const float expectedRelX = 10 * baseGain;
+ const float expectedRelY = 20 * baseGain;
+ ASSERT_THAT(motionArgs,
+ ElementsAre(VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(HOVER_MOVE),
+ WithRelativeMotion(expectedRelX, expectedRelY)))));
}
-TEST_F(CursorInputMapperUnitTestWithNewBallistics, ConfigureAccelerationWithAssociatedViewport) {
+TEST_F(CursorInputMapperUnitTest, ConfigureAccelerationWithAssociatedViewport) {
mPropertyMap.addProperty("cursor.mode", "pointer");
DisplayViewport primaryViewport = createPrimaryViewport(ui::Rotation::Rotation0);
mReaderConfiguration.setDisplayViewports({primaryViewport});
@@ -1135,7 +1078,7 @@
ASSERT_GT(coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y), 20.f);
// Disable acceleration for the display, and verify that acceleration is no longer applied.
- mReaderConfiguration.displaysWithMousePointerAccelerationDisabled.emplace(DISPLAY_ID);
+ mReaderConfiguration.displaysWithMouseScalingDisabled.emplace(DISPLAY_ID);
args += mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration,
InputReaderConfiguration::Change::POINTER_SPEED);
args.clear();
@@ -1149,12 +1092,12 @@
WithRelativeMotion(10, 20)))));
}
-TEST_F(CursorInputMapperUnitTestWithNewBallistics, ConfigureAccelerationOnDisplayChange) {
+TEST_F(CursorInputMapperUnitTest, ConfigureAccelerationOnDisplayChange) {
mPropertyMap.addProperty("cursor.mode", "pointer");
DisplayViewport primaryViewport = createPrimaryViewport(ui::Rotation::Rotation0);
mReaderConfiguration.setDisplayViewports({primaryViewport});
// Disable acceleration for the display.
- mReaderConfiguration.displaysWithMousePointerAccelerationDisabled.emplace(DISPLAY_ID);
+ mReaderConfiguration.displaysWithMouseScalingDisabled.emplace(DISPLAY_ID);
// Don't associate the device with the display yet.
EXPECT_CALL((*mDevice), getAssociatedViewport).WillRepeatedly(Return(std::nullopt));
@@ -1186,72 +1129,6 @@
WithRelativeMotion(10, 20)))));
}
-TEST_F(CursorInputMapperUnitTestWithNewBallistics, ProcessRegularScroll) {
- createMapper();
-
- std::list<NotifyArgs> args;
- args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL, 1);
- args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL, 1);
- args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-
- EXPECT_THAT(args,
- ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithSource(AINPUT_SOURCE_MOUSE),
- WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))),
- VariantWith<NotifyMotionArgs>(
- AllOf(WithSource(AINPUT_SOURCE_MOUSE),
- WithMotionAction(AMOTION_EVENT_ACTION_SCROLL),
- WithScroll(1.0f, 1.0f)))));
-}
-
-TEST_F(CursorInputMapperUnitTestWithNewBallistics, ProcessHighResScroll) {
- vd_flags::high_resolution_scroll(true);
- EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL_HI_RES))
- .WillRepeatedly(Return(true));
- EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL_HI_RES))
- .WillRepeatedly(Return(true));
- createMapper();
-
- std::list<NotifyArgs> args;
- args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL_HI_RES, 60);
- args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL_HI_RES, 60);
- args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-
- EXPECT_THAT(args,
- ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithSource(AINPUT_SOURCE_MOUSE),
- WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))),
- VariantWith<NotifyMotionArgs>(
- AllOf(WithSource(AINPUT_SOURCE_MOUSE),
- WithMotionAction(AMOTION_EVENT_ACTION_SCROLL),
- WithScroll(0.5f, 0.5f)))));
-}
-
-TEST_F(CursorInputMapperUnitTestWithNewBallistics, HighResScrollIgnoresRegularScroll) {
- vd_flags::high_resolution_scroll(true);
- EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL_HI_RES))
- .WillRepeatedly(Return(true));
- EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL_HI_RES))
- .WillRepeatedly(Return(true));
- createMapper();
-
- std::list<NotifyArgs> args;
- args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL_HI_RES, 60);
- args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL_HI_RES, 60);
- args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL, 1);
- args += process(ARBITRARY_TIME, EV_REL, REL_HWHEEL, 1);
- args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
-
- EXPECT_THAT(args,
- ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithSource(AINPUT_SOURCE_MOUSE),
- WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))),
- VariantWith<NotifyMotionArgs>(
- AllOf(WithSource(AINPUT_SOURCE_MOUSE),
- WithMotionAction(AMOTION_EVENT_ACTION_SCROLL),
- WithScroll(0.5f, 0.5f)))));
-}
-
namespace {
// Minimum timestamp separation between subsequent input events from a Bluetooth device.
@@ -1265,7 +1142,9 @@
class BluetoothCursorInputMapperUnitTest : public CursorInputMapperUnitTestBase {
protected:
- void SetUp() override { SetUpWithBus(BUS_BLUETOOTH); }
+ void SetUp() override {
+ CursorInputMapperUnitTestBase::SetUp(BUS_BLUETOOTH, /*isExternal=*/true);
+ }
};
TEST_F(BluetoothCursorInputMapperUnitTest, TimestampSmoothening) {
@@ -1279,8 +1158,7 @@
argsList += process(kernelEventTime, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(argsList,
ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
- WithEventTime(expectedEventTime)))));
+ AllOf(WithMotionAction(HOVER_MOVE), WithEventTime(expectedEventTime)))));
argsList.clear();
// Process several events that come in quick succession, according to their timestamps.
@@ -1294,7 +1172,7 @@
argsList += process(kernelEventTime, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(argsList,
ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
+ AllOf(WithMotionAction(HOVER_MOVE),
WithEventTime(expectedEventTime)))));
argsList.clear();
}
@@ -1310,8 +1188,7 @@
argsList += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(argsList,
ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
- WithEventTime(expectedEventTime)))));
+ AllOf(WithMotionAction(HOVER_MOVE), WithEventTime(expectedEventTime)))));
argsList.clear();
// Process several events with the same timestamp from the kernel.
@@ -1325,7 +1202,7 @@
argsList += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(argsList,
ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
+ AllOf(WithMotionAction(HOVER_MOVE),
WithEventTime(expectedEventTime)))));
argsList.clear();
}
@@ -1338,8 +1215,7 @@
argsList += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(argsList,
ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
- WithEventTime(cappedEventTime)))));
+ AllOf(WithMotionAction(HOVER_MOVE), WithEventTime(cappedEventTime)))));
argsList.clear();
}
}
@@ -1355,8 +1231,7 @@
argsList += process(kernelEventTime, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(argsList,
ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
- WithEventTime(expectedEventTime)))));
+ AllOf(WithMotionAction(HOVER_MOVE), WithEventTime(expectedEventTime)))));
argsList.clear();
// If the next event has a timestamp that is sufficiently spaced out so that Bluetooth timestamp
@@ -1368,8 +1243,7 @@
argsList += process(kernelEventTime, EV_SYN, SYN_REPORT, 0);
EXPECT_THAT(argsList,
ElementsAre(VariantWith<NotifyMotionArgs>(
- AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
- WithEventTime(expectedEventTime)))));
+ AllOf(WithMotionAction(HOVER_MOVE), WithEventTime(expectedEventTime)))));
argsList.clear();
}
diff --git a/services/inputflinger/tests/FakeEventHub.cpp b/services/inputflinger/tests/FakeEventHub.cpp
index 943de6e..e72c440 100644
--- a/services/inputflinger/tests/FakeEventHub.cpp
+++ b/services/inputflinger/tests/FakeEventHub.cpp
@@ -650,4 +650,25 @@
}
}
+bool FakeEventHub::setKernelWakeEnabled(int32_t deviceId, bool enabled) {
+ Device* device = getDevice(deviceId);
+ if (device == nullptr) {
+ return false;
+ }
+ mKernelWakeup.emplace(deviceId, enabled);
+ return true;
+}
+
+bool FakeEventHub::fakeReadKernelWakeup(int32_t deviceId) const {
+ Device* device = getDevice(deviceId);
+ if (device == nullptr) {
+ return false;
+ }
+ auto it = mKernelWakeup.find(deviceId);
+ if (it == mKernelWakeup.end()) {
+ return false;
+ }
+ return it->second;
+}
+
} // namespace android
diff --git a/services/inputflinger/tests/FakeEventHub.h b/services/inputflinger/tests/FakeEventHub.h
index 2dfbb23..143b93b 100644
--- a/services/inputflinger/tests/FakeEventHub.h
+++ b/services/inputflinger/tests/FakeEventHub.h
@@ -94,6 +94,8 @@
// Simulates a device light intensities, from light id to light intensities map.
std::unordered_map<int32_t /* lightId */, std::unordered_map<LightColor, int32_t>>
mLightIntensities;
+ // fake sysfs node path and value.
+ std::unordered_map<int32_t /*deviceId*/, bool /* wakeupNode*/> mKernelWakeup;
public:
static constexpr int32_t DEFAULT_BATTERY = 1;
@@ -158,6 +160,8 @@
void setMtSlotValues(int32_t deviceId, int32_t axis, const std::vector<int32_t>& values);
base::Result<std::vector<int32_t>> getMtSlotValues(int32_t deviceId, int32_t axis,
size_t slotCount) const override;
+ bool setKernelWakeEnabled(int32_t deviceId, bool enabled) override;
+ bool fakeReadKernelWakeup(int32_t deviceId) const;
private:
Device* getDevice(int32_t deviceId) const;
diff --git a/services/inputflinger/tests/FakeInputDispatcherPolicy.cpp b/services/inputflinger/tests/FakeInputDispatcherPolicy.cpp
index db68d8a..c4257a8 100644
--- a/services/inputflinger/tests/FakeInputDispatcherPolicy.cpp
+++ b/services/inputflinger/tests/FakeInputDispatcherPolicy.cpp
@@ -16,6 +16,8 @@
#include "FakeInputDispatcherPolicy.h"
+#include <variant>
+
#include <gtest/gtest.h>
namespace android {
@@ -409,12 +411,18 @@
void FakeInputDispatcherPolicy::interceptMotionBeforeQueueing(ui::LogicalDisplayId, uint32_t,
int32_t, nsecs_t, uint32_t&) {}
-nsecs_t FakeInputDispatcherPolicy::interceptKeyBeforeDispatching(const sp<IBinder>&,
- const KeyEvent&, uint32_t) {
+std::variant<nsecs_t, inputdispatcher::KeyEntry::InterceptKeyResult>
+FakeInputDispatcherPolicy::interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&,
+ uint32_t) {
if (mConsumeKeyBeforeDispatching) {
- return -1;
+ return inputdispatcher::KeyEntry::InterceptKeyResult::SKIP;
}
+
nsecs_t delay = std::chrono::nanoseconds(mInterceptKeyTimeout).count();
+ if (delay == 0) {
+ return inputdispatcher::KeyEntry::InterceptKeyResult::CONTINUE;
+ }
+
// Clear intercept state so we could dispatch the event in next wake.
mInterceptKeyTimeout = 0ms;
return delay;
diff --git a/services/inputflinger/tests/FakeInputDispatcherPolicy.h b/services/inputflinger/tests/FakeInputDispatcherPolicy.h
index a9e39d1..c387eac 100644
--- a/services/inputflinger/tests/FakeInputDispatcherPolicy.h
+++ b/services/inputflinger/tests/FakeInputDispatcherPolicy.h
@@ -28,11 +28,13 @@
#include <optional>
#include <queue>
#include <string>
+#include <variant>
#include <vector>
#include <android-base/logging.h>
#include <android-base/thread_annotations.h>
#include <binder/IBinder.h>
+#include <dispatcher/Entry.h>
#include <gui/PidUid.h>
#include <gui/WindowInfo.h>
#include <input/BlockingQueue.h>
@@ -189,7 +191,8 @@
void interceptKeyBeforeQueueing(const KeyEvent& inputEvent, uint32_t&) override;
void interceptMotionBeforeQueueing(ui::LogicalDisplayId, uint32_t, int32_t, nsecs_t,
uint32_t&) override;
- nsecs_t interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override;
+ std::variant<nsecs_t, inputdispatcher::KeyEntry::InterceptKeyResult>
+ interceptKeyBeforeDispatching(const sp<IBinder>&, const KeyEvent&, uint32_t) override;
std::optional<KeyEvent> dispatchUnhandledKey(const sp<IBinder>&, const KeyEvent& event,
uint32_t) override;
void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.cpp b/services/inputflinger/tests/FakeInputReaderPolicy.cpp
index f373cac..5a14f4b 100644
--- a/services/inputflinger/tests/FakeInputReaderPolicy.cpp
+++ b/services/inputflinger/tests/FakeInputReaderPolicy.cpp
@@ -31,6 +31,30 @@
} // namespace
+DisplayViewport createViewport(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
+ ui::Rotation orientation, bool isActive, const std::string& uniqueId,
+ std::optional<uint8_t> physicalPort, ViewportType type) {
+ const bool isRotated = orientation == ui::ROTATION_90 || orientation == ui::ROTATION_270;
+ DisplayViewport v;
+ v.displayId = displayId;
+ v.orientation = orientation;
+ v.logicalLeft = 0;
+ v.logicalTop = 0;
+ v.logicalRight = isRotated ? height : width;
+ v.logicalBottom = isRotated ? width : height;
+ v.physicalLeft = 0;
+ v.physicalTop = 0;
+ v.physicalRight = isRotated ? height : width;
+ v.physicalBottom = isRotated ? width : height;
+ v.deviceWidth = isRotated ? height : width;
+ v.deviceHeight = isRotated ? width : height;
+ v.isActive = isActive;
+ v.uniqueId = uniqueId;
+ v.physicalPort = physicalPort;
+ v.type = type;
+ return v;
+};
+
void FakeInputReaderPolicy::assertInputDevicesChanged() {
waitForInputDevices(
[](bool devicesChanged) {
@@ -80,6 +104,17 @@
ASSERT_TRUE(success) << "Timed out waiting for hardware state to be notified";
}
+void FakeInputReaderPolicy::assertTouchpadThreeFingerTapNotified() {
+ std::unique_lock lock(mLock);
+ base::ScopedLockAssertion assumeLocked(mLock);
+
+ const bool success =
+ mTouchpadThreeFingerTapNotified.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
+ return mTouchpadThreeFingerTapHasBeenReported;
+ });
+ ASSERT_TRUE(success) << "Timed out waiting for three-finger tap to be notified";
+}
+
void FakeInputReaderPolicy::clearViewports() {
mViewports.clear();
mConfig.setDisplayViewports(mViewports);
@@ -104,33 +139,6 @@
mConfig.setDisplayViewports(mViewports);
}
-void FakeInputReaderPolicy::addDisplayViewport(ui::LogicalDisplayId displayId, int32_t width,
- int32_t height, ui::Rotation orientation,
- bool isActive, const std::string& uniqueId,
- std::optional<uint8_t> physicalPort,
- ViewportType type) {
- const bool isRotated = orientation == ui::ROTATION_90 || orientation == ui::ROTATION_270;
- DisplayViewport v;
- v.displayId = displayId;
- v.orientation = orientation;
- v.logicalLeft = 0;
- v.logicalTop = 0;
- v.logicalRight = isRotated ? height : width;
- v.logicalBottom = isRotated ? width : height;
- v.physicalLeft = 0;
- v.physicalTop = 0;
- v.physicalRight = isRotated ? height : width;
- v.physicalBottom = isRotated ? width : height;
- v.deviceWidth = isRotated ? height : width;
- v.deviceHeight = isRotated ? width : height;
- v.isActive = isActive;
- v.uniqueId = uniqueId;
- v.physicalPort = physicalPort;
- v.type = type;
-
- addDisplayViewport(v);
-}
-
bool FakeInputReaderPolicy::updateViewport(const DisplayViewport& viewport) {
size_t count = mViewports.size();
for (size_t i = 0; i < count; i++) {
@@ -217,7 +225,6 @@
}
void FakeInputReaderPolicy::setVelocityControlParams(const VelocityControlParameters& params) {
- mConfig.pointerVelocityControlParameters = params;
mConfig.wheelVelocityControlParameters = params;
}
@@ -260,6 +267,12 @@
std::scoped_lock lock(mLock);
}
+void FakeInputReaderPolicy::notifyTouchpadThreeFingerTap() {
+ std::scoped_lock lock(mLock);
+ mTouchpadThreeFingerTapHasBeenReported = true;
+ mTouchpadThreeFingerTapNotified.notify_all();
+}
+
std::shared_ptr<KeyCharacterMap> FakeInputReaderPolicy::getKeyboardLayoutOverlay(
const InputDeviceIdentifier&, const std::optional<KeyboardLayoutInfo>) {
return nullptr;
diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.h b/services/inputflinger/tests/FakeInputReaderPolicy.h
index 3a2b4e9..9dce31a 100644
--- a/services/inputflinger/tests/FakeInputReaderPolicy.h
+++ b/services/inputflinger/tests/FakeInputReaderPolicy.h
@@ -31,6 +31,10 @@
namespace android {
+DisplayViewport createViewport(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
+ ui::Rotation orientation, bool isActive, const std::string& uniqueId,
+ std::optional<uint8_t> physicalPort, ViewportType type);
+
class FakeInputReaderPolicy : public InputReaderPolicyInterface {
protected:
virtual ~FakeInputReaderPolicy() {}
@@ -43,15 +47,13 @@
void assertStylusGestureNotified(int32_t deviceId);
void assertStylusGestureNotNotified();
void assertTouchpadHardwareStateNotified();
+ void assertTouchpadThreeFingerTapNotified();
virtual void clearViewports();
std::optional<DisplayViewport> getDisplayViewportByUniqueId(const std::string& uniqueId) const;
std::optional<DisplayViewport> getDisplayViewportByType(ViewportType type) const;
std::optional<DisplayViewport> getDisplayViewportByPort(uint8_t displayPort) const;
void addDisplayViewport(DisplayViewport viewport);
- void addDisplayViewport(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
- ui::Rotation orientation, bool isActive, const std::string& uniqueId,
- std::optional<uint8_t> physicalPort, ViewportType type);
bool updateViewport(const DisplayViewport& viewport);
void addExcludedDeviceName(const std::string& deviceName);
void addInputPortAssociation(const std::string& inputPort, uint8_t displayPort);
@@ -86,6 +88,7 @@
void notifyTouchpadHardwareState(const SelfContainedHardwareState& schs,
int32_t deviceId) override;
void notifyTouchpadGestureInfo(GestureType type, int32_t deviceId) override;
+ void notifyTouchpadThreeFingerTap() override;
std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay(
const InputDeviceIdentifier&, const std::optional<KeyboardLayoutInfo>) override;
std::string getDeviceAlias(const InputDeviceIdentifier&) override;
@@ -109,6 +112,9 @@
std::condition_variable mTouchpadHardwareStateNotified;
std::optional<SelfContainedHardwareState> mTouchpadHardwareState GUARDED_BY(mLock){};
+ std::condition_variable mTouchpadThreeFingerTapNotified;
+ bool mTouchpadThreeFingerTapHasBeenReported{false};
+
uint32_t mNextPointerCaptureSequenceNumber{0};
};
diff --git a/services/inputflinger/tests/FakePointerController.cpp b/services/inputflinger/tests/FakePointerController.cpp
index 887a939..f033e57 100644
--- a/services/inputflinger/tests/FakePointerController.cpp
+++ b/services/inputflinger/tests/FakePointerController.cpp
@@ -43,7 +43,7 @@
mY = y;
}
-FloatPoint FakePointerController::getPosition() const {
+vec2 FakePointerController::getPosition() const {
if (!mEnabled) {
return {0, 0};
}
@@ -96,9 +96,9 @@
}
void FakePointerController::assertPosition(float x, float y) {
- const auto [actualX, actualY] = getPosition();
- ASSERT_NEAR(x, actualX, 1);
- ASSERT_NEAR(y, actualY, 1);
+ const auto actual = getPosition();
+ ASSERT_NEAR(x, actual.x, 1);
+ ASSERT_NEAR(y, actual.y, 1);
}
void FakePointerController::assertSpotCount(ui::LogicalDisplayId displayId, int32_t count) {
@@ -148,15 +148,20 @@
return mIsPointerShown;
}
-void FakePointerController::move(float deltaX, float deltaY) {
- if (!mEnabled) return;
+vec2 FakePointerController::move(float deltaX, float deltaY) {
+ if (!mEnabled) return {0, 0};
mX += deltaX;
+ mY += deltaY;
+
+ const vec2 position(mX, mY);
+
if (mX < mMinX) mX = mMinX;
if (mX > mMaxX) mX = mMaxX;
- mY += deltaY;
if (mY < mMinY) mY = mMinY;
if (mY > mMaxY) mY = mMaxY;
+
+ return {position.x - mX, position.y - mY};
}
void FakePointerController::fade(Transition) {
@@ -190,4 +195,8 @@
mSpotsByDisplay.clear();
}
+ui::Transform FakePointerController::getDisplayTransform() const {
+ return ui::Transform();
+}
+
} // namespace android
diff --git a/services/inputflinger/tests/FakePointerController.h b/services/inputflinger/tests/FakePointerController.h
index 9b773a7..c526bb8 100644
--- a/services/inputflinger/tests/FakePointerController.h
+++ b/services/inputflinger/tests/FakePointerController.h
@@ -40,7 +40,7 @@
const std::map<ui::LogicalDisplayId, std::vector<int32_t>>& getSpots();
void setPosition(float x, float y) override;
- FloatPoint getPosition() const override;
+ vec2 getPosition() const override;
ui::LogicalDisplayId getDisplayId() const override;
void setDisplayViewport(const DisplayViewport& viewport) override;
void updatePointerIcon(PointerIconStyle iconId) override;
@@ -48,6 +48,7 @@
void setSkipScreenshotFlagForDisplay(ui::LogicalDisplayId displayId) override;
void clearSkipScreenshotFlags() override;
void fade(Transition) override;
+ ui::Transform getDisplayTransform() const override;
void assertViewportSet(ui::LogicalDisplayId displayId);
void assertViewportNotSet();
@@ -65,7 +66,7 @@
private:
std::string dump() override { return ""; }
- void move(float deltaX, float deltaY) override;
+ vec2 move(float deltaX, float deltaY) override;
void unfade(Transition) override;
void setPresentation(Presentation) override {}
void setSpots(const PointerCoords*, const uint32_t*, BitSet32 spotIdBits,
diff --git a/services/inputflinger/tests/FakeWindows.h b/services/inputflinger/tests/FakeWindows.h
index 3a3238a..54dc25a 100644
--- a/services/inputflinger/tests/FakeWindows.h
+++ b/services/inputflinger/tests/FakeWindows.h
@@ -144,10 +144,6 @@
mInfo.setInputConfig(InputConfig::PAUSE_DISPATCHING, paused);
}
- inline void setPreventSplitting(bool preventSplitting) {
- mInfo.setInputConfig(InputConfig::PREVENT_SPLITTING, preventSplitting);
- }
-
inline void setSlippery(bool slippery) {
mInfo.setInputConfig(InputConfig::SLIPPERY, slippery);
}
diff --git a/services/inputflinger/tests/GestureConverter_test.cpp b/services/inputflinger/tests/GestureConverter_test.cpp
index 225ae0f..914f5ab 100644
--- a/services/inputflinger/tests/GestureConverter_test.cpp
+++ b/services/inputflinger/tests/GestureConverter_test.cpp
@@ -15,11 +15,15 @@
*/
#include <memory>
+#include <tuple>
+#include <android-base/result-gmock.h>
+#include <android-base/result.h>
#include <com_android_input_flags.h>
#include <flag_macros.h>
#include <gestures/GestureConverter.h>
#include <gtest/gtest.h>
+#include <input/InputVerifier.h>
#include "FakeEventHub.h"
#include "FakeInputReaderPolicy.h"
@@ -43,20 +47,24 @@
const auto TOUCHPAD_PALM_REJECTION_V2 =
ACONFIG_FLAG(input_flags, enable_v2_touchpad_typing_palm_rejection);
+constexpr stime_t ARBITRARY_GESTURE_TIME = 1.2;
+constexpr stime_t GESTURE_TIME = ARBITRARY_GESTURE_TIME;
+
} // namespace
+using android::base::testing::Ok;
using testing::AllOf;
using testing::Each;
using testing::ElementsAre;
+using testing::IsEmpty;
using testing::VariantWith;
class GestureConverterTest : public testing::Test {
protected:
static constexpr int32_t DEVICE_ID = END_RESERVED_ID + 1000;
static constexpr int32_t EVENTHUB_ID = 1;
- static constexpr stime_t ARBITRARY_GESTURE_TIME = 1.2;
- void SetUp() {
+ GestureConverterTest() {
mFakeEventHub = std::make_unique<FakeEventHub>();
mFakePolicy = sp<FakeInputReaderPolicy>::make();
mFakeListener = std::make_unique<TestInputListener>();
@@ -849,6 +857,107 @@
WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
}
+TEST_F(GestureConverterTest, DisablingSystemGestures_IgnoresMultiFingerSwipe) {
+ InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
+ GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
+ converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
+
+ std::list<NotifyArgs> args = converter.setEnableSystemGestures(ARBITRARY_TIME, false);
+ ASSERT_THAT(args, IsEmpty());
+
+ Gesture startGesture(kGestureSwipe, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dx=*/0,
+ /*dy=*/10);
+ Gesture continueGesture(kGestureSwipe, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dx=*/0,
+ /*dy=*/5);
+ Gesture liftGesture(kGestureSwipeLift, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME);
+
+ args += converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, startGesture);
+ args += converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, continueGesture);
+ args += converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, liftGesture);
+ ASSERT_THAT(args, IsEmpty());
+
+ args = converter.setEnableSystemGestures(ARBITRARY_TIME, true);
+ ASSERT_THAT(args, IsEmpty());
+
+ args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, startGesture);
+ ASSERT_THAT(args,
+ ElementsAre(VariantWith<NotifyMotionArgs>(
+ WithMotionAction(AMOTION_EVENT_ACTION_DOWN)),
+ VariantWith<NotifyMotionArgs>(WithMotionAction(
+ AMOTION_EVENT_ACTION_POINTER_DOWN |
+ 1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT)),
+ VariantWith<NotifyMotionArgs>(WithMotionAction(
+ AMOTION_EVENT_ACTION_POINTER_DOWN |
+ 2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT)),
+ VariantWith<NotifyMotionArgs>(
+ WithMotionAction(AMOTION_EVENT_ACTION_MOVE))));
+ ASSERT_THAT(args,
+ Each(VariantWith<NotifyMotionArgs>(
+ WithMotionClassification(MotionClassification::MULTI_FINGER_SWIPE))));
+}
+
+TEST_F(GestureConverterTest, DisablingSystemGestures_EndsOngoingMultiFingerSwipe) {
+ InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
+ GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
+ converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
+
+ Gesture startGesture(kGestureSwipe, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dx=*/0,
+ /*dy=*/10);
+ std::list<NotifyArgs> args;
+ args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, startGesture);
+ ASSERT_FALSE(args.empty());
+
+ // Disabling system gestures should end the swipe early.
+ args = converter.setEnableSystemGestures(ARBITRARY_TIME, false);
+ ASSERT_THAT(args,
+ ElementsAre(VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(
+ AMOTION_EVENT_ACTION_POINTER_UP |
+ 2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ WithGestureOffset(0, 0, EPSILON),
+ WithMotionClassification(
+ MotionClassification::MULTI_FINGER_SWIPE),
+ WithPointerCount(3u))),
+ VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(
+ AMOTION_EVENT_ACTION_POINTER_UP |
+ 1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ WithGestureOffset(0, 0, EPSILON),
+ WithMotionClassification(
+ MotionClassification::MULTI_FINGER_SWIPE),
+ WithPointerCount(2u))),
+ VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
+ WithGestureOffset(0, 0, EPSILON),
+ WithMotionClassification(
+ MotionClassification::MULTI_FINGER_SWIPE),
+ WithPointerCount(1u))),
+ VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
+ WithMotionClassification(MotionClassification::NONE)))));
+ ASSERT_THAT(args,
+ Each(VariantWith<NotifyMotionArgs>(
+ AllOf(WithToolType(ToolType::FINGER),
+ WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
+
+ // Further movement in the same swipe should be ignored.
+ Gesture continueGesture(kGestureSwipe, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*dx=*/0,
+ /*dy=*/5);
+ args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, continueGesture);
+ ASSERT_THAT(args, IsEmpty());
+ Gesture liftGesture(kGestureSwipeLift, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME);
+ args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, liftGesture);
+ ASSERT_THAT(args, IsEmpty());
+
+ // But single-finger pointer motion should be reported.
+ Gesture moveGesture(kGestureMove, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, -5, 10);
+ args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, moveGesture);
+ ASSERT_THAT(args,
+ ElementsAre(VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
+ WithRelativeMotion(-5, 10), WithButtonState(0)))));
+}
+
TEST_F(GestureConverterTest, Pinch_Inwards) {
input_flags::enable_touchpad_no_focus_change(true);
@@ -1195,7 +1304,6 @@
TEST_F(GestureConverterTest, FlingTapDownAfterScrollStopsFling) {
InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
- input_flags::enable_touchpad_fling_stop(true);
GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
@@ -1272,6 +1380,27 @@
WithDisplayId(ui::LogicalDisplayId::DEFAULT)))));
}
+TEST_F(GestureConverterTest, ThreeFingerTap_TriggersShortcut) {
+ InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
+ GestureConverter converter(*mReader->getContext(), deviceContext, DEVICE_ID);
+ converter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
+ converter.setThreeFingerTapShortcutEnabled(true);
+
+ Gesture flingGesture(kGestureFling, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME, /*vx=*/0,
+ /*vy=*/0, GESTURES_FLING_TAP_DOWN);
+ std::list<NotifyArgs> args =
+ converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, flingGesture);
+ // We don't need to check args here, since it's covered by the FlingTapDown test.
+
+ Gesture tapGesture(kGestureButtonsChange, ARBITRARY_GESTURE_TIME, ARBITRARY_GESTURE_TIME,
+ /*down=*/GESTURES_BUTTON_MIDDLE, /*up=*/GESTURES_BUTTON_MIDDLE,
+ /*is_tap=*/true);
+ args = converter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, tapGesture);
+
+ ASSERT_TRUE(args.empty());
+ mFakePolicy->assertTouchpadThreeFingerTapNotified();
+}
+
TEST_F(GestureConverterTest, Click) {
// Click should produce button press/release events
InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
@@ -1576,4 +1705,136 @@
WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))));
}
+/**
+ * Tests that the event stream output by the converter remains consistent when converting sequences
+ * of Gestures interleaved with button presses in various ways. Takes tuples of three Gestures: one
+ * that starts the gesture sequence, one that continues it (which may or may not be used in a
+ * particular test case), and one that ends it.
+ */
+class GestureConverterConsistencyTest
+ : public GestureConverterTest,
+ public testing::WithParamInterface<std::tuple<Gesture, Gesture, Gesture>> {
+protected:
+ GestureConverterConsistencyTest()
+ : GestureConverterTest(),
+ mParamStartGesture(std::get<0>(GetParam())),
+ mParamContinueGesture(std::get<1>(GetParam())),
+ mParamEndGesture(std::get<2>(GetParam())),
+ mDeviceContext(*mDevice, EVENTHUB_ID),
+ mConverter(*mReader->getContext(), mDeviceContext, DEVICE_ID) {
+ mConverter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
+ input_flags::enable_button_state_verification(true);
+ mVerifier = std::make_unique<InputVerifier>("Test verifier");
+ }
+
+ base::Result<void> processMotionArgs(NotifyMotionArgs arg) {
+ return mVerifier->processMovement(arg.deviceId, arg.source, arg.action, arg.actionButton,
+ arg.getPointerCount(), arg.pointerProperties.data(),
+ arg.pointerCoords.data(), arg.flags, arg.buttonState);
+ }
+
+ void verifyArgsFromGesture(const Gesture& gesture, size_t gestureIndex) {
+ std::list<NotifyArgs> args =
+ mConverter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, gesture);
+ for (const NotifyArgs& notifyArg : args) {
+ const NotifyMotionArgs& arg = std::get<NotifyMotionArgs>(notifyArg);
+ ASSERT_THAT(processMotionArgs(arg), Ok())
+ << "when processing " << arg.dump() << "\nfrom gesture " << gestureIndex << ": "
+ << gesture.String();
+ }
+ }
+
+ void verifyArgsFromGestures(const std::vector<Gesture>& gestures) {
+ for (size_t i = 0; i < gestures.size(); i++) {
+ ASSERT_NO_FATAL_FAILURE(verifyArgsFromGesture(gestures[i], i));
+ }
+ }
+
+ Gesture mParamStartGesture;
+ Gesture mParamContinueGesture;
+ Gesture mParamEndGesture;
+
+ InputDeviceContext mDeviceContext;
+ GestureConverter mConverter;
+ std::unique_ptr<InputVerifier> mVerifier;
+};
+
+TEST_P(GestureConverterConsistencyTest, ButtonChangesDuringGesture) {
+ verifyArgsFromGestures({
+ mParamStartGesture,
+ Gesture(kGestureButtonsChange, GESTURE_TIME, GESTURE_TIME,
+ /*down=*/GESTURES_BUTTON_LEFT, /*up=*/GESTURES_BUTTON_NONE, /*is_tap=*/false),
+ mParamContinueGesture,
+ Gesture(kGestureButtonsChange, GESTURE_TIME, GESTURE_TIME,
+ /*down=*/GESTURES_BUTTON_NONE, /*up=*/GESTURES_BUTTON_LEFT, /*is_tap=*/false),
+ mParamEndGesture,
+ });
+}
+
+TEST_P(GestureConverterConsistencyTest, ButtonDownDuringGestureAndUpAfterEnd) {
+ verifyArgsFromGestures({
+ mParamStartGesture,
+ Gesture(kGestureButtonsChange, GESTURE_TIME, GESTURE_TIME,
+ /*down=*/GESTURES_BUTTON_LEFT, /*up=*/GESTURES_BUTTON_NONE, /*is_tap=*/false),
+ mParamContinueGesture,
+ mParamEndGesture,
+ Gesture(kGestureButtonsChange, GESTURE_TIME, GESTURE_TIME,
+ /*down=*/GESTURES_BUTTON_NONE, /*up=*/GESTURES_BUTTON_LEFT, /*is_tap=*/false),
+ });
+}
+
+TEST_P(GestureConverterConsistencyTest, GestureStartAndEndDuringButtonDown) {
+ verifyArgsFromGestures({
+ Gesture(kGestureButtonsChange, GESTURE_TIME, GESTURE_TIME,
+ /*down=*/GESTURES_BUTTON_LEFT, /*up=*/GESTURES_BUTTON_NONE, /*is_tap=*/false),
+ mParamStartGesture,
+ mParamContinueGesture,
+ mParamEndGesture,
+ Gesture(kGestureButtonsChange, GESTURE_TIME, GESTURE_TIME,
+ /*down=*/GESTURES_BUTTON_NONE, /*up=*/GESTURES_BUTTON_LEFT, /*is_tap=*/false),
+ });
+}
+
+TEST_P(GestureConverterConsistencyTest, GestureStartsWhileButtonDownAndEndsAfterUp) {
+ verifyArgsFromGestures({
+ Gesture(kGestureButtonsChange, GESTURE_TIME, GESTURE_TIME,
+ /*down=*/GESTURES_BUTTON_LEFT, /*up=*/GESTURES_BUTTON_NONE, /*is_tap=*/false),
+ mParamStartGesture,
+ mParamContinueGesture,
+ Gesture(kGestureButtonsChange, GESTURE_TIME, GESTURE_TIME,
+ /*down=*/GESTURES_BUTTON_NONE, /*up=*/GESTURES_BUTTON_LEFT, /*is_tap=*/false),
+ mParamEndGesture,
+ });
+}
+
+TEST_P(GestureConverterConsistencyTest, TapToClickDuringGesture) {
+ verifyArgsFromGestures({
+ mParamStartGesture,
+ Gesture(kGestureButtonsChange, GESTURE_TIME, GESTURE_TIME,
+ /*down=*/GESTURES_BUTTON_LEFT, /*up=*/GESTURES_BUTTON_LEFT, /*is_tap=*/false),
+ mParamEndGesture,
+ });
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ GestureAndButtonInterleavings, GestureConverterConsistencyTest,
+ testing::Values(
+ std::make_tuple(Gesture(kGestureScroll, GESTURE_TIME, GESTURE_TIME, 0, -10),
+ Gesture(kGestureScroll, GESTURE_TIME, GESTURE_TIME, 0, -5),
+ Gesture(kGestureFling, GESTURE_TIME, GESTURE_TIME, 1, 1,
+ GESTURES_FLING_START)),
+ std::make_tuple(Gesture(kGestureSwipe, GESTURE_TIME, GESTURE_TIME, 0, -10),
+ Gesture(kGestureSwipe, GESTURE_TIME, GESTURE_TIME, 0, 5),
+ Gesture(kGestureSwipeLift, GESTURE_TIME, GESTURE_TIME)),
+ std::make_tuple(Gesture(kGestureFourFingerSwipe, GESTURE_TIME, GESTURE_TIME, 0,
+ -10),
+ Gesture(kGestureFourFingerSwipe, GESTURE_TIME, GESTURE_TIME, 0, 5),
+ Gesture(kGestureFourFingerSwipeLift, GESTURE_TIME, GESTURE_TIME)),
+ std::make_tuple(Gesture(kGesturePinch, GESTURE_TIME, GESTURE_TIME,
+ /*dz=*/1, GESTURES_ZOOM_START),
+ Gesture(kGesturePinch, GESTURE_TIME, GESTURE_TIME,
+ /*dz=*/0.8, GESTURES_ZOOM_UPDATE),
+ Gesture(kGesturePinch, GESTURE_TIME, GESTURE_TIME,
+ /*dz=*/1, GESTURES_ZOOM_END))));
+
} // namespace android
diff --git a/services/inputflinger/tests/HardwareStateConverter_test.cpp b/services/inputflinger/tests/HardwareStateConverter_test.cpp
index 34c81fc..ee125bb 100644
--- a/services/inputflinger/tests/HardwareStateConverter_test.cpp
+++ b/services/inputflinger/tests/HardwareStateConverter_test.cpp
@@ -33,13 +33,6 @@
namespace android {
-namespace {
-
-const auto REPORT_PALMS =
- ACONFIG_FLAG(com::android::input::flags, report_palms_to_gestures_library);
-
-} // namespace
-
class HardwareStateConverterTest : public testing::Test {
public:
HardwareStateConverterTest()
@@ -201,24 +194,7 @@
EXPECT_EQ(0u, finger2.flags);
}
-TEST_F_WITH_FLAGS(HardwareStateConverterTest, OnePalmDisableReportPalms,
- REQUIRES_FLAGS_DISABLED(REPORT_PALMS)) {
- processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_SLOT, 0);
- processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
- processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TRACKING_ID, 123);
- processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_X, 50);
- processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_Y, 100);
-
- processAxis(ARBITRARY_TIME, EV_KEY, BTN_TOUCH, 1);
- processAxis(ARBITRARY_TIME, EV_KEY, BTN_TOOL_FINGER, 1);
- std::optional<SelfContainedHardwareState> schs = processSync(ARBITRARY_TIME);
- ASSERT_TRUE(schs.has_value());
- EXPECT_EQ(0, schs->state.touch_cnt);
- EXPECT_EQ(0, schs->state.finger_cnt);
-}
-
-TEST_F_WITH_FLAGS(HardwareStateConverterTest, OnePalmEnableReportPalms,
- REQUIRES_FLAGS_ENABLED(REPORT_PALMS)) {
+TEST_F(HardwareStateConverterTest, OnePalm) {
processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_SLOT, 0);
processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TRACKING_ID, 123);
@@ -234,54 +210,7 @@
EXPECT_EQ(FingerState::ToolType::kPalm, schs->state.fingers[0].tool_type);
}
-TEST_F_WITH_FLAGS(HardwareStateConverterTest, OneFingerTurningIntoAPalmDisableReportPalms,
- REQUIRES_FLAGS_DISABLED(REPORT_PALMS)) {
- processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_SLOT, 0);
- processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
- processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TRACKING_ID, 123);
- processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_X, 50);
- processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_Y, 100);
-
- processAxis(ARBITRARY_TIME, EV_KEY, BTN_TOUCH, 1);
- processAxis(ARBITRARY_TIME, EV_KEY, BTN_TOOL_FINGER, 1);
-
- std::optional<SelfContainedHardwareState> schs = processSync(ARBITRARY_TIME);
- ASSERT_TRUE(schs.has_value());
- EXPECT_EQ(1, schs->state.touch_cnt);
- EXPECT_EQ(1, schs->state.finger_cnt);
-
- processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
- processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_X, 51);
- processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_Y, 99);
-
- schs = processSync(ARBITRARY_TIME);
- ASSERT_TRUE(schs.has_value());
- EXPECT_EQ(0, schs->state.touch_cnt);
- ASSERT_EQ(0, schs->state.finger_cnt);
-
- processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_X, 53);
- processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_Y, 97);
-
- schs = processSync(ARBITRARY_TIME);
- ASSERT_TRUE(schs.has_value());
- EXPECT_EQ(0, schs->state.touch_cnt);
- EXPECT_EQ(0, schs->state.finger_cnt);
-
- processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
- processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_X, 55);
- processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_POSITION_Y, 95);
- schs = processSync(ARBITRARY_TIME);
- ASSERT_TRUE(schs.has_value());
- EXPECT_EQ(1, schs->state.touch_cnt);
- ASSERT_EQ(1, schs->state.finger_cnt);
- const FingerState& newFinger = schs->state.fingers[0];
- EXPECT_EQ(123, newFinger.tracking_id);
- EXPECT_NEAR(55, newFinger.position_x, EPSILON);
- EXPECT_NEAR(95, newFinger.position_y, EPSILON);
-}
-
-TEST_F_WITH_FLAGS(HardwareStateConverterTest, OneFingerTurningIntoAPalmEnableReportPalms,
- REQUIRES_FLAGS_ENABLED(REPORT_PALMS)) {
+TEST_F(HardwareStateConverterTest, OneFingerTurningIntoAPalmEnableReportPalms) {
processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_SLOT, 0);
processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
processAxis(ARBITRARY_TIME, EV_ABS, ABS_MT_TRACKING_ID, 123);
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 3413caa..2b9b470 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -19,6 +19,7 @@
#include "FakeInputDispatcherPolicy.h"
#include "FakeInputTracingBackend.h"
#include "FakeWindows.h"
+#include "ScopedFlagOverride.h"
#include "TestEventMatchers.h"
#include <NotifyArgsBuilders.h>
@@ -117,8 +118,12 @@
// An arbitrary pid of the gesture monitor window
static constexpr gui::Pid MONITOR_PID{2001};
+static constexpr int32_t FLAG_WINDOW_IS_OBSCURED = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
+static constexpr int32_t FLAG_WINDOW_IS_PARTIALLY_OBSCURED =
+ AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
+
static constexpr int EXPECTED_WALLPAPER_FLAGS =
- AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
+ FLAG_WINDOW_IS_OBSCURED | FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
@@ -134,40 +139,6 @@
return event;
}
-/**
- * Provide a local override for a flag value. The value is restored when the object of this class
- * goes out of scope.
- * This class is not intended to be used directly, because its usage is cumbersome.
- * Instead, a wrapper macro SCOPED_FLAG_OVERRIDE is provided.
- */
-class ScopedFlagOverride {
-public:
- ScopedFlagOverride(std::function<bool()> read, std::function<void(bool)> write, bool value)
- : mInitialValue(read()), mWriteValue(write) {
- mWriteValue(value);
- }
- ~ScopedFlagOverride() { mWriteValue(mInitialValue); }
-
-private:
- const bool mInitialValue;
- std::function<void(bool)> mWriteValue;
-};
-
-typedef bool (*readFlagValueFunction)();
-typedef void (*writeFlagValueFunction)(bool);
-
-/**
- * Use this macro to locally override a flag value.
- * Example usage:
- * SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
- * Note: this works by creating a local variable in your current scope. Don't call this twice for
- * the same flag, because the variable names will clash!
- */
-#define SCOPED_FLAG_OVERRIDE(NAME, VALUE) \
- readFlagValueFunction read##NAME = com::android::input::flags::NAME; \
- writeFlagValueFunction write##NAME = com::android::input::flags::NAME; \
- ScopedFlagOverride override##NAME(read##NAME, write##NAME, (VALUE))
-
} // namespace
// --- InputDispatcherTest ---
@@ -1211,22 +1182,17 @@
WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
}
-class ShouldSplitTouchFixture : public InputDispatcherTest,
- public ::testing::WithParamInterface<bool> {};
-INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
- ::testing::Values(true, false));
/**
* A single window that receives touch (on top), and a wallpaper window underneath it.
* The top window gets a multitouch gesture.
* Ensure that wallpaper gets the same gesture.
*/
-TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
+TEST_F(InputDispatcherTest, WallpaperWindowReceivesMultiTouch) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> foregroundWindow =
sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
ui::LogicalDisplayId::DEFAULT);
foregroundWindow->setDupTouchToWallpaper(true);
- foregroundWindow->setPreventSplitting(GetParam());
sp<FakeWindowHandle> wallpaperWindow =
sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
@@ -1571,6 +1537,60 @@
window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
}
+// Still send inject motion events to window which already be touched.
+TEST_F(InputDispatcherTest, AlwaysDispatchInjectMotionEventWhenAlreadyDownForWindow) {
+ std::shared_ptr<FakeApplicationHandle> application1 = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> window1 =
+ sp<FakeWindowHandle>::make(application1, mDispatcher, "window1",
+ ui::LogicalDisplayId::DEFAULT);
+ window1->setFrame(Rect(0, 0, 100, 100));
+ window1->setWatchOutsideTouch(false);
+
+ std::shared_ptr<FakeApplicationHandle> application2 = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> window2 =
+ sp<FakeWindowHandle>::make(application2, mDispatcher, "window2",
+ ui::LogicalDisplayId::DEFAULT);
+ window2->setFrame(Rect(50, 50, 100, 100));
+ window2->setWatchOutsideTouch(true);
+ mDispatcher->onWindowInfosChanged({{*window2->getInfo(), *window1->getInfo()}, {}, 0, 0});
+
+ std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT;
+ InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT;
+ std::optional<gui::Uid> targetUid = {};
+ uint32_t policyFlags = DEFAULT_POLICY_FLAGS;
+
+ const MotionEvent eventDown1 = MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60)).deviceId(-1)
+ .build();
+ injectMotionEvent(*mDispatcher, eventDown1, injectionTimeout, injectionMode, targetUid,
+ policyFlags);
+ window2->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
+
+ const MotionEvent eventUp1 = MotionEventBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60)).deviceId(-1)
+ .downTime(eventDown1.getDownTime()).build();
+ // Inject UP event, without the POLICY_FLAG_PASS_TO_USER (to simulate policy behaviour
+ // when screen is off).
+ injectMotionEvent(*mDispatcher, eventUp1, injectionTimeout, injectionMode, targetUid,
+ /*policyFlags=*/0);
+ window2->consumeMotionEvent(WithMotionAction(ACTION_UP));
+ const MotionEvent eventDown2 = MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40)).deviceId(-1)
+ .build();
+ injectMotionEvent(*mDispatcher, eventDown2, injectionTimeout, injectionMode, targetUid,
+ policyFlags);
+ window1->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
+ window2->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
+
+ const MotionEvent eventUp2 = MotionEventBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60)).deviceId(-1)
+ .downTime(eventDown2.getDownTime()).build();
+ injectMotionEvent(*mDispatcher, eventUp2, injectionTimeout, injectionMode, targetUid,
+ /*policyFlags=*/0);
+ window1->consumeMotionEvent(WithMotionAction(ACTION_UP));
+ window2->assertNoEvents();
+}
+
/**
* Two windows: a window on the left and a window on the right.
* Mouse is hovered from the right window into the left window.
@@ -4256,17 +4276,15 @@
}
/**
- * When events are not split, the downTime should be adjusted such that the downTime corresponds
+ * When events are split, the downTime should be adjusted such that the downTime corresponds
* to the event time of the first ACTION_DOWN. If a new window appears, it should not affect
- * the event routing because the first window prevents splitting.
+ * the event routing unless pointers are delivered to the new window.
*/
TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTimeForNewWindow) {
- SCOPED_FLAG_OVERRIDE(split_all_touches, false);
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window1 =
sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
window1->setTouchableRegion(Region{{0, 0, 100, 100}});
- window1->setPreventSplitting(true);
sp<FakeWindowHandle> window2 =
sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
@@ -4286,13 +4304,18 @@
// Second window is added
mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
- // Now touch down on the window with another pointer
- mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
- .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
- .downTime(downArgs.downTime)
- .build());
- window1->consumeMotionPointerDown(1, AllOf(WithDownTime(downArgs.downTime)));
+ // Now touch down on the new window with another pointer
+ NotifyMotionArgs pointerDownArgs =
+ MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
+ .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
+ .downTime(downArgs.downTime)
+ .build();
+ mDispatcher->notifyMotion(pointerDownArgs);
+ window1->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithPointerCount(1),
+ WithDownTime(downArgs.downTime)));
+ window2->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_DOWN), WithDownTime(pointerDownArgs.eventTime)));
// Finish the gesture
mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
@@ -4300,11 +4323,16 @@
.pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
.downTime(downArgs.downTime)
.build());
+ window1->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_MOVE), WithDownTime(downArgs.downTime)));
+ window2->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_UP), WithDownTime(pointerDownArgs.eventTime)));
+
mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
.pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
.downTime(downArgs.downTime)
.build());
- window1->consumeMotionPointerUp(1, AllOf(WithDownTime(downArgs.downTime)));
+
window1->consumeMotionEvent(
AllOf(WithMotionAction(ACTION_UP), WithDownTime(downArgs.downTime)));
window2->assertNoEvents();
@@ -4313,13 +4341,12 @@
/**
* When splitting touch events, the downTime should be adjusted such that the downTime corresponds
* to the event time of the first ACTION_DOWN sent to the new window.
- * If a new window that does not support split appears on the screen and gets touched with the
- * second finger, it should not get any events because it doesn't want split touches. At the same
- * time, the first window should not get the pointer_down event because it supports split touches
- * (and the touch occurred outside of the bounds of window1).
+ * If a new window appears on the screen and gets touched with the
+ * second finger, it should get the new event. At the same
+ * time, the first window should not get the pointer_down event because
+ * the touch occurred outside of its bounds.
*/
-TEST_F(InputDispatcherTest, SplitTouchesDropsEventForNonSplittableSecondWindow) {
- SCOPED_FLAG_OVERRIDE(split_all_touches, false);
+TEST_F(InputDispatcherTest, SplitTouchesWhenWindowIsAdded) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window1 =
sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
@@ -4341,16 +4368,16 @@
AllOf(WithMotionAction(ACTION_DOWN), WithDownTime(downArgs.downTime)));
// Second window is added
- window2->setPreventSplitting(true);
mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
- // Now touch down on the window with another pointer
+ // Now touch down on the new window with another pointer
mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
.pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
.pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
.downTime(downArgs.downTime)
.build());
- // Event is dropped because window2 doesn't support split touch, and window1 does.
+ window1->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithPointerCount(1)));
+ window2->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
// Complete the gesture
mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
@@ -4361,6 +4388,8 @@
// A redundant MOVE event is generated that doesn't carry any new information
window1->consumeMotionEvent(
AllOf(WithMotionAction(ACTION_MOVE), WithDownTime(downArgs.downTime)));
+ window2->consumeMotionEvent(WithMotionAction(ACTION_UP));
+
mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
.pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
.downTime(downArgs.downTime)
@@ -4580,22 +4609,20 @@
* A spy window sits above a window with NO_INPUT_CHANNEL. Ensure that the spy receives events even
* though the window underneath should not get any events.
*/
-TEST_F(InputDispatcherTest, NonSplittableSpyAboveNoInputChannelWindowSinglePointer) {
+TEST_F(InputDispatcherTest, SpyAboveNoInputChannelWindowSinglePointer) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
ui::LogicalDisplayId::DEFAULT);
spyWindow->setFrame(Rect(0, 0, 100, 100));
spyWindow->setTrustedOverlay(true);
- spyWindow->setPreventSplitting(true);
spyWindow->setSpy(true);
- // Another window below spy that has both NO_INPUT_CHANNEL and PREVENT_SPLITTING
+ // Another window below spy that has NO_INPUT_CHANNEL
sp<FakeWindowHandle> inputSinkWindow =
sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
ui::LogicalDisplayId::DEFAULT);
inputSinkWindow->setFrame(Rect(0, 0, 100, 100));
inputSinkWindow->setTrustedOverlay(true);
- inputSinkWindow->setPreventSplitting(true);
inputSinkWindow->setNoInputChannel(true);
mDispatcher->onWindowInfosChanged(
@@ -4620,22 +4647,20 @@
* though the window underneath should not get any events.
* Same test as above, but with two pointers touching instead of one.
*/
-TEST_F(InputDispatcherTest, NonSplittableSpyAboveNoInputChannelWindowTwoPointers) {
+TEST_F(InputDispatcherTest, SpyAboveNoInputChannelWindowTwoPointers) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
ui::LogicalDisplayId::DEFAULT);
spyWindow->setFrame(Rect(0, 0, 100, 100));
spyWindow->setTrustedOverlay(true);
- spyWindow->setPreventSplitting(true);
spyWindow->setSpy(true);
- // Another window below spy that would have both NO_INPUT_CHANNEL and PREVENT_SPLITTING
+ // Another window below spy that would have NO_INPUT_CHANNEL
sp<FakeWindowHandle> inputSinkWindow =
sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
ui::LogicalDisplayId::DEFAULT);
inputSinkWindow->setFrame(Rect(0, 0, 100, 100));
inputSinkWindow->setTrustedOverlay(true);
- inputSinkWindow->setPreventSplitting(true);
inputSinkWindow->setNoInputChannel(true);
mDispatcher->onWindowInfosChanged(
@@ -4667,15 +4692,10 @@
inputSinkWindow->assertNoEvents();
}
-/** Check the behaviour for cases where input sink prevents or doesn't prevent splitting. */
-class SpyThatPreventsSplittingWithApplicationFixture : public InputDispatcherTest,
- public ::testing::WithParamInterface<bool> {
-};
-
/**
* Three windows:
* - An application window (app window)
- * - A spy window that does not overlap the app window. Has PREVENT_SPLITTING flag
+ * - A spy window that does not overlap the app window.
* - A window below the spy that has NO_INPUT_CHANNEL (call it 'inputSink')
*
* The spy window is side-by-side with the app window. The inputSink is below the spy.
@@ -4683,34 +4703,31 @@
* Only the SPY window should get the DOWN event.
* The spy pilfers after receiving the first DOWN event.
* Next, we touch the app window.
- * The spy should receive POINTER_DOWN(1) (since spy is preventing splits).
- * Also, since the spy is already pilfering the first pointer, it will be sent the remaining new
- * pointers automatically, as well.
+ * The spy should not receive POINTER_DOWN(1) (since the pointer is outside of the spy).
* Next, the first pointer (from the spy) is lifted.
- * Spy should get POINTER_UP(0).
+ * Spy should get ACTION_UP.
* This event should not go to the app because the app never received this pointer to begin with.
- * Now, lift the remaining pointer and check that the spy receives UP event.
+ * However, due to the current implementation, this would still cause an ACTION_MOVE event in the
+ * app.
+ * Now, lift the remaining pointer and check that the app receives UP event.
*
- * Finally, send a new ACTION_DOWN event to the spy and check that it's received.
+ * Finally, send a new ACTION_DOWN event to the spy and check that it gets received.
* This test attempts to reproduce a crash in the dispatcher.
*/
-TEST_P(SpyThatPreventsSplittingWithApplicationFixture, SpyThatPreventsSplittingWithApplication) {
- SCOPED_FLAG_OVERRIDE(split_all_touches, false);
+TEST_F(InputDispatcherTest, SpyThatPilfersAfterFirstPointerWithTwoOtherWindows) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
ui::LogicalDisplayId::DEFAULT);
spyWindow->setFrame(Rect(100, 100, 200, 200));
spyWindow->setTrustedOverlay(true);
- spyWindow->setPreventSplitting(true);
spyWindow->setSpy(true);
- // Another window below spy that has both NO_INPUT_CHANNEL and PREVENT_SPLITTING
+ // Another window below spy that has NO_INPUT_CHANNEL
sp<FakeWindowHandle> inputSinkWindow =
sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
ui::LogicalDisplayId::DEFAULT);
inputSinkWindow->setFrame(Rect(100, 100, 200, 200)); // directly below the spy
inputSinkWindow->setTrustedOverlay(true);
- inputSinkWindow->setPreventSplitting(GetParam());
inputSinkWindow->setNoInputChannel(true);
sp<FakeWindowHandle> appWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "App",
@@ -4732,16 +4749,15 @@
mDispatcher->pilferPointers(spyWindow->getToken());
- // Second finger lands in the app, and goes to the spy window. It doesn't go to the app because
- // the spy is already pilfering the first pointer, and this automatically grants the remaining
- // new pointers to the spy, as well.
+ // Second finger lands in the app. It goes to the app as ACTION_DOWN.
mDispatcher->notifyMotion(
MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
.pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
.pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
.build());
- spyWindow->consumeMotionPointerDown(1, WithPointerCount(2));
+ spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithPointerCount(1)));
+ appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
// Now lift up the first pointer
mDispatcher->notifyMotion(
@@ -4749,14 +4765,15 @@
.pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
.pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
.build());
- spyWindow->consumeMotionPointerUp(0, WithPointerCount(2));
+ spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
+ appWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithPointerCount(1)));
// And lift the remaining pointer!
mDispatcher->notifyMotion(
MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
.pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
.build());
- spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithPointerCount(1)));
+ appWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithPointerCount(1)));
// Now send a new DOWN, which should again go to spy.
mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
@@ -4768,10 +4785,6 @@
appWindow->assertNoEvents();
}
-// Behaviour should be the same regardless of whether inputSink supports splitting.
-INSTANTIATE_TEST_SUITE_P(SpyThatPreventsSplittingWithApplication,
- SpyThatPreventsSplittingWithApplicationFixture, testing::Bool());
-
TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
@@ -5725,14 +5738,12 @@
window->assertNoEvents();
}
-TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
- SCOPED_FLAG_OVERRIDE(split_all_touches, false);
+TEST_F(InputDispatcherTest, WindowDoesNotReceiveSecondPointerOutsideOfItsBounds) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
ui::LogicalDisplayId::DEFAULT);
- // Ensure window is non-split and have some transform.
- window->setPreventSplitting(true);
+ // Ensure window has a non-trivial transform.
window->setWindowOffset(20, 40);
mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
@@ -5740,7 +5751,10 @@
injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
ui::LogicalDisplayId::DEFAULT, {50, 50}))
<< "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
- window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
+ window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
+ WithCoords(70, // 50 + 20
+ 90 // 50 + 40
+ )));
const MotionEvent secondFingerDownEvent =
MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
@@ -5749,45 +5763,32 @@
.pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
.pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
.build();
- ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ ASSERT_EQ(InputEventInjectionResult::FAILED,
injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
InputEventInjectionSync::WAIT_FOR_RESULT))
- << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-
- std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
- ASSERT_NE(nullptr, event);
- EXPECT_EQ(POINTER_1_DOWN, event->getAction());
- EXPECT_EQ(70, event->getX(0)); // 50 + 20
- EXPECT_EQ(90, event->getY(0)); // 50 + 40
- EXPECT_EQ(-10, event->getX(1)); // -30 + 20
- EXPECT_EQ(-10, event->getY(1)); // -50 + 40
+ << "Injection should fail because the second finger is outside of any window on the "
+ "screen.";
}
/**
- * Two windows: a splittable and a non-splittable.
- * The non-splittable window shouldn't receive any "incomplete" gestures.
- * Send the first pointer to the splittable window, and then touch the non-splittable window.
- * The second pointer should be dropped because the initial window is splittable, so it won't get
- * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
- * "incomplete" gestures.
+ * Two windows.
+ * Send the first pointer to the left window, and then touch the right window.
+ * The second pointer should generate an ACTION_DOWN in the right window.
*/
-TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
- SCOPED_FLAG_OVERRIDE(split_all_touches, false);
+TEST_F(InputDispatcherTest, TwoWindowsTwoPointers) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> leftWindow =
- sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
ui::LogicalDisplayId::DEFAULT);
- leftWindow->setPreventSplitting(false);
leftWindow->setFrame(Rect(0, 0, 100, 100));
sp<FakeWindowHandle> rightWindow =
- sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
ui::LogicalDisplayId::DEFAULT);
- rightWindow->setPreventSplitting(true);
rightWindow->setFrame(Rect(100, 100, 200, 200));
mDispatcher->onWindowInfosChanged(
{{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
- // Touch down on left, splittable window
+ // Touch down on left window
mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
.pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
.build());
@@ -5798,8 +5799,8 @@
.pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
.pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
.build());
- leftWindow->assertNoEvents();
- rightWindow->assertNoEvents();
+ leftWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
+ rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
}
/**
@@ -5822,7 +5823,6 @@
sp<FakeWindowHandle>::make(application1, mDispatcher, "wallpaper",
ui::LogicalDisplayId::DEFAULT);
wallpaper->setIsWallpaper(true);
- wallpaper->setPreventSplitting(true);
wallpaper->setTouchable(false);
sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application2, mDispatcher, "Left",
@@ -5956,7 +5956,6 @@
sp<FakeWindowHandle>::make(application1, mDispatcher, "wallpaper",
ui::LogicalDisplayId::DEFAULT);
wallpaper->setIsWallpaper(true);
- wallpaper->setPreventSplitting(true);
wallpaper->setTouchable(false);
sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application2, mDispatcher, "Left",
@@ -6070,20 +6069,18 @@
}
/**
- * Two windows: left and right. The left window has PREVENT_SPLITTING input config. Device A sends a
- * down event to the right window. Device B sends a down event to the left window, and then a
- * POINTER_DOWN event to the right window. However, since the left window prevents splitting, the
- * POINTER_DOWN event should only go to the left window, and not to the right window.
+ * Two windows: left and right. Device A sends a DOWN event to the right window. Device B sends a
+ * DOWN event to the left window, and then a POINTER_DOWN event outside of all windows.
+ * The POINTER_DOWN event should be dropped.
* This test attempts to reproduce a crash.
*/
-TEST_F(InputDispatcherTest, MultiDeviceTwoWindowsPreventSplitting) {
- SCOPED_FLAG_OVERRIDE(split_all_touches, false);
+TEST_F(InputDispatcherTest, MultiDeviceTwoWindowsTwoPointers) {
+ SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> leftWindow =
- sp<FakeWindowHandle>::make(application, mDispatcher, "Left window (prevent splitting)",
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
ui::LogicalDisplayId::DEFAULT);
leftWindow->setFrame(Rect(0, 0, 100, 100));
- leftWindow->setPreventSplitting(true);
sp<FakeWindowHandle> rightWindow =
sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
@@ -6107,14 +6104,14 @@
.deviceId(deviceB)
.build());
leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
- // Send a second pointer from device B to the right window. It shouldn't go to the right window
- // because the left window prevents splitting.
+
+ // Send a second pointer from device B to an area outside of all windows.
mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
.deviceId(deviceB)
.pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
.pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
.build());
- leftWindow->consumeMotionPointerDown(1, WithDeviceId(deviceB));
+ // This is dropped because there's no touchable window at the location (120, 120)
// Finish the gesture for both devices
mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
@@ -6122,7 +6119,8 @@
.pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
.pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
.build());
- leftWindow->consumeMotionPointerUp(1, WithDeviceId(deviceB));
+ leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithPointerId(0, 0)));
+
mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
.pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
.deviceId(deviceB)
@@ -6501,19 +6499,47 @@
ui::LogicalDisplayId::DEFAULT, {PointF{150, 220}}));
firstWindow->assertNoEvents();
- std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
- ASSERT_NE(nullptr, event);
- EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
+ secondWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_DOWN),
+ // Ensure that the events from the "getRaw" API are in logical display
+ // coordinates, which has an x-scale of 2 and y-scale of 4.
+ WithRawCoords(300, 880),
+ // Ensure that the x and y values are in the window's coordinate space.
+ // The left-top of the second window is at (100, 200) in display space, which is
+ // (200, 800) in the logical display space. This will be the origin of the window
+ // space.
+ WithCoords(100, 80)));
+}
- // Ensure that the events from the "getRaw" API are in logical display coordinates.
- EXPECT_EQ(300, event->getRawX(0));
- EXPECT_EQ(880, event->getRawY(0));
+TEST_F(InputDispatcherDisplayProjectionTest, UseCloneLayerStackTransformForRawCoordinates) {
+ SCOPED_FLAG_OVERRIDE(use_cloned_screen_coordinates_as_raw, true);
- // Ensure that the x and y values are in the window's coordinate space.
- // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
- // the logical display space. This will be the origin of the window space.
- EXPECT_EQ(100, event->getX(0));
- EXPECT_EQ(80, event->getY(0));
+ auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
+
+ const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
+ ui::Transform secondDisplayTransform;
+ secondDisplayTransform.set(matrix);
+ addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
+
+ // When a clone layer stack transform is provided for a window, we should use that as the
+ // "display transform" for input going to that window.
+ sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
+ secondWindowClone->editInfo()->cloneLayerStackTransform = ui::Transform();
+ secondWindowClone->editInfo()->cloneLayerStackTransform->set(0.5, 0, 0, 0.25);
+ addWindow(secondWindowClone);
+
+ // Touch down on the clone window, and ensure its raw coordinates use
+ // the clone layer stack transform.
+ mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ SECOND_DISPLAY_ID, {PointF{150, 220}}));
+ secondWindowClone->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_DOWN),
+ // Ensure the x and y coordinates are in the window's coordinate space.
+ // See previous test case for calculation.
+ WithCoords(100, 80),
+ // Ensure the "getRaw" API uses the clone layer stack transform when it is
+ // provided for the window. It has an x-scale of 0.5 and y-scale of 0.25.
+ WithRawCoords(75, 55)));
}
TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
@@ -6949,7 +6975,7 @@
AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
}
-TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
+TEST_P(TransferTouchFixture, TransferTouch_TwoPointers) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
PointF touchPoint = {10, 10};
@@ -6958,11 +6984,9 @@
sp<FakeWindowHandle> firstWindow =
sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
ui::LogicalDisplayId::DEFAULT);
- firstWindow->setPreventSplitting(true);
sp<FakeWindowHandle> secondWindow =
sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
ui::LogicalDisplayId::DEFAULT);
- secondWindow->setPreventSplitting(true);
// Add the windows to the dispatcher
mDispatcher->onWindowInfosChanged(
@@ -8077,6 +8101,17 @@
ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
ASSERT_EQ(0, verifiedKey.repeatCount);
+
+ // InputEvent and subclasses don't have a virtual destructor and only
+ // InputEvent's destructor gets called when `verified` goes out of scope,
+ // even if `verifyInputEvent` returns an object of a subclass. To fix this,
+ // we should either consider using std::variant in some way, or introduce an
+ // intermediate POD data structure that we will put the data into just prior
+ // to signing. Adding virtual functions to these classes is undesirable as
+ // the bytes in these objects are getting signed. As a temporary fix, cast
+ // the pointer to the correct class (which is statically known) before
+ // destruction.
+ delete (VerifiedKeyEvent*)verified.release();
}
TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
@@ -8124,6 +8159,10 @@
EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
+
+ // Cast to the correct type before destruction. See explanation at the end
+ // of the VerifyInputEvent_KeyEvent test.
+ delete (VerifiedMotionEvent*)verified.release();
}
/**
@@ -8819,12 +8858,10 @@
}
/**
- * When a device reports a DOWN event, which lands in a window that supports splits, and then the
- * device then reports a POINTER_DOWN, which lands in the location of a non-existing window, then
- * the previous window should receive this event and not be dropped.
+ * First finger lands into a window, and then the second finger lands in the location of a
+ * non-existent window. The second finger should be dropped.
*/
TEST_F(InputDispatcherMultiDeviceTest, SingleDevicePointerDownEventRetentionWithoutWindowTarget) {
- SCOPED_FLAG_OVERRIDE(split_all_touches, false);
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
ui::LogicalDisplayId::DEFAULT);
@@ -8842,13 +8879,13 @@
.pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
.build());
- window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_1_DOWN)));
+ window->assertNoEvents();
}
/**
* When deviceA reports a DOWN event, which lands in a window that supports splits, and then deviceB
* also reports a DOWN event, which lands in the location of a non-existing window, then the
- * previous window should receive deviceB's event and it should be dropped.
+ * previous window should not receive deviceB's event and it should be dropped.
*/
TEST_F(InputDispatcherMultiDeviceTest, SecondDeviceDownEventDroppedWithoutWindowTarget) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
@@ -9868,6 +9905,15 @@
AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
}
+TEST_F(InputFilterInjectionPolicyTest,
+ MotionEventsInjectedFromAccessibilityTool_HaveAccessibilityFlags) {
+ testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY |
+ POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY_TOOL,
+ /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
+ AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT |
+ AMOTION_EVENT_FLAG_INJECTED_FROM_ACCESSIBILITY_TOOL);
+}
+
TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
/*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
@@ -9878,6 +9924,9 @@
virtual void SetUp() override {
InputDispatcherTest::SetUp();
+ // Use current time as start time otherwise events may be dropped due to being stale.
+ mGestureStartTime = std::chrono::nanoseconds(systemTime(SYSTEM_TIME_MONOTONIC));
+
std::shared_ptr<FakeApplicationHandle> application =
std::make_shared<FakeApplicationHandle>();
application->setDispatchingTimeout(100ms);
@@ -9895,18 +9944,23 @@
mWindow->consumeFocusEvent(true);
}
- void notifyAndConsumeMotion(int32_t action, uint32_t source, ui::LogicalDisplayId displayId,
- nsecs_t eventTime) {
- mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
- .displayId(displayId)
- .eventTime(eventTime)
- .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
- .build());
+ NotifyMotionArgs notifyAndConsumeMotion(int32_t action, uint32_t source,
+ ui::LogicalDisplayId displayId,
+ std::chrono::nanoseconds timeDelay) {
+ const NotifyMotionArgs motionArgs =
+ MotionArgsBuilder(action, source)
+ .displayId(displayId)
+ .eventTime((mGestureStartTime + timeDelay).count())
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
+ .build();
+ mDispatcher->notifyMotion(motionArgs);
mWindow->consumeMotionEvent(WithMotionAction(action));
+ return motionArgs;
}
private:
sp<FakeWindowHandle> mWindow;
+ std::chrono::nanoseconds mGestureStartTime;
};
TEST_F_WITH_FLAGS(
@@ -9916,55 +9970,55 @@
mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
// First event of type TOUCH. Should poke.
- notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
- milliseconds_to_nanoseconds(50));
+ NotifyMotionArgs motionArgs =
+ notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ui::LogicalDisplayId::DEFAULT, std::chrono::milliseconds(50));
mFakePolicy->assertUserActivityPoked(
- {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH,
- ui::LogicalDisplayId::DEFAULT}});
+ {{motionArgs.eventTime, USER_ACTIVITY_EVENT_TOUCH, ui::LogicalDisplayId::DEFAULT}});
// 80ns > 50ns has passed since previous TOUCH event. Should poke.
- notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
- milliseconds_to_nanoseconds(130));
+ motionArgs =
+ notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
+ ui::LogicalDisplayId::DEFAULT, std::chrono::milliseconds(130));
mFakePolicy->assertUserActivityPoked(
- {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH,
- ui::LogicalDisplayId::DEFAULT}});
+ {{motionArgs.eventTime, USER_ACTIVITY_EVENT_TOUCH, ui::LogicalDisplayId::DEFAULT}});
// First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
- notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
- ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(135));
+ motionArgs =
+ notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
+ ui::LogicalDisplayId::DEFAULT, std::chrono::milliseconds(135));
mFakePolicy->assertUserActivityPoked(
- {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER,
- ui::LogicalDisplayId::DEFAULT}});
+ {{motionArgs.eventTime, USER_ACTIVITY_EVENT_OTHER, ui::LogicalDisplayId::DEFAULT}});
// Within 50ns of previous TOUCH event. Should NOT poke.
notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
- milliseconds_to_nanoseconds(140));
+ std::chrono::milliseconds(140));
mFakePolicy->assertUserActivityNotPoked();
// Within 50ns of previous OTHER event. Should NOT poke.
notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
- ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(150));
+ ui::LogicalDisplayId::DEFAULT, std::chrono::milliseconds(150));
mFakePolicy->assertUserActivityNotPoked();
// Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
// Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
- milliseconds_to_nanoseconds(160));
+ std::chrono::milliseconds(160));
mFakePolicy->assertUserActivityNotPoked();
// 65ns > 50ns has passed since previous OTHER event. Should poke.
- notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
- ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(200));
+ motionArgs =
+ notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
+ ui::LogicalDisplayId::DEFAULT, std::chrono::milliseconds(200));
mFakePolicy->assertUserActivityPoked(
- {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER,
- ui::LogicalDisplayId::DEFAULT}});
+ {{motionArgs.eventTime, USER_ACTIVITY_EVENT_OTHER, ui::LogicalDisplayId::DEFAULT}});
// 170ns > 50ns has passed since previous TOUCH event. Should poke.
- notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
- milliseconds_to_nanoseconds(300));
+ motionArgs =
+ notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
+ std::chrono::milliseconds(300));
mFakePolicy->assertUserActivityPoked(
- {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH,
- ui::LogicalDisplayId::DEFAULT}});
+ {{motionArgs.eventTime, USER_ACTIVITY_EVENT_TOUCH, ui::LogicalDisplayId::DEFAULT}});
// Assert that there's no more user activity poke event.
mFakePolicy->assertUserActivityNotPoked();
@@ -9974,21 +10028,21 @@
InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
rate_limit_user_activity_poke_in_dispatcher))) {
- notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
- milliseconds_to_nanoseconds(200));
+ NotifyMotionArgs motionArgs =
+ notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ui::LogicalDisplayId::DEFAULT, std::chrono::milliseconds(200));
mFakePolicy->assertUserActivityPoked(
- {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH,
- ui::LogicalDisplayId::DEFAULT}});
+ {{motionArgs.eventTime, USER_ACTIVITY_EVENT_TOUCH, ui::LogicalDisplayId::DEFAULT}});
notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
- milliseconds_to_nanoseconds(280));
+ std::chrono::milliseconds(280));
mFakePolicy->assertUserActivityNotPoked();
- notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
- milliseconds_to_nanoseconds(340));
+ motionArgs =
+ notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
+ ui::LogicalDisplayId::DEFAULT, std::chrono::milliseconds(340));
mFakePolicy->assertUserActivityPoked(
- {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH,
- ui::LogicalDisplayId::DEFAULT}});
+ {{motionArgs.eventTime, USER_ACTIVITY_EVENT_TOUCH, ui::LogicalDisplayId::DEFAULT}});
}
TEST_F_WITH_FLAGS(
@@ -9998,11 +10052,11 @@
mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
- 20);
+ std::chrono::milliseconds(20));
mFakePolicy->assertUserActivityPoked();
notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
- 30);
+ std::chrono::milliseconds(30));
mFakePolicy->assertUserActivityPoked();
}
@@ -12320,6 +12374,11 @@
sp<FakeWindowHandle> mSecondWindow;
sp<FakeWindowHandle> mDragWindow;
sp<FakeWindowHandle> mSpyWindow;
+
+ std::vector<gui::DisplayInfo> mDisplayInfos;
+
+ std::shared_ptr<FakeApplicationHandle> mSecondApplication;
+ sp<FakeWindowHandle> mWindowOnSecondDisplay;
// Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
static constexpr int32_t MOUSE_POINTER_ID = 1;
@@ -12340,85 +12399,141 @@
mSpyWindow->setTrustedOverlay(true);
mSpyWindow->setFrame(Rect(0, 0, 200, 100));
+ mSecondApplication = std::make_shared<FakeApplicationHandle>();
+ mWindowOnSecondDisplay =
+ sp<FakeWindowHandle>::make(mSecondApplication, mDispatcher,
+ "TestWindowOnSecondDisplay", SECOND_DISPLAY_ID);
+ mWindowOnSecondDisplay->setFrame({0, 0, 100, 100});
+
mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
mDispatcher->onWindowInfosChanged(
- {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
- {},
+ {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo(),
+ *mWindowOnSecondDisplay->getInfo()},
+ mDisplayInfos,
0,
0});
}
- void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
+ void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN,
+ ui::LogicalDisplayId displayId = ui::LogicalDisplayId::DEFAULT) {
+ bool consumeButtonPress = false;
+ const PointF location =
+ displayId == ui::LogicalDisplayId::DEFAULT ? PointF(50, 50) : PointF(50, 450);
switch (fromSource) {
- case AINPUT_SOURCE_TOUCHSCREEN:
+ case AINPUT_SOURCE_TOUCHSCREEN: {
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
- injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
- ui::LogicalDisplayId::DEFAULT, {50, 50}))
+ injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, displayId,
+ location))
<< "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
break;
- case AINPUT_SOURCE_STYLUS:
+ }
+ case AINPUT_SOURCE_STYLUS: {
+ PointerBuilder pointer =
+ PointerBuilder(0, ToolType::STYLUS).x(location.x).y(location.y);
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
injectMotionEvent(*mDispatcher,
MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
AINPUT_SOURCE_STYLUS)
.buttonState(
AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
- .pointer(PointerBuilder(0, ToolType::STYLUS)
- .x(50)
- .y(50))
+ .pointer(pointer)
.build()));
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(*mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
+ AINPUT_SOURCE_STYLUS)
+ .actionButton(
+ AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
+ .buttonState(
+ AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
+ .pointer(pointer)
+ .build()));
+ consumeButtonPress = true;
break;
- case AINPUT_SOURCE_MOUSE:
+ }
+ case AINPUT_SOURCE_MOUSE: {
+ PointerBuilder pointer = PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
+ .x(location.x)
+ .y(location.y);
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
injectMotionEvent(*mDispatcher,
MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
AINPUT_SOURCE_MOUSE)
+ .displayId(displayId)
.buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
- .pointer(PointerBuilder(MOUSE_POINTER_ID,
- ToolType::MOUSE)
- .x(50)
- .y(50))
+ .pointer(pointer)
.build()));
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(*mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
+ AINPUT_SOURCE_MOUSE)
+ .displayId(displayId)
+ .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(pointer)
+ .build()));
+ consumeButtonPress = true;
break;
- default:
+ }
+ default: {
FAIL() << "Source " << fromSource << " doesn't support drag and drop";
+ }
}
// Window should receive motion event.
- mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
- // Spy window should also receive motion event
- mSpyWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
+ sp<FakeWindowHandle>& targetWindow =
+ displayId == ui::LogicalDisplayId::DEFAULT ? mWindow : mWindowOnSecondDisplay;
+ targetWindow->consumeMotionDown(displayId);
+ if (consumeButtonPress) {
+ targetWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
+ }
+
+ // Spy window should also receive motion event if event is on the same display.
+ if (displayId == ui::LogicalDisplayId::DEFAULT) {
+ mSpyWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
+ }
}
// Start performing drag, we will create a drag window and transfer touch to it.
// @param sendDown : if true, send a motion down on first window before perform drag and drop.
// Returns true on success.
- bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
+ bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN,
+ ui::LogicalDisplayId dragStartDisplay = ui::LogicalDisplayId::DEFAULT) {
if (sendDown) {
- injectDown(fromSource);
+ injectDown(fromSource, dragStartDisplay);
}
// The drag window covers the entire display
- mDragWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow",
- ui::LogicalDisplayId::DEFAULT);
+ mDragWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow", dragStartDisplay);
mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
- mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
- *mWindow->getInfo(), *mSecondWindow->getInfo()},
- {},
- 0,
- 0});
+ mDispatcher->onWindowInfosChanged(
+ {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
+ *mSecondWindow->getInfo(), *mWindowOnSecondDisplay->getInfo()},
+ mDisplayInfos,
+ 0,
+ 0});
+
+ sp<FakeWindowHandle>& targetWindow = dragStartDisplay == ui::LogicalDisplayId::DEFAULT
+ ? mWindow
+ : mWindowOnSecondDisplay;
// Transfer touch focus to the drag window
bool transferred =
- mDispatcher->transferTouchGesture(mWindow->getToken(), mDragWindow->getToken(),
+ mDispatcher->transferTouchGesture(targetWindow->getToken(), mDragWindow->getToken(),
/*isDragDrop=*/true);
if (transferred) {
- mWindow->consumeMotionCancel();
- mDragWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
- AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+ targetWindow->consumeMotionCancel(dragStartDisplay);
+ mDragWindow->consumeMotionDown(dragStartDisplay, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
}
return transferred;
}
+
+ void addDisplay(ui::LogicalDisplayId displayId, ui::Transform transform) {
+ gui::DisplayInfo displayInfo;
+ displayInfo.displayId = displayId;
+ displayInfo.transform = transform;
+ mDisplayInfos.push_back(displayInfo);
+ }
};
TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
@@ -12585,6 +12700,16 @@
// Move to another window and release button, expect to drop item.
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
injectMotionEvent(*mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
+ AINPUT_SOURCE_STYLUS)
+ .actionButton(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
+ .buttonState(0)
+ .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
+ .build()))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ mDragWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(*mDispatcher,
MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
.buttonState(0)
.pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
@@ -12649,9 +12774,6 @@
}
TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
- // Ensure window could track pointerIds if it didn't support split touch.
- mWindow->setPreventSplitting(true);
-
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
ui::LogicalDisplayId::DEFAULT, {50, 50}))
@@ -12829,6 +12951,18 @@
// drop to another window.
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
injectMotionEvent(*mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
+ AINPUT_SOURCE_MOUSE)
+ .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
+ .buttonState(0)
+ .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
+ .x(150)
+ .y(50))
+ .build()))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ mDragWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(*mDispatcher,
MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
.buttonState(0)
.pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
@@ -13551,14 +13685,10 @@
}
/**
- * The spy window should not be able to affect whether or not touches are split. Only the foreground
- * windows should be allowed to control split touch.
+ * The spy window should not be able to affect whether or not touches are split.
*/
TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
- // This spy window prevents touch splitting. However, we still expect to split touches
- // because a foreground window has not disabled splitting.
auto spy = createSpy();
- spy->setPreventSplitting(true);
auto window = createForeground();
window->setFrame(Rect(0, 0, 100, 100));
@@ -14684,4 +14814,636 @@
mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
}
+class InputDispatcherObscuredFlagTest : public InputDispatcherTest {
+protected:
+ std::shared_ptr<FakeApplicationHandle> mApplication;
+ std::shared_ptr<FakeApplicationHandle> mOcclusionApplication;
+ sp<FakeWindowHandle> mWindow;
+ sp<FakeWindowHandle> mOcclusionWindow;
+
+ void SetUp() override {
+ InputDispatcherTest::SetUp();
+ mDispatcher->setMaximumObscuringOpacityForTouch(0.8f);
+ mApplication = std::make_shared<FakeApplicationHandle>();
+ mOcclusionApplication = std::make_shared<FakeApplicationHandle>();
+ mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Window", DISPLAY_ID);
+ mWindow->setOwnerInfo(WINDOW_PID, WINDOW_UID);
+
+ mOcclusionWindow = sp<FakeWindowHandle>::make(mOcclusionApplication, mDispatcher,
+ "Occlusion Window", DISPLAY_ID);
+
+ mOcclusionWindow->setTouchable(false);
+ mOcclusionWindow->setTouchOcclusionMode(TouchOcclusionMode::USE_OPACITY);
+ mOcclusionWindow->setAlpha(0.7f);
+ mOcclusionWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
+ }
+};
+
+/**
+ * Two windows. An untouchable window partially occludes a touchable region below it.
+ * Use a finger to touch the bottom window.
+ * When the finger touches down in the obscured area, the motion event should always have the
+ * FLAG_WINDOW_IS_OBSCURED flag, regardless of where it is moved to. If it starts from a
+ * non-obscured area, the motion event should always with a FLAG_WINDOW_IS_PARTIALLY_OBSCURED flag,
+ * regardless of where it is moved to.
+ */
+TEST_F(InputDispatcherObscuredFlagTest, TouchObscuredTest) {
+ mWindow->setFrame({0, 0, 100, 100});
+ mOcclusionWindow->setFrame({0, 0, 100, 50});
+
+ mDispatcher->onWindowInfosChanged(
+ {{*mOcclusionWindow->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
+
+ // If the finger touch goes down in the region that is obscured.
+ // Expect the entire stream to use FLAG_WINDOW_IS_OBSCURED.
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(10))
+ .build());
+
+ mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
+ WithFlags(FLAG_WINDOW_IS_OBSCURED),
+ WithDisplayId(DISPLAY_ID)));
+
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(60))
+ .build());
+
+ mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
+ WithFlags(FLAG_WINDOW_IS_OBSCURED),
+ WithDisplayId(DISPLAY_ID)));
+
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(110))
+ .build());
+
+ mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP),
+ WithFlags(FLAG_WINDOW_IS_OBSCURED),
+ WithDisplayId(DISPLAY_ID)));
+}
+
+/**
+ * Two windows. An untouchable window partially occludes a touchable region below it.
+ * Use a finger to touch the bottom window.
+ * When the finger starts from a non-obscured area, the motion event should always have the
+ * FLAG_WINDOW_IS_PARTIALLY_OBSCURED flag, regardless of where it is moved to.
+ */
+TEST_F(InputDispatcherObscuredFlagTest, TouchPartiallyObscuredTest) {
+ mWindow->setFrame({0, 0, 100, 100});
+ mOcclusionWindow->setFrame({0, 0, 100, 50});
+
+ mDispatcher->onWindowInfosChanged(
+ {{*mOcclusionWindow->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
+
+ // If the finger touch goes down in the region that is not directly obscured by the overlay.
+ // Expect the entire stream to use FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(60))
+ .build());
+
+ mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
+ WithFlags(FLAG_WINDOW_IS_PARTIALLY_OBSCURED),
+ WithDisplayId(DISPLAY_ID)));
+
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(80))
+ .build());
+
+ mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
+ WithFlags(FLAG_WINDOW_IS_PARTIALLY_OBSCURED),
+ WithDisplayId(DISPLAY_ID)));
+
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(110))
+ .build());
+
+ mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP),
+ WithFlags(FLAG_WINDOW_IS_PARTIALLY_OBSCURED),
+ WithDisplayId(DISPLAY_ID)));
+}
+
+/**
+ * Two windows. An untouchable window partially occludes a touchable region below it.
+ * Use the mouse to hover over the bottom window.
+ * When the hover happens over the occluded area, the window below should receive a motion
+ * event with the FLAG_WINDOW_IS_OBSCURED flag. When the hover event moves to the non-occluded area,
+ * the window below should receive a motion event with the FLAG_WINDOW_IS_PARTIALLY_OBSCURED flag.
+ */
+TEST_F(InputDispatcherObscuredFlagTest, MouseHoverObscuredTest) {
+ mWindow->setFrame({0, 0, 100, 100});
+ mOcclusionWindow->setFrame({0, 0, 100, 40});
+
+ mDispatcher->onWindowInfosChanged(
+ {{*mOcclusionWindow->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
+
+ // TODO(b/328160937): The window should receive a motion event with the FLAG_WINDOW_IS_OBSCURED
+ // flag.
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(20))
+ .build());
+ mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithFlags(0)));
+
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(30))
+ .build());
+ mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithFlags(0)));
+
+ // TODO(b/328160937): The window should receive a motion event with the
+ // FLAG_WINDOW_IS_PARTIALLY_OBSCURED flag.
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
+ .build());
+ mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithFlags(0)));
+
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(60))
+ .build());
+ mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithFlags(0)));
+
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(110))
+ .build());
+
+ // TODO(b/328160937): The window should receive a HOVER_EXIT with the
+ // FLAG_WINDOW_IS_PARTIALLY_OBSCURED flag. The cause of the current issue is that we moved the
+ // mouse to a location where there are no windows, so the HOVER_EXIT event cannot be generated.
+ mWindow->assertNoEvents();
+}
+
+/**
+ * Two windows. An untouchable window partially occludes a touchable region below it.
+ * Use the stylus to hover over the bottom window.
+ * When the hover happens over the occluded area, the window below should receive a motion
+ * event with the FLAG_WINDOW_IS_OBSCURED flag. When the hover event moves to the non-occluded area,
+ * the window below should receive a motion event with the FLAG_WINDOW_IS_PARTIALLY_OBSCURED flag.
+ */
+TEST_F(InputDispatcherObscuredFlagTest, StylusHoverObscuredTest) {
+ mWindow->setFrame({0, 0, 100, 100});
+ mOcclusionWindow->setFrame({0, 0, 100, 40});
+
+ mDispatcher->onWindowInfosChanged(
+ {{*mOcclusionWindow->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
+
+ // TODO(b/328160937): The window should receive a motion event with the FLAG_WINDOW_IS_OBSCURED
+ // flag.
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(20))
+ .build());
+ mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithFlags(0)));
+
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(30))
+ .build());
+ mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithFlags(0)));
+
+ // TODO(b/328160937): The window should receive a motion event with the
+ // FLAG_WINDOW_IS_PARTIALLY_OBSCURED flag.
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
+ .build());
+ mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithFlags(0)));
+
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(60))
+ .build());
+ mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithFlags(0)));
+
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(70))
+ .build());
+ mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithFlags(0)));
+}
+
+class TransferOrDontTransferFixture : public InputDispatcherTest,
+ public ::testing::WithParamInterface<bool> {
+public:
+ void SetUp() override {
+ InputDispatcherTest::SetUp();
+
+ std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
+ mFromWindow =
+ sp<FakeWindowHandle>::make(app, mDispatcher, "From", ui::LogicalDisplayId::DEFAULT);
+ mToWindow =
+ sp<FakeWindowHandle>::make(app, mDispatcher, "To", ui::LogicalDisplayId::DEFAULT);
+
+ mDispatcher->onWindowInfosChanged(
+ {{*mFromWindow->getInfo(), *mToWindow->getInfo()}, {}, 0, 0});
+ }
+
+protected:
+ sp<FakeWindowHandle> mFromWindow;
+ sp<FakeWindowHandle> mToWindow;
+};
+
+// Start a touch gesture and then continue hovering the mouse at the same time.
+// After the mouse is hovering, invoke transferTouch API. Check the events that
+// are received by each of the windows.
+TEST_P(TransferOrDontTransferFixture, TouchDownAndMouseHover) {
+ SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
+
+ const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
+ const int32_t mouseDeviceId = 6;
+ const int32_t touchDeviceId = 4;
+
+ // Send touch down to the first window
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .downTime(baseTime + 10)
+ .eventTime(baseTime + 10)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
+ .build());
+ mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
+
+ // Send touch move to the first window
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .downTime(baseTime + 10)
+ .eventTime(baseTime + 20)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(100))
+ .build());
+ mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
+
+ // Start mouse hover on the first window
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
+ .deviceId(mouseDeviceId)
+ .downTime(baseTime + 30)
+ .eventTime(baseTime + 30)
+ .pointer(PointerBuilder(0, ToolType::MOUSE).x(200).y(200))
+ .build());
+
+ mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
+ mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
+
+ if (GetParam()) {
+ // Call transferTouchGesture
+ const bool transferred =
+ mDispatcher->transferTouchGesture(mFromWindow->getToken(), mToWindow->getToken());
+ ASSERT_TRUE(transferred);
+
+ mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
+ // b/382473355: For some reason, mToWindow also receives HOVER_EXIT first
+ mToWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
+ mToWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
+
+ // Further touch events should be delivered to mTowindow (?)
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .downTime(baseTime + 10)
+ .eventTime(baseTime + 40)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(120).y(100))
+ .build());
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .downTime(baseTime + 10)
+ .eventTime(baseTime + 50)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(120).y(100))
+ .build());
+ // b/382473355: Even though the window got ACTION_DOWN, it's no longer receiving the
+ // remainder of the touch gesture.
+
+ mFromWindow->assertNoEvents();
+ mToWindow->assertNoEvents();
+ } else {
+ // Don't call transferTouchGesture
+
+ // Further touch events should be dropped
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .downTime(baseTime + 10)
+ .eventTime(baseTime + 40)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(120).y(100))
+ .build());
+ mFromWindow->assertNoEvents();
+ mToWindow->assertNoEvents();
+ }
+}
+
+TEST_P(TransferOrDontTransferFixture, MouseAndTouchTransferSimultaneousMultiDevice) {
+ SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
+
+ const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
+ const int32_t mouseDeviceId = 6;
+ const int32_t touchDeviceId = 4;
+
+ // Send touch down to the 'From' window
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .downTime(baseTime + 10)
+ .eventTime(baseTime + 10)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
+ .build());
+ mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
+
+ // Send touch move to the 'From' window
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .downTime(baseTime + 10)
+ .eventTime(baseTime + 20)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(100))
+ .build());
+ mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
+
+ // Start mouse hover on the 'From' window
+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
+ .deviceId(mouseDeviceId)
+ .downTime(baseTime + 30)
+ .eventTime(baseTime + 30)
+ .pointer(PointerBuilder(0, ToolType::MOUSE).x(200).y(200))
+ .build());
+
+ mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
+
+ if (GetParam()) {
+ // Call transferTouchGesture
+ const bool transferred =
+ mDispatcher->transferTouchGesture(mFromWindow->getToken(), mToWindow->getToken());
+ ASSERT_TRUE(transferred);
+ mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
+ mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
+ mToWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
+
+ // Further touch events should be delivered to mToWindow
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .downTime(baseTime + 10)
+ .eventTime(baseTime + 40)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(120).y(100))
+ .build());
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .downTime(baseTime + 10)
+ .eventTime(baseTime + 50)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(120).y(100))
+ .build());
+ // b/382473355: Even though the window got ACTION_DOWN, it's receiving another DOWN!
+ mToWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
+ mToWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
+ mToWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
+
+ mFromWindow->assertNoEvents();
+ mToWindow->assertNoEvents();
+ } else {
+ // Don't call transferTouchGesture
+
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
+ .deviceId(touchDeviceId)
+ .downTime(baseTime + 10)
+ .eventTime(baseTime + 40)
+ .pointer(PointerBuilder(0, ToolType::FINGER).x(120).y(100))
+ .build());
+ mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
+ mFromWindow->assertNoEvents();
+ mToWindow->assertNoEvents();
+ }
+}
+
+INSTANTIATE_TEST_SUITE_P(WithAndWithoutTransfer, TransferOrDontTransferFixture, testing::Bool());
+
+class InputDispatcherConnectedDisplayTest : public InputDispatcherDragTests {
+ constexpr static int DENSITY_MEDIUM = 160;
+
+ const DisplayTopologyGraph
+ mTopology{.primaryDisplayId = DISPLAY_ID,
+ .graph = {{DISPLAY_ID,
+ {{SECOND_DISPLAY_ID, DisplayTopologyPosition::TOP, 0.0f}}},
+ {SECOND_DISPLAY_ID,
+ {{DISPLAY_ID, DisplayTopologyPosition::BOTTOM, 0.0f}}}},
+ .displaysDensity = {{DISPLAY_ID, DENSITY_MEDIUM},
+ {SECOND_DISPLAY_ID, DENSITY_MEDIUM}}};
+
+protected:
+ void SetUp() override {
+ addDisplay(DISPLAY_ID, ui::Transform());
+ addDisplay(SECOND_DISPLAY_ID,
+ ui::Transform(ui::Transform::ROT_270, /*logicalDisplayWidth=*/
+ 500, /*logicalDisplayHeight=*/500));
+
+ InputDispatcherDragTests::SetUp();
+
+ mDispatcher->setDisplayTopology(mTopology);
+ }
+};
+
+TEST_F(InputDispatcherConnectedDisplayTest, MultiDisplayMouseGesture) {
+ SCOPED_FLAG_OVERRIDE(connected_displays_cursor, true);
+
+ // pointer-down
+ mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
+ .displayId(DISPLAY_ID)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(0, ToolType::MOUSE).x(60).y(60))
+ .build());
+ mWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(DISPLAY_ID), WithRawCoords(60, 60)));
+
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
+ .displayId(DISPLAY_ID)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(0, ToolType::MOUSE).x(60).y(60))
+ .build());
+ mWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
+ WithDisplayId(DISPLAY_ID), WithRawCoords(60, 60)));
+
+ // pointer-move
+ mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
+ .displayId(DISPLAY_ID)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(0, ToolType::MOUSE).x(60).y(60))
+ .build());
+ mWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
+ WithDisplayId(DISPLAY_ID), WithRawCoords(60, 60)));
+
+ // pointer-move with different display
+ // TODO (b/383092013): by default windows will not be topology aware and receive events as it
+ // was in the same display. This behaviour has not been implemented yet.
+ mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
+ .displayId(SECOND_DISPLAY_ID)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(0, ToolType::MOUSE).x(70).y(70))
+ .build());
+ // events should be delivered with the second displayId and in corrosponding coordinate space
+ mWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
+ WithDisplayId(SECOND_DISPLAY_ID), WithRawCoords(70, 430)));
+
+ // pointer-up
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE, AINPUT_SOURCE_MOUSE)
+ .displayId(SECOND_DISPLAY_ID)
+ .buttonState(0)
+ .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(0, ToolType::MOUSE).x(70).y(70))
+ .build());
+ mWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
+ WithDisplayId(SECOND_DISPLAY_ID), WithRawCoords(70, 430)));
+
+ mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
+ .displayId(SECOND_DISPLAY_ID)
+ .buttonState(0)
+ .pointer(PointerBuilder(0, ToolType::MOUSE).x(70).y(70))
+ .build());
+ mWindow->consumeMotionUp(SECOND_DISPLAY_ID);
+}
+
+TEST_F(InputDispatcherConnectedDisplayTest, MultiDisplayMouseDragAndDropFromPrimaryDisplay) {
+ SCOPED_FLAG_OVERRIDE(connected_displays_cursor, true);
+
+ EXPECT_TRUE(startDrag(true, AINPUT_SOURCE_MOUSE));
+ // Move on window.
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
+ .displayId(DISPLAY_ID)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE).x(50).y(50))
+ .build());
+ mDragWindow->consumeMotionMove(DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+ mWindow->consumeDragEvent(false, 50, 50);
+ mSecondWindow->assertNoEvents();
+ mWindowOnSecondDisplay->assertNoEvents();
+
+ // Move to another window.
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
+ .displayId(DISPLAY_ID)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE).x(150).y(50))
+ .build());
+ mDragWindow->consumeMotionMove(DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+ mWindow->consumeDragEvent(true, 150, 50);
+ mSecondWindow->consumeDragEvent(false, 50, 50);
+ mWindowOnSecondDisplay->assertNoEvents();
+
+ // Move to window on the second display
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
+ .displayId(SECOND_DISPLAY_ID)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE).x(50).y(50))
+ .build());
+ mDragWindow->consumeMotionMove(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+ mWindow->assertNoEvents();
+ mSecondWindow->consumeDragEvent(true, -50, 50);
+ mWindowOnSecondDisplay->consumeDragEvent(false, 50, 50);
+
+ // drop on the second display
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
+ .displayId(SECOND_DISPLAY_ID)
+ .buttonState(0)
+ .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE).x(50).y(50))
+ .build());
+ mDragWindow->consumeMotionUp(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+ mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindowOnSecondDisplay->getToken());
+ mWindow->assertNoEvents();
+ mSecondWindow->assertNoEvents();
+ mWindowOnSecondDisplay->assertNoEvents();
+}
+
+TEST_F(InputDispatcherConnectedDisplayTest, MultiDisplayMouseDragAndDropFromNonPrimaryDisplay) {
+ SCOPED_FLAG_OVERRIDE(connected_displays_cursor, true);
+
+ EXPECT_TRUE(startDrag(true, AINPUT_SOURCE_MOUSE, SECOND_DISPLAY_ID));
+ // Move on window.
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
+ .displayId(SECOND_DISPLAY_ID)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE).x(50).y(50))
+ .build());
+ mDragWindow->consumeMotionMove(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+ mWindow->assertNoEvents();
+ mSecondWindow->assertNoEvents();
+ mWindowOnSecondDisplay->consumeDragEvent(false, 50, 50);
+
+ // Move to window on the primary display
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
+ .displayId(DISPLAY_ID)
+ .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
+ .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE).x(50).y(50))
+ .build());
+ mDragWindow->consumeMotionMove(DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+ mWindow->consumeDragEvent(false, 50, 50);
+ mSecondWindow->assertNoEvents();
+ mWindowOnSecondDisplay->consumeDragEvent(true, 50, 50);
+
+ // drop on the primary display
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
+ .displayId(DISPLAY_ID)
+ .buttonState(0)
+ .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE).x(50).y(50))
+ .build());
+ mDragWindow->consumeMotionUp(DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+ mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
+ mWindow->assertNoEvents();
+ mSecondWindow->assertNoEvents();
+ mWindowOnSecondDisplay->assertNoEvents();
+}
+
+using InputDispatcherConnectedDisplayPointerInWindowTest = InputDispatcherConnectedDisplayTest;
+
+TEST_F(InputDispatcherConnectedDisplayPointerInWindowTest, MouseOnWindowOnPrimaryDisplay) {
+ SCOPED_FLAG_OVERRIDE(connected_displays_cursor, true);
+
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
+ .build());
+
+ mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
+ mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
+ mWindowOnSecondDisplay->assertNoEvents();
+
+ ASSERT_TRUE(mDispatcher->isPointerInWindow(mWindow->getToken(), DISPLAY_ID, DEVICE_ID,
+ /*pointerId=*/0));
+ ASSERT_TRUE(mDispatcher->isPointerInWindow(mSpyWindow->getToken(), DISPLAY_ID, DEVICE_ID,
+ /*pointerId=*/0));
+ ASSERT_FALSE(mDispatcher->isPointerInWindow(mWindowOnSecondDisplay->getToken(),
+ SECOND_DISPLAY_ID, DEVICE_ID, /*pointerId=*/0));
+}
+
+TEST_F(InputDispatcherConnectedDisplayPointerInWindowTest, MouseOnWindowOnNonPrimaryDisplay) {
+ SCOPED_FLAG_OVERRIDE(connected_displays_cursor, true);
+
+ mDispatcher->notifyMotion(
+ MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
+ .displayId(SECOND_DISPLAY_ID)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
+ .build());
+
+ mWindow->assertNoEvents();
+ mSpyWindow->assertNoEvents();
+ mWindowOnSecondDisplay->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
+
+ ASSERT_FALSE(mDispatcher->isPointerInWindow(mWindow->getToken(), DISPLAY_ID, DEVICE_ID,
+ /*pointerId=*/0));
+ ASSERT_FALSE(mDispatcher->isPointerInWindow(mSpyWindow->getToken(), DISPLAY_ID, DEVICE_ID,
+ /*pointerId=*/0));
+ ASSERT_TRUE(mDispatcher->isPointerInWindow(mWindowOnSecondDisplay->getToken(),
+ SECOND_DISPLAY_ID, DEVICE_ID, /*pointerId=*/0));
+}
+
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/tests/InputMapperTest.cpp b/services/inputflinger/tests/InputMapperTest.cpp
index 7dff144..652a658 100644
--- a/services/inputflinger/tests/InputMapperTest.cpp
+++ b/services/inputflinger/tests/InputMapperTest.cpp
@@ -30,7 +30,7 @@
using testing::Return;
using testing::ReturnRef;
-void InputMapperUnitTest::SetUpWithBus(int bus) {
+void InputMapperUnitTest::SetUp(int bus, bool isExternal) {
mFakePolicy = sp<FakeInputReaderPolicy>::make();
EXPECT_CALL(mMockInputReaderContext, getPolicy()).WillRepeatedly(Return(mFakePolicy.get()));
@@ -46,20 +46,21 @@
return mPropertyMap;
});
- mDevice = std::make_unique<NiceMock<MockInputDevice>>(&mMockInputReaderContext, DEVICE_ID,
- /*generation=*/2, mIdentifier);
+ mDevice =
+ std::make_unique<NiceMock<MockInputDevice>>(&mMockInputReaderContext, DEVICE_ID,
+ /*generation=*/2, mIdentifier, isExternal);
ON_CALL((*mDevice), getConfiguration).WillByDefault(ReturnRef(mPropertyMap));
mDeviceContext = std::make_unique<InputDeviceContext>(*mDevice, EVENTHUB_ID);
}
void InputMapperUnitTest::setupAxis(int axis, bool valid, int32_t min, int32_t max,
- int32_t resolution) {
+ int32_t resolution, int32_t flat, int32_t fuzz) {
EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis))
.WillRepeatedly(Return(valid ? std::optional<RawAbsoluteAxisInfo>{{
.minValue = min,
.maxValue = max,
- .flat = 0,
- .fuzz = 0,
+ .flat = flat,
+ .fuzz = fuzz,
.resolution = resolution,
}}
: std::nullopt));
@@ -100,9 +101,14 @@
std::list<NotifyArgs> InputMapperUnitTest::process(nsecs_t when, int32_t type, int32_t code,
int32_t value) {
+ return process(when, when, type, code, value);
+}
+
+std::list<NotifyArgs> InputMapperUnitTest::process(nsecs_t when, nsecs_t readTime, int32_t type,
+ int32_t code, int32_t value) {
RawEvent event;
event.when = when;
- event.readTime = when;
+ event.readTime = readTime;
event.deviceId = mMapper->getDeviceContext().getEventHubId();
event.type = type;
event.code = code;
@@ -180,8 +186,10 @@
const std::string& uniqueId,
std::optional<uint8_t> physicalPort,
ViewportType viewportType) {
- mFakePolicy->addDisplayViewport(displayId, width, height, orientation, /* isActive= */ true,
- uniqueId, physicalPort, viewportType);
+ DisplayViewport viewport =
+ createViewport(displayId, width, height, orientation, /* isActive= */ true, uniqueId,
+ physicalPort, viewportType);
+ mFakePolicy->addDisplayViewport(viewport);
configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
}
diff --git a/services/inputflinger/tests/InputMapperTest.h b/services/inputflinger/tests/InputMapperTest.h
index fc27e4f..edc87a3 100644
--- a/services/inputflinger/tests/InputMapperTest.h
+++ b/services/inputflinger/tests/InputMapperTest.h
@@ -40,10 +40,11 @@
protected:
static constexpr int32_t EVENTHUB_ID = 1;
static constexpr int32_t DEVICE_ID = END_RESERVED_ID + 1000;
- virtual void SetUp() override { SetUpWithBus(0); }
- virtual void SetUpWithBus(int bus);
+ virtual void SetUp() override { SetUp(/*bus=*/0, /*isExternal=*/false); }
+ virtual void SetUp(int bus, bool isExternal);
- void setupAxis(int axis, bool valid, int32_t min, int32_t max, int32_t resolution);
+ void setupAxis(int axis, bool valid, int32_t min, int32_t max, int32_t resolution,
+ int32_t flat = 0, int32_t fuzz = 0);
void expectScanCodes(bool present, std::set<int> scanCodes);
@@ -55,6 +56,8 @@
std::list<NotifyArgs> process(int32_t type, int32_t code, int32_t value);
std::list<NotifyArgs> process(nsecs_t when, int32_t type, int32_t code, int32_t value);
+ std::list<NotifyArgs> process(nsecs_t when, nsecs_t readTime, int32_t type, int32_t code,
+ int32_t value);
InputDeviceIdentifier mIdentifier;
MockEventHubInterface mMockEventHub;
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 6c8b65c..43d2378 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -28,7 +28,7 @@
#include <MultiTouchInputMapper.h>
#include <NotifyArgsBuilders.h>
#include <PeripheralController.h>
-#include <SensorInputMapper.h>
+#include <ScopedFlagOverride.h>
#include <SingleTouchInputMapper.h>
#include <TestEventMatchers.h>
#include <TestInputListener.h>
@@ -36,6 +36,7 @@
#include <UinputDevice.h>
#include <android-base/thread_annotations.h>
#include <com_android_input_flags.h>
+#include <flag_macros.h>
#include <ftl/enum.h>
#include <gtest/gtest.h>
#include <ui/Rotation.h>
@@ -384,30 +385,29 @@
static const std::string uniqueId = "local:0";
// We didn't add any viewports yet, so there shouldn't be any.
- std::optional<DisplayViewport> internalViewport =
- mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
- ASSERT_FALSE(internalViewport);
+ ASSERT_FALSE(mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL));
// Add an internal viewport, then clear it
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, uniqueId, NO_PORT, ViewportType::INTERNAL);
-
+ DisplayViewport internalViewport =
+ createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, uniqueId, NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(internalViewport);
// Check matching by uniqueId
- internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
- ASSERT_TRUE(internalViewport);
- ASSERT_EQ(ViewportType::INTERNAL, internalViewport->type);
+ std::optional<DisplayViewport> receivedInternalViewport =
+ mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
+ ASSERT_TRUE(receivedInternalViewport.has_value());
+ ASSERT_EQ(internalViewport, *receivedInternalViewport);
// Check matching by viewport type
- internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
- ASSERT_TRUE(internalViewport);
- ASSERT_EQ(uniqueId, internalViewport->uniqueId);
+ receivedInternalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
+ ASSERT_TRUE(receivedInternalViewport.has_value());
+ ASSERT_EQ(internalViewport, *receivedInternalViewport);
mFakePolicy->clearViewports();
+
// Make sure nothing is found after clear
- internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
- ASSERT_FALSE(internalViewport);
- internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
- ASSERT_FALSE(internalViewport);
+ ASSERT_FALSE(mFakePolicy->getDisplayViewportByUniqueId(uniqueId));
+ ASSERT_FALSE(mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL));
}
TEST_F(InputReaderPolicyTest, Viewports_GetByType) {
@@ -419,49 +419,49 @@
constexpr ui::LogicalDisplayId virtualDisplayId2 = ui::LogicalDisplayId{3};
// Add an internal viewport
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, internalUniqueId, NO_PORT,
- ViewportType::INTERNAL);
+ DisplayViewport internalViewport =
+ createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, internalUniqueId, NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(internalViewport);
// Add an external viewport
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, externalUniqueId, NO_PORT,
- ViewportType::EXTERNAL);
+ DisplayViewport externalViewport =
+ createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, externalUniqueId, NO_PORT, ViewportType::EXTERNAL);
+ mFakePolicy->addDisplayViewport(externalViewport);
// Add an virtual viewport
- mFakePolicy->addDisplayViewport(virtualDisplayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- ui::ROTATION_0, /*isActive=*/true, virtualUniqueId1, NO_PORT,
- ViewportType::VIRTUAL);
+ DisplayViewport virtualViewport1 =
+ createViewport(virtualDisplayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, virtualUniqueId1, NO_PORT, ViewportType::VIRTUAL);
+ mFakePolicy->addDisplayViewport(virtualViewport1);
// Add another virtual viewport
- mFakePolicy->addDisplayViewport(virtualDisplayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- ui::ROTATION_0, /*isActive=*/true, virtualUniqueId2, NO_PORT,
- ViewportType::VIRTUAL);
+ DisplayViewport virtualViewport2 =
+ createViewport(virtualDisplayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, virtualUniqueId2, NO_PORT, ViewportType::VIRTUAL);
+ mFakePolicy->addDisplayViewport(virtualViewport2);
// Check matching by type for internal
- std::optional<DisplayViewport> internalViewport =
+ std::optional<DisplayViewport> receivedInternalViewport =
mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
- ASSERT_TRUE(internalViewport);
- ASSERT_EQ(internalUniqueId, internalViewport->uniqueId);
+ ASSERT_TRUE(receivedInternalViewport.has_value());
+ ASSERT_EQ(internalViewport, *receivedInternalViewport);
// Check matching by type for external
- std::optional<DisplayViewport> externalViewport =
+ std::optional<DisplayViewport> receivedExternalViewport =
mFakePolicy->getDisplayViewportByType(ViewportType::EXTERNAL);
- ASSERT_TRUE(externalViewport);
- ASSERT_EQ(externalUniqueId, externalViewport->uniqueId);
+ ASSERT_TRUE(receivedExternalViewport.has_value());
+ ASSERT_EQ(externalViewport, *receivedExternalViewport);
// Check matching by uniqueId for virtual viewport #1
- std::optional<DisplayViewport> virtualViewport1 =
+ std::optional<DisplayViewport> receivedVirtualViewport1 =
mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId1);
- ASSERT_TRUE(virtualViewport1);
- ASSERT_EQ(ViewportType::VIRTUAL, virtualViewport1->type);
- ASSERT_EQ(virtualUniqueId1, virtualViewport1->uniqueId);
- ASSERT_EQ(virtualDisplayId1, virtualViewport1->displayId);
+ ASSERT_TRUE(receivedVirtualViewport1.has_value());
+ ASSERT_EQ(virtualViewport1, *receivedVirtualViewport1);
// Check matching by uniqueId for virtual viewport #2
- std::optional<DisplayViewport> virtualViewport2 =
+ std::optional<DisplayViewport> receivedVirtualViewport2 =
mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId2);
- ASSERT_TRUE(virtualViewport2);
- ASSERT_EQ(ViewportType::VIRTUAL, virtualViewport2->type);
- ASSERT_EQ(virtualUniqueId2, virtualViewport2->uniqueId);
- ASSERT_EQ(virtualDisplayId2, virtualViewport2->displayId);
+ ASSERT_TRUE(receivedVirtualViewport2.has_value());
+ ASSERT_EQ(virtualViewport2, *receivedVirtualViewport2);
}
@@ -481,24 +481,26 @@
for (const ViewportType& type : types) {
mFakePolicy->clearViewports();
// Add a viewport
- mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, uniqueId1, NO_PORT, type);
+ DisplayViewport viewport1 =
+ createViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, uniqueId1, NO_PORT, type);
+ mFakePolicy->addDisplayViewport(viewport1);
// Add another viewport
- mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, uniqueId2, NO_PORT, type);
+ DisplayViewport viewport2 =
+ createViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, uniqueId2, NO_PORT, type);
+ mFakePolicy->addDisplayViewport(viewport2);
// Check that correct display viewport was returned by comparing the display IDs.
- std::optional<DisplayViewport> viewport1 =
+ std::optional<DisplayViewport> receivedViewport1 =
mFakePolicy->getDisplayViewportByUniqueId(uniqueId1);
- ASSERT_TRUE(viewport1);
- ASSERT_EQ(displayId1, viewport1->displayId);
- ASSERT_EQ(type, viewport1->type);
+ ASSERT_TRUE(receivedViewport1.has_value());
+ ASSERT_EQ(viewport1, *receivedViewport1);
- std::optional<DisplayViewport> viewport2 =
+ std::optional<DisplayViewport> receivedViewport2 =
mFakePolicy->getDisplayViewportByUniqueId(uniqueId2);
- ASSERT_TRUE(viewport2);
- ASSERT_EQ(displayId2, viewport2->displayId);
- ASSERT_EQ(type, viewport2->type);
+ ASSERT_TRUE(receivedViewport2.has_value());
+ ASSERT_EQ(viewport2, *receivedViewport2);
// When there are multiple viewports of the same kind, and uniqueId is not specified
// in the call to getDisplayViewport, then that situation is not supported.
@@ -524,32 +526,27 @@
// Add the default display first and ensure it gets returned.
mFakePolicy->clearViewports();
- mFakePolicy->addDisplayViewport(ui::LogicalDisplayId::DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- ui::ROTATION_0, /*isActive=*/true, uniqueId1, NO_PORT,
- ViewportType::INTERNAL);
- mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- ui::ROTATION_0, /*isActive=*/true, uniqueId2, NO_PORT,
- ViewportType::INTERNAL);
-
- std::optional<DisplayViewport> viewport =
+ DisplayViewport viewport1 = createViewport(ui::LogicalDisplayId::DEFAULT, DISPLAY_WIDTH,
+ DISPLAY_HEIGHT, ui::ROTATION_0, /*isActive=*/true,
+ uniqueId1, NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(viewport1);
+ DisplayViewport viewport2 =
+ createViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, uniqueId2, NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(viewport2);
+ std::optional<DisplayViewport> receivedViewport =
mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
- ASSERT_TRUE(viewport);
- ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, viewport->displayId);
- ASSERT_EQ(ViewportType::INTERNAL, viewport->type);
+ ASSERT_TRUE(receivedViewport.has_value());
+ ASSERT_EQ(viewport1, *receivedViewport);
// Add the default display second to make sure order doesn't matter.
mFakePolicy->clearViewports();
- mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- ui::ROTATION_0, /*isActive=*/true, uniqueId2, NO_PORT,
- ViewportType::INTERNAL);
- mFakePolicy->addDisplayViewport(ui::LogicalDisplayId::DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- ui::ROTATION_0, /*isActive=*/true, uniqueId1, NO_PORT,
- ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(viewport2);
+ mFakePolicy->addDisplayViewport(viewport1);
- viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
- ASSERT_TRUE(viewport);
- ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, viewport->displayId);
- ASSERT_EQ(ViewportType::INTERNAL, viewport->type);
+ receivedViewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
+ ASSERT_TRUE(receivedViewport.has_value());
+ ASSERT_EQ(viewport1, *receivedViewport);
}
/**
@@ -567,28 +564,27 @@
mFakePolicy->clearViewports();
// Add a viewport that's associated with some display port that's not of interest.
- mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, uniqueId1, hdmi3, type);
+ DisplayViewport viewport1 =
+ createViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, uniqueId1, hdmi3, type);
+ mFakePolicy->addDisplayViewport(viewport1);
// Add another viewport, connected to HDMI1 port
- mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, uniqueId2, hdmi1, type);
-
+ DisplayViewport viewport2 =
+ createViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, uniqueId2, hdmi1, type);
+ mFakePolicy->addDisplayViewport(viewport2);
// Check that correct display viewport was returned by comparing the display ports.
std::optional<DisplayViewport> hdmi1Viewport = mFakePolicy->getDisplayViewportByPort(hdmi1);
- ASSERT_TRUE(hdmi1Viewport);
- ASSERT_EQ(displayId2, hdmi1Viewport->displayId);
- ASSERT_EQ(uniqueId2, hdmi1Viewport->uniqueId);
+ ASSERT_TRUE(hdmi1Viewport.has_value());
+ ASSERT_EQ(viewport2, *hdmi1Viewport);
// Check that we can still get the same viewport using the uniqueId
hdmi1Viewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId2);
- ASSERT_TRUE(hdmi1Viewport);
- ASSERT_EQ(displayId2, hdmi1Viewport->displayId);
- ASSERT_EQ(uniqueId2, hdmi1Viewport->uniqueId);
- ASSERT_EQ(type, hdmi1Viewport->type);
+ ASSERT_TRUE(hdmi1Viewport.has_value());
+ ASSERT_EQ(viewport2, *hdmi1Viewport);
// Check that we cannot find a port with "HDMI2", because we never added one
- std::optional<DisplayViewport> hdmi2Viewport = mFakePolicy->getDisplayViewportByPort(hdmi2);
- ASSERT_FALSE(hdmi2Viewport);
+ ASSERT_FALSE(mFakePolicy->getDisplayViewportByPort(hdmi2));
}
// --- InputReaderTest ---
@@ -1045,11 +1041,14 @@
// Add default and second display.
mFakePolicy->clearViewports();
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL);
- mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- ui::ROTATION_0, /*isActive=*/true, "local:1", hdmi1,
- ViewportType::EXTERNAL);
+ DisplayViewport internalViewport =
+ createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(internalViewport);
+ DisplayViewport externalViewport =
+ createViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, "local:1", hdmi1, ViewportType::EXTERNAL);
+ mFakePolicy->addDisplayViewport(externalViewport);
mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::DISPLAY_INFO);
mReader->loopOnce();
@@ -1392,6 +1391,82 @@
ASSERT_EQ(mReader->getLightColor(deviceId, /*lightId=*/1), LIGHT_BRIGHTNESS);
}
+TEST_F(InputReaderTest, SetPowerWakeUp) {
+ ASSERT_NO_FATAL_FAILURE(addDevice(1, "1st", InputDeviceClass::KEYBOARD, nullptr));
+ ASSERT_NO_FATAL_FAILURE(addDevice(2, "2nd", InputDeviceClass::KEYBOARD, nullptr));
+ ASSERT_NO_FATAL_FAILURE(addDevice(3, "3rd", InputDeviceClass::KEYBOARD, nullptr));
+
+ ASSERT_EQ(mFakeEventHub->fakeReadKernelWakeup(1), false);
+
+ ASSERT_TRUE(mFakeEventHub->setKernelWakeEnabled(2, true));
+ ASSERT_EQ(mFakeEventHub->fakeReadKernelWakeup(2), true);
+
+ ASSERT_TRUE(mFakeEventHub->setKernelWakeEnabled(3, false));
+ ASSERT_EQ(mFakeEventHub->fakeReadKernelWakeup(3), false);
+}
+
+TEST_F(InputReaderTest, MergeableInputDevices) {
+ constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
+
+ // By default, all of the default-created eventhub devices will have the same identifier
+ // (implicitly vid 0, pid 0, etc.), which is why we expect them to be merged.
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "1st", InputDeviceClass::KEYBOARD, nullptr));
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[1], "2nd", InputDeviceClass::JOYSTICK, nullptr));
+
+ // The two devices will be merged to one input device as they have same identifier, and none are
+ // pointer devices.
+ ASSERT_EQ(1U, mFakePolicy->getInputDevices().size());
+}
+
+TEST_F(InputReaderTest, MergeableDevicesWithTouch) {
+ constexpr int32_t eventHubIds[3] = {END_RESERVED_ID, END_RESERVED_ID + 1, END_RESERVED_ID + 2};
+
+ // By default, all of the default-created eventhub devices will have the same identifier
+ // (implicitly vid 0, pid 0, etc.), which is why we expect them to be merged.
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "1st", InputDeviceClass::TOUCH_MT, nullptr));
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[1], "2nd", InputDeviceClass::KEYBOARD, nullptr));
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[2], "3rd", InputDeviceClass::GAMEPAD, nullptr));
+
+ // The three devices will be merged to one input device as they have same identifier, and only
+ // one is a pointer device.
+ ASSERT_EQ(1U, mFakePolicy->getInputDevices().size());
+}
+
+TEST_F(InputReaderTest, UnmergeableTouchDevices) {
+ SCOPED_FLAG_OVERRIDE(prevent_merging_input_pointer_devices, true);
+
+ constexpr int32_t eventHubIds[3] = {END_RESERVED_ID, END_RESERVED_ID + 1, END_RESERVED_ID + 2};
+
+ // By default, all of the default-created eventhub devices will have the same identifier
+ // (implicitly vid 0, pid 0, etc.), which is why they can potentially be merged.
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "1st", InputDeviceClass::TOUCH, nullptr));
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[1], "2nd", InputDeviceClass::TOUCH_MT, nullptr));
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[2], "2nd", InputDeviceClass::CURSOR, nullptr));
+
+ // The three devices will not be merged, as they have same identifier, but are all pointer
+ // devices.
+ ASSERT_EQ(3U, mFakePolicy->getInputDevices().size());
+}
+
+TEST_F(InputReaderTest, MergeableMixedDevices) {
+ SCOPED_FLAG_OVERRIDE(prevent_merging_input_pointer_devices, true);
+
+ constexpr int32_t eventHubIds[4] = {END_RESERVED_ID, END_RESERVED_ID + 1, END_RESERVED_ID + 2,
+ END_RESERVED_ID + 3};
+
+ // By default, all of the default-created eventhub devices will have the same identifier
+ // (implicitly vid 0, pid 0, etc.), which is why they can potentially be merged.
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[0], "1st", InputDeviceClass::TOUCH, nullptr));
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[1], "2nd", InputDeviceClass::TOUCH_MT, nullptr));
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[2], "3rd", InputDeviceClass::DPAD, nullptr));
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubIds[3], "4th", InputDeviceClass::JOYSTICK, nullptr));
+
+ // Non-touch devices can be merged with one of the touch devices, as they have same identifier,
+ // but the two touch devices will not combine with each other. It is not specified which touch
+ // device the non-touch devices merge with.
+ ASSERT_EQ(2U, mFakePolicy->getInputDevices().size());
+}
+
// --- InputReaderIntegrationTest ---
// These tests create and interact with the InputReader only through its interface.
@@ -1638,7 +1713,7 @@
mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT));
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
const auto info = waitForDevice(mDevice->getName());
- ASSERT_TRUE(info);
+ ASSERT_TRUE(info.has_value());
mDeviceInfo = *info;
}
@@ -1646,8 +1721,10 @@
ui::Rotation orientation, const std::string& uniqueId,
std::optional<uint8_t> physicalPort,
ViewportType viewportType) {
- mFakePolicy->addDisplayViewport(displayId, width, height, orientation, /*isActive=*/true,
- uniqueId, physicalPort, viewportType);
+ DisplayViewport viewport =
+ createViewport(displayId, width, height, orientation, /*isActive=*/true, uniqueId,
+ physicalPort, viewportType);
+ mFakePolicy->addDisplayViewport(viewport);
mReader->requestRefreshConfiguration(InputReaderConfiguration::Change::DISPLAY_INFO);
}
@@ -1706,7 +1783,7 @@
ViewportType::INTERNAL);
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
const auto info = waitForDevice(mDevice->getName());
- ASSERT_TRUE(info);
+ ASSERT_TRUE(info.has_value());
mDeviceInfo = *info;
}
};
@@ -2038,7 +2115,7 @@
auto externalStylus = createUinputDevice<UinputExternalStylus>();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
const auto stylusInfo = waitForDevice(externalStylus->getName());
- ASSERT_TRUE(stylusInfo);
+ ASSERT_TRUE(stylusInfo.has_value());
// Move
mDevice->sendMove(centerPoint + Point(2, 2));
@@ -2107,7 +2184,7 @@
mStylus = mStylusDeviceLifecycleTracker.get();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
const auto info = waitForDevice(mStylus->getName());
- ASSERT_TRUE(info);
+ ASSERT_TRUE(info.has_value());
mStylusInfo = *info;
}
@@ -2380,7 +2457,7 @@
// Connecting an external stylus changes the source of the touchscreen.
const auto deviceInfo = waitForDevice(mDevice->getName());
- ASSERT_TRUE(deviceInfo);
+ ASSERT_TRUE(deviceInfo.has_value());
ASSERT_TRUE(isFromSource(deviceInfo->getSources(), STYLUS_FUSION_SOURCE));
}
@@ -2393,7 +2470,7 @@
createUinputDevice<UinputExternalStylusWithPressure>();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
const auto stylusInfo = waitForDevice(stylus->getName());
- ASSERT_TRUE(stylusInfo);
+ ASSERT_TRUE(stylusInfo.has_value());
ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
@@ -2438,7 +2515,7 @@
createUinputDevice<UinputExternalStylusWithPressure>();
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
const auto stylusInfo = waitForDevice(stylus->getName());
- ASSERT_TRUE(stylusInfo);
+ ASSERT_TRUE(stylusInfo.has_value());
ASSERT_EQ(AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_KEYBOARD, stylusInfo->getSources());
@@ -2460,10 +2537,10 @@
const auto syncTime = std::chrono::system_clock::now();
// After 72 ms, the event *will* be generated. If we wait the full 72 ms to check that NO event
// is generated in that period, there will be a race condition between the event being generated
- // and the test's wait timeout expiring. Thus, we wait for a shorter duration in the test, which
- // will reduce the liklihood of the race condition occurring.
- const auto waitUntilTimeForNoEvent =
- syncTime + std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT / 2));
+ // and the test's wait timeout expiring. Thus, we wait for a shorter duration in the test to
+ // ensure the event is not immediately generated, which should reduce the liklihood of the race
+ // condition occurring.
+ const auto waitUntilTimeForNoEvent = syncTime + std::chrono::milliseconds(1);
mDevice->sendSync();
ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled(waitUntilTimeForNoEvent));
@@ -2865,9 +2942,10 @@
ASSERT_FALSE(mDevice->isEnabled());
// Prepare displays.
- mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- ui::ROTATION_0, /*isActive=*/true, UNIQUE_ID, hdmi,
- ViewportType::INTERNAL);
+ DisplayViewport viewport =
+ createViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, UNIQUE_ID, hdmi, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(viewport);
unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
InputReaderConfiguration::Change::DISPLAY_INFO);
ASSERT_TRUE(mDevice->isEnabled());
@@ -2902,9 +2980,12 @@
ASSERT_FALSE(mDevice->isEnabled());
// Device should be enabled when a display is found.
- mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
- NO_PORT, ViewportType::INTERNAL);
+
+ DisplayViewport secondViewport =
+ createViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /* isActive= */ true, DISPLAY_UNIQUE_ID, NO_PORT,
+ ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(secondViewport);
unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
InputReaderConfiguration::Change::DISPLAY_INFO);
ASSERT_TRUE(mDevice->isEnabled());
@@ -2930,9 +3011,12 @@
/*changes=*/{});
mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
- mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
- NO_PORT, ViewportType::INTERNAL);
+
+ DisplayViewport secondViewport =
+ createViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /* isActive= */ true, DISPLAY_UNIQUE_ID, NO_PORT,
+ ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(secondViewport);
const auto initialGeneration = mDevice->getGeneration();
unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
InputReaderConfiguration::Change::DISPLAY_INFO);
@@ -3017,1163 +3101,6 @@
mapper.assertProcessWasCalled();
}
-// --- SensorInputMapperTest ---
-
-class SensorInputMapperTest : public InputMapperTest {
-protected:
- static const int32_t ACCEL_RAW_MIN;
- static const int32_t ACCEL_RAW_MAX;
- static const int32_t ACCEL_RAW_FUZZ;
- static const int32_t ACCEL_RAW_FLAT;
- static const int32_t ACCEL_RAW_RESOLUTION;
-
- static const int32_t GYRO_RAW_MIN;
- static const int32_t GYRO_RAW_MAX;
- static const int32_t GYRO_RAW_FUZZ;
- static const int32_t GYRO_RAW_FLAT;
- static const int32_t GYRO_RAW_RESOLUTION;
-
- static const float GRAVITY_MS2_UNIT;
- static const float DEGREE_RADIAN_UNIT;
-
- void prepareAccelAxes();
- void prepareGyroAxes();
- void setAccelProperties();
- void setGyroProperties();
- void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::SENSOR); }
-};
-
-const int32_t SensorInputMapperTest::ACCEL_RAW_MIN = -32768;
-const int32_t SensorInputMapperTest::ACCEL_RAW_MAX = 32768;
-const int32_t SensorInputMapperTest::ACCEL_RAW_FUZZ = 16;
-const int32_t SensorInputMapperTest::ACCEL_RAW_FLAT = 0;
-const int32_t SensorInputMapperTest::ACCEL_RAW_RESOLUTION = 8192;
-
-const int32_t SensorInputMapperTest::GYRO_RAW_MIN = -2097152;
-const int32_t SensorInputMapperTest::GYRO_RAW_MAX = 2097152;
-const int32_t SensorInputMapperTest::GYRO_RAW_FUZZ = 16;
-const int32_t SensorInputMapperTest::GYRO_RAW_FLAT = 0;
-const int32_t SensorInputMapperTest::GYRO_RAW_RESOLUTION = 1024;
-
-const float SensorInputMapperTest::GRAVITY_MS2_UNIT = 9.80665f;
-const float SensorInputMapperTest::DEGREE_RADIAN_UNIT = 0.0174533f;
-
-void SensorInputMapperTest::prepareAccelAxes() {
- mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
- ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
- mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
- ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
- mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Z, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ,
- ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION);
-}
-
-void SensorInputMapperTest::prepareGyroAxes() {
- mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RX, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
- GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
- mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RY, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
- GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
- mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RZ, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ,
- GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION);
-}
-
-void SensorInputMapperTest::setAccelProperties() {
- mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 0, InputDeviceSensorType::ACCELEROMETER,
- /* sensorDataIndex */ 0);
- mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 1, InputDeviceSensorType::ACCELEROMETER,
- /* sensorDataIndex */ 1);
- mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 2, InputDeviceSensorType::ACCELEROMETER,
- /* sensorDataIndex */ 2);
- mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP);
- addConfigurationProperty("sensor.accelerometer.reportingMode", "0");
- addConfigurationProperty("sensor.accelerometer.maxDelay", "100000");
- addConfigurationProperty("sensor.accelerometer.minDelay", "5000");
- addConfigurationProperty("sensor.accelerometer.power", "1.5");
-}
-
-void SensorInputMapperTest::setGyroProperties() {
- mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 3, InputDeviceSensorType::GYROSCOPE,
- /* sensorDataIndex */ 0);
- mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 4, InputDeviceSensorType::GYROSCOPE,
- /* sensorDataIndex */ 1);
- mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 5, InputDeviceSensorType::GYROSCOPE,
- /* sensorDataIndex */ 2);
- mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP);
- addConfigurationProperty("sensor.gyroscope.reportingMode", "0");
- addConfigurationProperty("sensor.gyroscope.maxDelay", "100000");
- addConfigurationProperty("sensor.gyroscope.minDelay", "5000");
- addConfigurationProperty("sensor.gyroscope.power", "0.8");
-}
-
-TEST_F(SensorInputMapperTest, GetSources) {
- SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
-
- ASSERT_EQ(static_cast<uint32_t>(AINPUT_SOURCE_SENSOR), mapper.getSources());
-}
-
-TEST_F(SensorInputMapperTest, ProcessAccelerometerSensor) {
- setAccelProperties();
- prepareAccelAxes();
- SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
-
- ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::ACCELEROMETER,
- std::chrono::microseconds(10000),
- std::chrono::microseconds(0)));
- ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID));
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, 20000);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, -20000);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Z, 40000);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
-
- NotifySensorArgs args;
- std::vector<float> values = {20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT,
- -20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT,
- 40000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT};
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args));
- ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR);
- ASSERT_EQ(args.deviceId, DEVICE_ID);
- ASSERT_EQ(args.sensorType, InputDeviceSensorType::ACCELEROMETER);
- ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH);
- ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME);
- ASSERT_EQ(args.values, values);
- mapper.flushSensor(InputDeviceSensorType::ACCELEROMETER);
-}
-
-TEST_F(SensorInputMapperTest, ProcessGyroscopeSensor) {
- setGyroProperties();
- prepareGyroAxes();
- SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>();
-
- ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::GYROSCOPE,
- std::chrono::microseconds(10000),
- std::chrono::microseconds(0)));
- ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID));
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RX, 20000);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RY, -20000);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RZ, 40000);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
-
- NotifySensorArgs args;
- std::vector<float> values = {20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT,
- -20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT,
- 40000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT};
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args));
- ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR);
- ASSERT_EQ(args.deviceId, DEVICE_ID);
- ASSERT_EQ(args.sensorType, InputDeviceSensorType::GYROSCOPE);
- ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH);
- ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME);
- ASSERT_EQ(args.values, values);
- mapper.flushSensor(InputDeviceSensorType::GYROSCOPE);
-}
-
-// --- KeyboardInputMapperTest ---
-
-class KeyboardInputMapperTest : public InputMapperTest {
-protected:
- void SetUp() override {
- InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
- InputDeviceClass::ALPHAKEY);
- }
- const std::string UNIQUE_ID = "local:0";
- const KeyboardLayoutInfo DEVICE_KEYBOARD_LAYOUT_INFO = KeyboardLayoutInfo("en-US", "qwerty");
- void prepareDisplay(ui::Rotation orientation);
-
- void testDPadKeyRotation(KeyboardInputMapper& mapper, int32_t originalScanCode,
- int32_t originalKeyCode, int32_t rotatedKeyCode,
- ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID);
-};
-
-/* Similar to setDisplayInfoAndReconfigure, but pre-populates all parameters except for the
- * orientation.
- */
-void KeyboardInputMapperTest::prepareDisplay(ui::Rotation orientation) {
- setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
- NO_PORT, ViewportType::INTERNAL);
-}
-
-void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper& mapper,
- int32_t originalScanCode, int32_t originalKeyCode,
- int32_t rotatedKeyCode,
- ui::LogicalDisplayId displayId) {
- NotifyKeyArgs args;
-
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
- ASSERT_EQ(originalScanCode, args.scanCode);
- ASSERT_EQ(rotatedKeyCode, args.keyCode);
- ASSERT_EQ(displayId, args.displayId);
-
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, originalScanCode, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(originalScanCode, args.scanCode);
- ASSERT_EQ(rotatedKeyCode, args.keyCode);
- ASSERT_EQ(displayId, args.displayId);
-}
-
-TEST_F(KeyboardInputMapperTest, GetSources) {
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
-
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, mapper.getSources());
-}
-
-TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) {
- const int32_t USAGE_A = 0x070004;
- const int32_t USAGE_UNKNOWN = 0x07ffff;
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
- mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
- mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, POLICY_FLAG_WAKE);
- mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, POLICY_FLAG_WAKE);
- mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, POLICY_FLAG_WAKE);
-
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
- // Initial metastate is AMETA_NONE.
- ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
-
- // Key down by scan code.
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
- NotifyKeyArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
- ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
- ASSERT_EQ(KEY_HOME, args.scanCode);
- ASSERT_EQ(AMETA_NONE, args.metaState);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
- ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
- // Key up by scan code.
- process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
- ASSERT_EQ(KEY_HOME, args.scanCode);
- ASSERT_EQ(AMETA_NONE, args.metaState);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
- ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
- // Key down by usage code.
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, 0, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
- ASSERT_EQ(AKEYCODE_A, args.keyCode);
- ASSERT_EQ(0, args.scanCode);
- ASSERT_EQ(AMETA_NONE, args.metaState);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
- ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
- // Key up by usage code.
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_A);
- process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, 0, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(AKEYCODE_A, args.keyCode);
- ASSERT_EQ(0, args.scanCode);
- ASSERT_EQ(AMETA_NONE, args.metaState);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
- ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
- // Key down with unknown scan code or usage code.
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UNKNOWN, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
- ASSERT_EQ(0, args.keyCode);
- ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
- ASSERT_EQ(AMETA_NONE, args.metaState);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
- ASSERT_EQ(0U, args.policyFlags);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
- // Key up with unknown scan code or usage code.
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
- process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_UNKNOWN, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(0, args.keyCode);
- ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
- ASSERT_EQ(AMETA_NONE, args.metaState);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
- ASSERT_EQ(0U, args.policyFlags);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-}
-
-TEST_F(KeyboardInputMapperTest, Process_KeyRemapping) {
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_B, 0, AKEYCODE_B, 0);
-
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
-
- mFakeEventHub->setKeyRemapping(EVENTHUB_ID, {{AKEYCODE_A, AKEYCODE_B}});
- // Key down by scan code.
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_A, 1);
- NotifyKeyArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AKEYCODE_B, args.keyCode);
-
- // Key up by scan code.
- process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AKEYCODE_B, args.keyCode);
-}
-
-/**
- * Ensure that the readTime is set to the time when the EV_KEY is received.
- */
-TEST_F(KeyboardInputMapperTest, Process_SendsReadTime) {
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
-
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
- NotifyKeyArgs args;
-
- // Key down
- process(mapper, ARBITRARY_TIME, /*readTime=*/12, EV_KEY, KEY_HOME, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(12, args.readTime);
-
- // Key up
- process(mapper, ARBITRARY_TIME, /*readTime=*/15, EV_KEY, KEY_HOME, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(15, args.readTime);
-}
-
-TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) {
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFTSHIFT, 0, AKEYCODE_SHIFT_LEFT, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, 0, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 0);
-
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
-
- // Initial metastate is AMETA_NONE.
- ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
-
- // Metakey down.
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 1);
- NotifyKeyArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
- ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
-
- // Key down.
- process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_A, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
-
- // Key up.
- process(mapper, ARBITRARY_TIME + 2, READ_TIME, EV_KEY, KEY_A, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
-
- // Metakey up.
- process(mapper, ARBITRARY_TIME + 3, READ_TIME, EV_KEY, KEY_LEFTSHIFT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AMETA_NONE, args.metaState);
- ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
- ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
-}
-
-TEST_F(KeyboardInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateDPad) {
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
-
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
-
- prepareDisplay(ui::ROTATION_90);
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
-}
-
-TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
-
- addConfigurationProperty("keyboard.orientationAware", "1");
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
-
- prepareDisplay(ui::ROTATION_0);
- ASSERT_NO_FATAL_FAILURE(
- testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
- AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
- AKEYCODE_DPAD_DOWN, DISPLAY_ID));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
- AKEYCODE_DPAD_LEFT, DISPLAY_ID));
-
- clearViewports();
- prepareDisplay(ui::ROTATION_90);
- ASSERT_NO_FATAL_FAILURE(
- testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, DISPLAY_ID));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
- AKEYCODE_DPAD_UP, DISPLAY_ID));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
- AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
- AKEYCODE_DPAD_DOWN, DISPLAY_ID));
-
- clearViewports();
- prepareDisplay(ui::ROTATION_180);
- ASSERT_NO_FATAL_FAILURE(
- testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN, DISPLAY_ID));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
- AKEYCODE_DPAD_LEFT, DISPLAY_ID));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
- AKEYCODE_DPAD_UP, DISPLAY_ID));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
- AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
-
- clearViewports();
- prepareDisplay(ui::ROTATION_270);
- ASSERT_NO_FATAL_FAILURE(
- testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
- AKEYCODE_DPAD_DOWN, DISPLAY_ID));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
- AKEYCODE_DPAD_LEFT, DISPLAY_ID));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
- AKEYCODE_DPAD_UP, DISPLAY_ID));
-
- // Special case: if orientation changes while key is down, we still emit the same keycode
- // in the key up as we did in the key down.
- NotifyKeyArgs args;
- clearViewports();
- prepareDisplay(ui::ROTATION_270);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
- ASSERT_EQ(KEY_UP, args.scanCode);
- ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
-
- clearViewports();
- prepareDisplay(ui::ROTATION_180);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(KEY_UP, args.scanCode);
- ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
-}
-
-TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_NotOrientationAware) {
- // If the keyboard is not orientation aware,
- // key events should not be associated with a specific display id
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
-
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
- NotifyKeyArgs args;
-
- // Display id should be LogicalDisplayId::INVALID without any display configuration.
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(ui::LogicalDisplayId::INVALID, args.displayId);
-
- prepareDisplay(ui::ROTATION_0);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(ui::LogicalDisplayId::INVALID, args.displayId);
-}
-
-TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_OrientationAware) {
- // If the keyboard is orientation aware,
- // key events should be associated with the internal viewport
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
-
- addConfigurationProperty("keyboard.orientationAware", "1");
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
- NotifyKeyArgs args;
-
- // Display id should be LogicalDisplayId::INVALID without any display configuration.
- // ^--- already checked by the previous test
-
- setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(DISPLAY_ID, args.displayId);
-
- constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
- clearViewports();
- setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(newDisplayId, args.displayId);
-}
-
-TEST_F(KeyboardInputMapperTest, GetKeyCodeState) {
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
-
- mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 1);
- ASSERT_EQ(1, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
-
- mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 0);
- ASSERT_EQ(0, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
-}
-
-TEST_F(KeyboardInputMapperTest, GetKeyCodeForKeyLocation) {
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
-
- mFakeEventHub->addKeyCodeMapping(EVENTHUB_ID, AKEYCODE_Y, AKEYCODE_Z);
- ASSERT_EQ(AKEYCODE_Z, mapper.getKeyCodeForKeyLocation(AKEYCODE_Y))
- << "If a mapping is available, the result is equal to the mapping";
-
- ASSERT_EQ(AKEYCODE_A, mapper.getKeyCodeForKeyLocation(AKEYCODE_A))
- << "If no mapping is available, the result is the key location";
-}
-
-TEST_F(KeyboardInputMapperTest, GetScanCodeState) {
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
-
- mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 1);
- ASSERT_EQ(1, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
-
- mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 0);
- ASSERT_EQ(0, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
-}
-
-TEST_F(KeyboardInputMapperTest, MarkSupportedKeyCodes) {
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
-
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
-
- uint8_t flags[2] = { 0, 0 };
- ASSERT_TRUE(mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_A, AKEYCODE_B}, flags));
- ASSERT_TRUE(flags[0]);
- ASSERT_FALSE(flags[1]);
-}
-
-TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) {
- mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
- mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
- mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
-
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
- // Initial metastate is AMETA_NONE.
- ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
-
- // Initialization should have turned all of the lights off.
- ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
- ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
-
- // Toggle caps lock on.
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
- ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
- ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
-
- // Toggle num lock on.
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
- ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
- ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
-
- // Toggle caps lock off.
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
- ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
- ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper.getMetaState());
-
- // Toggle scroll lock on.
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
- ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
- ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
- ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
-
- // Toggle num lock off.
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
- ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
- ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
- ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
-
- // Toggle scroll lock off.
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
- ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
- ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
-}
-
-TEST_F(KeyboardInputMapperTest, Configure_AssignsDisplayPort) {
- // keyboard 1.
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
-
- // keyboard 2.
- const std::string USB2 = "USB2";
- const std::string DEVICE_NAME2 = "KEYBOARD2";
- constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
- constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
- std::shared_ptr<InputDevice> device2 =
- newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
- ftl::Flags<InputDeviceClass>(0));
-
- mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
- mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
- mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
- mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
-
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
-
- device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
- KeyboardInputMapper& mapper2 =
- device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
- mFakePolicy
- ->getReaderConfiguration(),
- AINPUT_SOURCE_KEYBOARD);
- std::list<NotifyArgs> unused =
- device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
- /*changes=*/{});
- unused += device2->reset(ARBITRARY_TIME);
-
- // Prepared displays and associated info.
- constexpr uint8_t hdmi1 = 0;
- constexpr uint8_t hdmi2 = 1;
- const std::string SECONDARY_UNIQUE_ID = "local:1";
-
- mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
- mFakePolicy->addInputPortAssociation(USB2, hdmi2);
-
- // No associated display viewport found, should disable the device.
- unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
- InputReaderConfiguration::Change::DISPLAY_INFO);
- ASSERT_FALSE(device2->isEnabled());
-
- // Prepare second display.
- constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
- setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- UNIQUE_ID, hdmi1, ViewportType::INTERNAL);
- setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- SECONDARY_UNIQUE_ID, hdmi2, ViewportType::EXTERNAL);
- // Default device will reconfigure above, need additional reconfiguration for another device.
- unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
- InputReaderConfiguration::Change::DISPLAY_INFO);
-
- // Device should be enabled after the associated display is found.
- ASSERT_TRUE(mDevice->isEnabled());
- ASSERT_TRUE(device2->isEnabled());
-
- // Test pad key events
- ASSERT_NO_FATAL_FAILURE(
- testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
- AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN,
- AKEYCODE_DPAD_DOWN, DISPLAY_ID));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT,
- AKEYCODE_DPAD_LEFT, DISPLAY_ID));
-
- ASSERT_NO_FATAL_FAILURE(
- testDPadKeyRotation(mapper2, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, newDisplayId));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
- AKEYCODE_DPAD_RIGHT, newDisplayId));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_DOWN, AKEYCODE_DPAD_DOWN,
- AKEYCODE_DPAD_DOWN, newDisplayId));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_LEFT, AKEYCODE_DPAD_LEFT,
- AKEYCODE_DPAD_LEFT, newDisplayId));
-}
-
-TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleAfterReattach) {
- mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
- mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
- mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
-
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
- // Initial metastate is AMETA_NONE.
- ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
-
- // Initialization should have turned all of the lights off.
- ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
- ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
-
- // Toggle caps lock on.
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
- ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
- ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
-
- // Toggle num lock on.
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
- ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
- ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
-
- // Toggle scroll lock on.
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
- ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
-
- mFakeEventHub->removeDevice(EVENTHUB_ID);
- mReader->loopOnce();
-
- // keyboard 2 should default toggle keys.
- const std::string USB2 = "USB2";
- const std::string DEVICE_NAME2 = "KEYBOARD2";
- constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
- constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
- std::shared_ptr<InputDevice> device2 =
- newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
- ftl::Flags<InputDeviceClass>(0));
- mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
- mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
- mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
- mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
- mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
- mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
-
- device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
- KeyboardInputMapper& mapper2 =
- device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
- mFakePolicy
- ->getReaderConfiguration(),
- AINPUT_SOURCE_KEYBOARD);
- std::list<NotifyArgs> unused =
- device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
- /*changes=*/{});
- unused += device2->reset(ARBITRARY_TIME);
-
- ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_CAPSL));
- ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_NUML));
- ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON,
- mapper2.getMetaState());
-}
-
-TEST_F(KeyboardInputMapperTest, Process_toggleCapsLockState) {
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
-
- // Suppose we have two mappers. (DPAD + KEYBOARD)
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD);
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
- // Initial metastate is AMETA_NONE.
- ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
-
- mReader->toggleCapsLockState(DEVICE_ID);
- ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
-}
-
-TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleInMultiDevices) {
- // keyboard 1.
- mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
- mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
- mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
-
- KeyboardInputMapper& mapper1 =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
-
- // keyboard 2.
- const std::string USB2 = "USB2";
- const std::string DEVICE_NAME2 = "KEYBOARD2";
- constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
- constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
- std::shared_ptr<InputDevice> device2 =
- newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
- ftl::Flags<InputDeviceClass>(0));
- mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
- mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
- mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
- mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
- mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
- mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
-
- device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
- KeyboardInputMapper& mapper2 =
- device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
- mFakePolicy
- ->getReaderConfiguration(),
- AINPUT_SOURCE_KEYBOARD);
- std::list<NotifyArgs> unused =
- device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
- /*changes=*/{});
- unused += device2->reset(ARBITRARY_TIME);
-
- // Initial metastate is AMETA_NONE.
- ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
- ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
-
- // Toggle num lock on and off.
- process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
- process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
- ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
- ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper1.getMetaState());
- ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper2.getMetaState());
-
- process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 1);
- process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_NUMLOCK, 0);
- ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
- ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
- ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
-
- // Toggle caps lock on and off.
- process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
- process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
- ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
- ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper1.getMetaState());
- ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper2.getMetaState());
-
- process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 1);
- process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_CAPSLOCK, 0);
- ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
- ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
- ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
-
- // Toggle scroll lock on and off.
- process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
- process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
- ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper1.getMetaState());
- ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper2.getMetaState());
-
- process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
- process(mapper1, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
- ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
- ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
-}
-
-TEST_F(KeyboardInputMapperTest, Process_DisabledDevice) {
- const int32_t USAGE_A = 0x070004;
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
- mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
-
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
- // Key down by scan code.
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
- NotifyKeyArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
- ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
- ASSERT_EQ(KEY_HOME, args.scanCode);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
-
- // Disable device, it should synthesize cancellation events for down events.
- mFakePolicy->addDisabledDevice(DEVICE_ID);
- configureDevice(InputReaderConfiguration::Change::ENABLED_STATE);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
- ASSERT_EQ(KEY_HOME, args.scanCode);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_CANCELED, args.flags);
-}
-
-TEST_F(KeyboardInputMapperTest, Configure_AssignKeyboardLayoutInfo) {
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
- std::list<NotifyArgs> unused =
- mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
- /*changes=*/{});
-
- uint32_t generation = mReader->getContext()->getGeneration();
- mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
-
- unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
- InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
-
- InputDeviceInfo deviceInfo = mDevice->getDeviceInfo();
- ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.languageTag,
- deviceInfo.getKeyboardLayoutInfo()->languageTag);
- ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.layoutType,
- deviceInfo.getKeyboardLayoutInfo()->layoutType);
- ASSERT_TRUE(mReader->getContext()->getGeneration() != generation);
-
- // Call change layout association with the same values: Generation shouldn't change
- generation = mReader->getContext()->getGeneration();
- mFakePolicy->addKeyboardLayoutAssociation(DEVICE_LOCATION, DEVICE_KEYBOARD_LAYOUT_INFO);
- unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
- InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
- ASSERT_TRUE(mReader->getContext()->getGeneration() == generation);
-}
-
-TEST_F(KeyboardInputMapperTest, LayoutInfoCorrectlyMapped) {
- mFakeEventHub->setRawLayoutInfo(EVENTHUB_ID,
- RawLayoutInfo{.languageTag = "en", .layoutType = "extended"});
-
- // Configuration
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
- InputReaderConfiguration config;
- std::list<NotifyArgs> unused = mDevice->configure(ARBITRARY_TIME, config, /*changes=*/{});
-
- ASSERT_EQ("en", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->languageTag);
- ASSERT_EQ("extended", mDevice->getDeviceInfo().getKeyboardLayoutInfo()->layoutType);
-}
-
-TEST_F(KeyboardInputMapperTest, Process_GesureEventToSetFlagKeepTouchMode) {
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, POLICY_FLAG_GESTURE);
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
- NotifyKeyArgs args;
-
- // Key down
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_LEFT, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_KEEP_TOUCH_MODE, args.flags);
-}
-
-/**
- * When there is more than one KeyboardInputMapper for an InputDevice, each mapper should produce
- * events that use the shared keyboard source across all mappers. This is to ensure that each
- * input device generates key events in a consistent manner, regardless of which mapper produces
- * the event.
- */
-TEST_F(KeyboardInputMapperTest, UsesSharedKeyboardSource) {
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
-
- // Add a mapper with SOURCE_KEYBOARD
- KeyboardInputMapper& keyboardMapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
-
- process(keyboardMapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1);
- ASSERT_NO_FATAL_FAILURE(
- mFakeListener->assertNotifyKeyWasCalled(WithSource(AINPUT_SOURCE_KEYBOARD)));
- process(keyboardMapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0);
- ASSERT_NO_FATAL_FAILURE(
- mFakeListener->assertNotifyKeyWasCalled(WithSource(AINPUT_SOURCE_KEYBOARD)));
-
- // Add a mapper with SOURCE_DPAD
- KeyboardInputMapper& dpadMapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD);
- for (auto* mapper : {&keyboardMapper, &dpadMapper}) {
- process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
- WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD)));
- process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
- WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD)));
- }
-
- // Add a mapper with SOURCE_GAMEPAD
- KeyboardInputMapper& gamepadMapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_GAMEPAD);
- for (auto* mapper : {&keyboardMapper, &dpadMapper, &gamepadMapper}) {
- process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
- WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD)));
- process(*mapper, ARBITRARY_TIME, 0, EV_KEY, KEY_HOME, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
- WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD)));
- }
-}
-
-// --- KeyboardInputMapperTest_ExternalAlphabeticDevice ---
-
-class KeyboardInputMapperTest_ExternalAlphabeticDevice : public InputMapperTest {
-protected:
- void SetUp() override {
- InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
- InputDeviceClass::ALPHAKEY | InputDeviceClass::EXTERNAL);
- }
-};
-
-// --- KeyboardInputMapperTest_ExternalNonAlphabeticDevice ---
-
-class KeyboardInputMapperTest_ExternalNonAlphabeticDevice : public InputMapperTest {
-protected:
- void SetUp() override {
- InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
- InputDeviceClass::EXTERNAL);
- }
-};
-
-TEST_F(KeyboardInputMapperTest_ExternalAlphabeticDevice, WakeBehavior_AlphabeticKeyboard) {
- // For external devices, keys will trigger wake on key down. Media keys should also trigger
- // wake if triggered from external devices.
-
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
- POLICY_FLAG_WAKE);
-
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
-
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
- NotifyKeyArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
-
- process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(uint32_t(0), args.policyFlags);
-
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
-
- process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(uint32_t(0), args.policyFlags);
-
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
-
- process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
-}
-
-TEST_F(KeyboardInputMapperTest_ExternalNonAlphabeticDevice, WakeBehavior_NonAlphabeticKeyboard) {
- // For external devices, keys will trigger wake on key down. Media keys should not trigger
- // wake if triggered from external non-alphaebtic keyboard (e.g. headsets).
-
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
- POLICY_FLAG_WAKE);
-
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
-
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
- NotifyKeyArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(uint32_t(0), args.policyFlags);
-
- process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(uint32_t(0), args.policyFlags);
-
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
-
- process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAYPAUSE, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
-}
-
-TEST_F(KeyboardInputMapperTest_ExternalAlphabeticDevice, DoNotWakeByDefaultBehavior) {
- // Tv Remote key's wake behavior is prescribed by the keylayout file.
-
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
- mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, POLICY_FLAG_WAKE);
-
- addConfigurationProperty("keyboard.doNotWakeByDefault", "1");
- KeyboardInputMapper& mapper =
- constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
-
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_HOME, 1);
- NotifyKeyArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
-
- process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_HOME, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
-
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_DOWN, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(uint32_t(0), args.policyFlags);
-
- process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_DOWN, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(uint32_t(0), args.policyFlags);
-
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_PLAY, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
-
- process(mapper, ARBITRARY_TIME + 1, READ_TIME, EV_KEY, KEY_PLAY, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
-}
-
// --- TouchInputMapperTest ---
class TouchInputMapperTest : public InputMapperTest {
@@ -5669,6 +4596,10 @@
NotifyMotionArgs motionArgs;
+ // Hold down the mouse button for the duration of the test, since the mouse tools require
+ // the button to be pressed to make sure they are not hovering.
+ processKey(mapper, BTN_MOUSE, 1);
+
// default tool type is finger
processDown(mapper, 100, 200);
processSync(mapper);
@@ -5676,6 +4607,9 @@
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
+ WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS)));
+
// eraser
processKey(mapper, BTN_TOOL_RUBBER, 1);
processSync(mapper);
@@ -8318,6 +7252,10 @@
NotifyMotionArgs motionArgs;
+ // Hold down the mouse button for the duration of the test, since the mouse tools require
+ // the button to be pressed to make sure they are not hovering.
+ processKey(mapper, BTN_MOUSE, 1);
+
// default tool type is finger
processId(mapper, 1);
processPosition(mapper, 100, 200);
@@ -8326,6 +7264,9 @@
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
ASSERT_EQ(ToolType::FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
+ WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS)));
+
// eraser
processKey(mapper, BTN_TOOL_RUBBER, 1);
processSync(mapper);
@@ -8492,35 +7433,39 @@
toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
// down when BTN_TOUCH is pressed, pressure defaults to 1
+ processPosition(mapper, 151, 251);
processKey(mapper, BTN_TOUCH, 1);
processSync(mapper);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
+ // HOVER_EXIT should have the same coordinates as the previous HOVER_MOVE
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-
+ // down at the new position
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
+ toDisplayX(151), toDisplayY(251), 1, 0, 0, 0, 0, 0, 0, 0));
// up when BTN_TOUCH is released, hover restored
+ processPosition(mapper, 152, 252);
processKey(mapper, BTN_TOUCH, 0);
processSync(mapper);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
+ // UP should have the same coordinates as the previous event
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
-
+ toDisplayX(151), toDisplayY(251), 1, 0, 0, 0, 0, 0, 0, 0));
+ // HOVER_ENTER at the new position
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
+ toDisplayX(152), toDisplayY(252), 0, 0, 0, 0, 0, 0, 0, 0));
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
+ toDisplayX(152), toDisplayY(252), 0, 0, 0, 0, 0, 0, 0, 0));
// exit hover when pointer goes away
processId(mapper, -1);
@@ -8528,7 +7473,7 @@
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
+ toDisplayX(152), toDisplayY(252), 0, 0, 0, 0, 0, 0, 0, 0));
}
TEST_F(MultiTouchInputMapperTest, Process_WhenAbsMTPressureIsPresent_HoversIfItsValueIsZero) {
@@ -8563,35 +7508,39 @@
toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
// down when pressure becomes non-zero
+ processPosition(mapper, 151, 251);
processPressure(mapper, RAW_PRESSURE_MAX);
processSync(mapper);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
+ // HOVER_EXIT should have the same coordinates as the previous HOVER_MOVE
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-
+ // down at the new position
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
+ toDisplayX(151), toDisplayY(251), 1, 0, 0, 0, 0, 0, 0, 0));
// up when pressure becomes 0, hover restored
+ processPosition(mapper, 152, 252);
processPressure(mapper, 0);
processSync(mapper);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
+ // UP should have the same coordinates as the previous event
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
-
+ toDisplayX(151), toDisplayY(251), 1, 0, 0, 0, 0, 0, 0, 0));
+ // HOVER_ENTER at the new position
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
+ toDisplayX(152), toDisplayY(252), 0, 0, 0, 0, 0, 0, 0, 0));
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
+ toDisplayX(152), toDisplayY(252), 0, 0, 0, 0, 0, 0, 0, 0));
// exit hover when pointer goes away
processId(mapper, -1);
@@ -8599,7 +7548,7 @@
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
+ toDisplayX(152), toDisplayY(252), 0, 0, 0, 0, 0, 0, 0, 0));
}
/**
@@ -8663,6 +7612,7 @@
}
TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
+ SCOPED_FLAG_OVERRIDE(disable_touch_input_mapper_pointer_usage, true);
prepareSecondaryDisplay(ViewportType::EXTERNAL);
prepareDisplay(ui::ROTATION_0);
@@ -8675,9 +7625,9 @@
processPosition(mapper, 100, 100);
processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_EQ(ui::LogicalDisplayId::INVALID, motionArgs.displayId);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithDisplayId(DISPLAY_ID),
+ WithSource(AINPUT_SOURCE_MOUSE), WithToolType(ToolType::FINGER))));
}
/**
@@ -8713,8 +7663,10 @@
TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreDropped) {
addConfigurationProperty("touch.deviceType", "touchScreen");
// Don't set touch.enableForInactiveViewport to verify the default behavior.
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
+ DisplayViewport viewport =
+ createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(viewport);
configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
prepareAxes(POSITION);
MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
@@ -8733,8 +7685,10 @@
TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreProcessed) {
addConfigurationProperty("touch.deviceType", "touchScreen");
addConfigurationProperty("touch.enableForInactiveViewport", "1");
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
+ DisplayViewport viewport =
+ createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/false, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(viewport);
configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
prepareAxes(POSITION);
MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
@@ -8755,8 +7709,10 @@
TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_AbortTouches) {
addConfigurationProperty("touch.deviceType", "touchScreen");
addConfigurationProperty("touch.enableForInactiveViewport", "0");
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
+ DisplayViewport viewport =
+ createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(viewport);
std::optional<DisplayViewport> optionalDisplayViewport =
mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
ASSERT_TRUE(optionalDisplayViewport.has_value());
@@ -8811,12 +7767,10 @@
TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_TouchesNotAborted) {
addConfigurationProperty("touch.deviceType", "touchScreen");
addConfigurationProperty("touch.enableForInactiveViewport", "1");
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
- std::optional<DisplayViewport> optionalDisplayViewport =
- mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
- ASSERT_TRUE(optionalDisplayViewport.has_value());
- DisplayViewport displayViewport = *optionalDisplayViewport;
+ DisplayViewport displayViewport =
+ createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(displayViewport);
configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
prepareAxes(POSITION);
@@ -9549,41 +8503,6 @@
WithToolType(ToolType::STYLUS))));
}
-// --- MultiTouchInputMapperTest_ExternalDevice ---
-
-class MultiTouchInputMapperTest_ExternalDevice : public MultiTouchInputMapperTest {
-protected:
- void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::EXTERNAL); }
-};
-
-/**
- * Expect fallback to internal viewport if device is external and external viewport is not present.
- */
-TEST_F(MultiTouchInputMapperTest_ExternalDevice, Viewports_Fallback) {
- prepareAxes(POSITION);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(ui::ROTATION_0);
- MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
-
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
-
- NotifyMotionArgs motionArgs;
-
- // Expect the event to be sent to the internal viewport,
- // because an external viewport is not present.
- processPosition(mapper, 100, 100);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ui::LogicalDisplayId::DEFAULT, motionArgs.displayId);
-
- // Expect the event to be sent to the external viewport if it is present.
- prepareSecondaryDisplay(ViewportType::EXTERNAL);
- processPosition(mapper, 100, 100);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
-}
-
// TODO(b/281840344): Remove the test when the old touchpad stack is removed. It is currently
// unclear what the behavior of the touchpad logic in TouchInputMapper should do after the
// PointerChoreographer refactor.
@@ -9747,6 +8666,8 @@
* fingers start to move downwards, the gesture should be swipe.
*/
TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthSwipe) {
+ SCOPED_FLAG_OVERRIDE(disable_touch_input_mapper_pointer_usage, false);
+
// The min freeform gesture width is 25units/mm x 30mm = 750
// which is greater than fraction of the diagnal length of the touchpad (349).
// Thus, MaxSwipWidth is 750.
@@ -9807,6 +8728,8 @@
* the gesture should be swipe.
*/
TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthLowResolutionSwipe) {
+ SCOPED_FLAG_OVERRIDE(disable_touch_input_mapper_pointer_usage, false);
+
// The min freeform gesture width is 5units/mm x 30mm = 150
// which is greater than fraction of the diagnal length of the touchpad (349).
// Thus, MaxSwipWidth is the fraction of the diagnal length, 349.
@@ -9866,6 +8789,8 @@
* freeform gestures after two fingers start to move downwards.
*/
TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthFreeform) {
+ SCOPED_FLAG_OVERRIDE(disable_touch_input_mapper_pointer_usage, false);
+
preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
@@ -9961,6 +8886,8 @@
}
TEST_F(MultiTouchPointerModeTest, TwoFingerSwipeOffsets) {
+ SCOPED_FLAG_OVERRIDE(disable_touch_input_mapper_pointer_usage, false);
+
preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -10007,6 +8934,8 @@
}
TEST_F(MultiTouchPointerModeTest, WhenViewportActiveStatusChanged_PointerGestureIsReset) {
+ SCOPED_FLAG_OVERRIDE(disable_touch_input_mapper_pointer_usage, false);
+
preparePointerMode(/*xResolution=*/25, /*yResolution=*/25);
mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
MultiTouchInputMapper& mapper = constructAndAddMapper<MultiTouchInputMapper>();
diff --git a/services/inputflinger/tests/InstrumentedInputReader.cpp b/services/inputflinger/tests/InstrumentedInputReader.cpp
index 110ca5f..53fc8a1 100644
--- a/services/inputflinger/tests/InstrumentedInputReader.cpp
+++ b/services/inputflinger/tests/InstrumentedInputReader.cpp
@@ -38,13 +38,14 @@
}
std::shared_ptr<InputDevice> InstrumentedInputReader::createDeviceLocked(
- nsecs_t when, int32_t eventHubId, const InputDeviceIdentifier& identifier) REQUIRES(mLock) {
+ nsecs_t when, int32_t eventHubId, const InputDeviceIdentifier& identifier,
+ ftl::Flags<InputDeviceClass> classes) REQUIRES(mLock) {
if (!mNextDevices.empty()) {
std::shared_ptr<InputDevice> device(std::move(mNextDevices.front()));
mNextDevices.pop();
return device;
}
- return InputReader::createDeviceLocked(when, eventHubId, identifier);
+ return InputReader::createDeviceLocked(when, eventHubId, identifier, classes);
}
} // namespace android
diff --git a/services/inputflinger/tests/InstrumentedInputReader.h b/services/inputflinger/tests/InstrumentedInputReader.h
index e9c7bb4..9abf30c 100644
--- a/services/inputflinger/tests/InstrumentedInputReader.h
+++ b/services/inputflinger/tests/InstrumentedInputReader.h
@@ -43,8 +43,9 @@
using InputReader::loopOnce;
protected:
- virtual std::shared_ptr<InputDevice> createDeviceLocked(
- nsecs_t when, int32_t eventHubId, const InputDeviceIdentifier& identifier);
+ virtual std::shared_ptr<InputDevice> createDeviceLocked(nsecs_t when, int32_t eventHubId,
+ const InputDeviceIdentifier& identifier,
+ ftl::Flags<InputDeviceClass> classes);
class FakeInputReaderContext : public ContextImpl {
public:
diff --git a/services/inputflinger/tests/InterfaceMocks.h b/services/inputflinger/tests/InterfaceMocks.h
index a43e4e4..06d60ce 100644
--- a/services/inputflinger/tests/InterfaceMocks.h
+++ b/services/inputflinger/tests/InterfaceMocks.h
@@ -68,7 +68,7 @@
MOCK_METHOD(InputReaderPolicyInterface*, getPolicy, (), (override));
MOCK_METHOD(EventHubInterface*, getEventHub, (), (override));
- int32_t getNextId() override { return 1; };
+ int32_t getNextId() const override { return 1; };
MOCK_METHOD(void, updateLedMetaState, (int32_t metaState), (override));
MOCK_METHOD(int32_t, getLedMetaState, (), (override));
@@ -180,6 +180,7 @@
MOCK_METHOD(status_t, enableDevice, (int32_t deviceId), (override));
MOCK_METHOD(status_t, disableDevice, (int32_t deviceId), (override));
MOCK_METHOD(void, sysfsNodeChanged, (const std::string& sysfsNodePath), (override));
+ MOCK_METHOD(bool, setKernelWakeEnabled, (int32_t deviceId, bool enabled), (override));
};
class MockPointerChoreographerPolicyInterface : public PointerChoreographerPolicyInterface {
@@ -187,20 +188,25 @@
MOCK_METHOD(std::shared_ptr<PointerControllerInterface>, createPointerController,
(PointerControllerInterface::ControllerType), (override));
MOCK_METHOD(void, notifyPointerDisplayIdChanged,
- (ui::LogicalDisplayId displayId, const FloatPoint& position), (override));
+ (ui::LogicalDisplayId displayId, const vec2& position), (override));
MOCK_METHOD(bool, isInputMethodConnectionActive, (), (override));
MOCK_METHOD(void, notifyMouseCursorFadedOnTyping, (), (override));
+ MOCK_METHOD(std::optional<vec2>, filterPointerMotionForAccessibility,
+ (const vec2& current, const vec2& delta, const ui::LogicalDisplayId& displayId),
+ (override));
};
class MockInputDevice : public InputDevice {
public:
MockInputDevice(InputReaderContext* context, int32_t id, int32_t generation,
- const InputDeviceIdentifier& identifier)
- : InputDevice(context, id, generation, identifier) {}
+ const InputDeviceIdentifier& identifier, bool isExternal)
+ : InputDevice(context, id, generation, identifier), mIsExternal(isExternal) {}
MOCK_METHOD(uint32_t, getSources, (), (const, override));
MOCK_METHOD(std::optional<DisplayViewport>, getAssociatedViewport, (), (const));
+ MOCK_METHOD(KeyboardType, getKeyboardType, (), (const, override));
MOCK_METHOD(bool, isEnabled, (), ());
+ bool isExternal() override { return mIsExternal; }
MOCK_METHOD(void, dump, (std::string& dump, const std::string& eventHubDevStr), ());
MOCK_METHOD(void, addEmptyEventHubDevice, (int32_t eventHubId), ());
@@ -248,8 +254,6 @@
MOCK_METHOD(int32_t, getMetaState, (), ());
MOCK_METHOD(void, setKeyboardType, (KeyboardType keyboardType), ());
- MOCK_METHOD(void, bumpGeneration, (), ());
-
MOCK_METHOD(const PropertyMap&, getConfiguration, (), (const, override));
MOCK_METHOD(NotifyDeviceResetArgs, notifyReset, (nsecs_t when), ());
@@ -259,5 +263,12 @@
MOCK_METHOD(void, updateLedState, (bool reset), ());
MOCK_METHOD(size_t, getMapperCount, (), ());
+
+ virtual int32_t getGeneration() const override { return mGeneration; }
+ virtual void bumpGeneration() override { mGeneration++; }
+
+private:
+ int32_t mGeneration = 0;
+ const bool mIsExternal;
};
} // namespace android
diff --git a/services/inputflinger/tests/KeyboardInputMapper_test.cpp b/services/inputflinger/tests/KeyboardInputMapper_test.cpp
index 88c25d3..40bbd34 100644
--- a/services/inputflinger/tests/KeyboardInputMapper_test.cpp
+++ b/services/inputflinger/tests/KeyboardInputMapper_test.cpp
@@ -16,26 +16,82 @@
#include "KeyboardInputMapper.h"
-#include <gtest/gtest.h>
+#include <cstdint>
+#include <list>
+#include <memory>
+#include <optional>
+#include <string>
+#include <android/input.h>
+#include <android/keycodes.h>
+#include <com_android_input_flags.h>
+#include <flag_macros.h>
+#include <ftl/flags.h>
+#include <gtest/gtest.h>
+#include <input/DisplayViewport.h>
+#include <input/Input.h>
+#include <input/InputDevice.h>
+#include <ui/LogicalDisplayId.h>
+#include <ui/Rotation.h>
+#include <utils/Errors.h>
+
+#include "EventHub.h"
#include "InputMapperTest.h"
#include "InterfaceMocks.h"
+#include "NotifyArgs.h"
+#include "TestConstants.h"
+#include "TestEventMatchers.h"
#define TAG "KeyboardInputMapper_test"
namespace android {
+using namespace ftl::flag_operators;
using testing::_;
+using testing::AllOf;
+using testing::AnyOf;
using testing::Args;
using testing::DoAll;
+using testing::IsEmpty;
using testing::Return;
+using testing::ReturnArg;
+using testing::SaveArg;
using testing::SetArgPointee;
+using testing::VariantWith;
+
+namespace {
+
+// Arbitrary display properties.
+constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
+constexpr int32_t DISPLAY_WIDTH = 480;
+constexpr int32_t DISPLAY_HEIGHT = 800;
+
+DisplayViewport createPrimaryViewport(ui::Rotation orientation) {
+ const bool isRotated =
+ orientation == ui::Rotation::Rotation90 || orientation == ui::Rotation::Rotation270;
+ DisplayViewport v;
+ v.displayId = DISPLAY_ID;
+ v.orientation = orientation;
+ v.logicalRight = isRotated ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
+ v.logicalBottom = isRotated ? DISPLAY_WIDTH : DISPLAY_HEIGHT;
+ v.physicalRight = isRotated ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
+ v.physicalBottom = isRotated ? DISPLAY_WIDTH : DISPLAY_HEIGHT;
+ v.deviceWidth = isRotated ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
+ v.deviceHeight = isRotated ? DISPLAY_WIDTH : DISPLAY_HEIGHT;
+ v.isActive = true;
+ v.uniqueId = "local:1";
+ return v;
+}
+
+} // namespace
/**
* Unit tests for KeyboardInputMapper.
*/
class KeyboardInputMapperUnitTest : public InputMapperUnitTest {
protected:
+ const KeyboardLayoutInfo DEVICE_KEYBOARD_LAYOUT_INFO = KeyboardLayoutInfo("en-US", "qwerty");
+
sp<FakeInputReaderPolicy> mFakePolicy;
const std::unordered_map<int32_t, int32_t> mKeyCodeMap{{KEY_0, AKEYCODE_0},
{KEY_A, AKEYCODE_A},
@@ -57,9 +113,8 @@
InputMapperUnitTest::SetUp();
// set key-codes expected in tests
- for (const auto& [scanCode, outKeycode] : mKeyCodeMap) {
- EXPECT_CALL(mMockEventHub, mapKey(EVENTHUB_ID, scanCode, _, _, _, _, _))
- .WillRepeatedly(DoAll(SetArgPointee<4>(outKeycode), Return(NO_ERROR)));
+ for (const auto& [evdevCode, outKeycode] : mKeyCodeMap) {
+ addKeyByEvdevCode(evdevCode, outKeycode);
}
mFakePolicy = sp<FakeInputReaderPolicy>::make();
@@ -70,8 +125,85 @@
mMapper = createInputMapper<KeyboardInputMapper>(*mDeviceContext, mReaderConfiguration,
AINPUT_SOURCE_KEYBOARD);
}
+
+ void addKeyByEvdevCode(int32_t evdevCode, int32_t keyCode, int32_t flags = 0) {
+ EXPECT_CALL(mMockEventHub, mapKey(EVENTHUB_ID, evdevCode, _, _, _, _, _))
+ .WillRepeatedly([=](int32_t, int32_t, int32_t, int32_t metaState,
+ int32_t* outKeycode, int32_t* outMetaState,
+ uint32_t* outFlags) {
+ if (outKeycode != nullptr) {
+ *outKeycode = keyCode;
+ }
+ if (outMetaState != nullptr) {
+ *outMetaState = metaState;
+ }
+ if (outFlags != nullptr) {
+ *outFlags = flags;
+ }
+ return NO_ERROR;
+ });
+ }
+
+ void addKeyByUsageCode(int32_t usageCode, int32_t keyCode, int32_t flags = 0) {
+ EXPECT_CALL(mMockEventHub, mapKey(EVENTHUB_ID, _, usageCode, _, _, _, _))
+ .WillRepeatedly([=](int32_t, int32_t, int32_t, int32_t metaState,
+ int32_t* outKeycode, int32_t* outMetaState,
+ uint32_t* outFlags) {
+ if (outKeycode != nullptr) {
+ *outKeycode = keyCode;
+ }
+ if (outMetaState != nullptr) {
+ *outMetaState = metaState;
+ }
+ if (outFlags != nullptr) {
+ *outFlags = flags;
+ }
+ return NO_ERROR;
+ });
+ }
+
+ void setDisplayOrientation(ui::Rotation orientation) {
+ EXPECT_CALL((*mDevice), getAssociatedViewport)
+ .WillRepeatedly(Return(createPrimaryViewport(orientation)));
+ std::list<NotifyArgs> args =
+ mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration,
+ InputReaderConfiguration::Change::DISPLAY_INFO);
+ ASSERT_EQ(0u, args.size());
+ }
+
+ NotifyKeyArgs expectSingleKeyArg(const std::list<NotifyArgs>& args) {
+ EXPECT_EQ(1u, args.size());
+ return std::get<NotifyKeyArgs>(args.front());
+ }
+
+ std::list<NotifyArgs> processKeyAndSync(nsecs_t when, int32_t code, int32_t value) {
+ std::list<NotifyArgs> argsList = process(when, EV_KEY, code, value);
+ argsList += process(when, EV_SYN, SYN_REPORT, 0);
+ return argsList;
+ }
+
+ void testDPadKeyRotation(int32_t originalEvdevCode, int32_t rotatedKeyCode,
+ ui::LogicalDisplayId displayId = DISPLAY_ID) {
+ std::list<NotifyArgs> argsList = processKeyAndSync(ARBITRARY_TIME, originalEvdevCode, 1);
+ NotifyKeyArgs args = expectSingleKeyArg(argsList);
+ ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
+ ASSERT_EQ(originalEvdevCode, args.scanCode);
+ ASSERT_EQ(rotatedKeyCode, args.keyCode);
+ ASSERT_EQ(displayId, args.displayId);
+
+ argsList = processKeyAndSync(ARBITRARY_TIME, originalEvdevCode, 0);
+ args = expectSingleKeyArg(argsList);
+ ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+ ASSERT_EQ(originalEvdevCode, args.scanCode);
+ ASSERT_EQ(rotatedKeyCode, args.keyCode);
+ ASSERT_EQ(displayId, args.displayId);
+ }
};
+TEST_F(KeyboardInputMapperUnitTest, GetSources) {
+ ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, mMapper->getSources());
+}
+
TEST_F(KeyboardInputMapperUnitTest, KeyPressTimestampRecorded) {
nsecs_t when = ARBITRARY_TIME;
std::vector<int32_t> keyCodes{KEY_0, KEY_A, KEY_LEFTCTRL, KEY_RIGHTALT, KEY_LEFTSHIFT};
@@ -79,11 +211,983 @@
.With(Args<0>(when))
.Times(keyCodes.size());
for (int32_t keyCode : keyCodes) {
- process(when, EV_KEY, keyCode, 1);
- process(when, EV_SYN, SYN_REPORT, 0);
- process(when, EV_KEY, keyCode, 0);
- process(when, EV_SYN, SYN_REPORT, 0);
+ processKeyAndSync(when, keyCode, 1);
+ processKeyAndSync(when, keyCode, 0);
}
}
+TEST_F(KeyboardInputMapperUnitTest, RepeatEventsDiscarded) {
+ std::list<NotifyArgs> args;
+ args += processKeyAndSync(ARBITRARY_TIME, KEY_0, 1);
+ args += processKeyAndSync(ARBITRARY_TIME, KEY_0, 2);
+ args += processKeyAndSync(ARBITRARY_TIME, KEY_0, 0);
+
+ EXPECT_THAT(args,
+ ElementsAre(VariantWith<NotifyKeyArgs>(AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN),
+ WithKeyCode(AKEYCODE_0),
+ WithScanCode(KEY_0))),
+ VariantWith<NotifyKeyArgs>(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
+ WithKeyCode(AKEYCODE_0),
+ WithScanCode(KEY_0)))));
+}
+
+TEST_F(KeyboardInputMapperUnitTest, Process_SimpleKeyPress) {
+ const int32_t USAGE_A = 0x070004;
+ addKeyByEvdevCode(KEY_HOME, AKEYCODE_HOME, POLICY_FLAG_WAKE);
+ addKeyByUsageCode(USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
+
+ // Initial metastate is AMETA_NONE.
+ ASSERT_EQ(AMETA_NONE, mMapper->getMetaState());
+
+ // Key down by evdev code.
+ std::list<NotifyArgs> argsList = processKeyAndSync(ARBITRARY_TIME, KEY_HOME, 1);
+ NotifyKeyArgs args = expectSingleKeyArg(argsList);
+ ASSERT_EQ(DEVICE_ID, args.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+ ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
+ ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
+ ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
+ ASSERT_EQ(KEY_HOME, args.scanCode);
+ ASSERT_EQ(AMETA_NONE, args.metaState);
+ ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
+ ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
+ ASSERT_EQ(ARBITRARY_TIME, args.downTime);
+
+ // Key up by evdev code.
+ argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_HOME, 0);
+ args = expectSingleKeyArg(argsList);
+ ASSERT_EQ(DEVICE_ID, args.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+ ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
+ ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+ ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
+ ASSERT_EQ(KEY_HOME, args.scanCode);
+ ASSERT_EQ(AMETA_NONE, args.metaState);
+ ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
+ ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
+ ASSERT_EQ(ARBITRARY_TIME, args.downTime);
+
+ // Key down by usage code.
+ argsList = process(ARBITRARY_TIME, EV_MSC, MSC_SCAN, USAGE_A);
+ argsList += process(ARBITRARY_TIME, EV_KEY, 0, 1);
+ argsList += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
+ args = expectSingleKeyArg(argsList);
+ ASSERT_EQ(DEVICE_ID, args.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+ ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
+ ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
+ ASSERT_EQ(AKEYCODE_A, args.keyCode);
+ ASSERT_EQ(0, args.scanCode);
+ ASSERT_EQ(AMETA_NONE, args.metaState);
+ ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
+ ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
+ ASSERT_EQ(ARBITRARY_TIME, args.downTime);
+
+ // Key up by usage code.
+ argsList = process(ARBITRARY_TIME + 1, EV_MSC, MSC_SCAN, USAGE_A);
+ argsList += process(ARBITRARY_TIME + 1, EV_KEY, 0, 0);
+ argsList += process(ARBITRARY_TIME + 1, EV_SYN, SYN_REPORT, 0);
+ args = expectSingleKeyArg(argsList);
+ ASSERT_EQ(DEVICE_ID, args.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+ ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
+ ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+ ASSERT_EQ(AKEYCODE_A, args.keyCode);
+ ASSERT_EQ(0, args.scanCode);
+ ASSERT_EQ(AMETA_NONE, args.metaState);
+ ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
+ ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
+ ASSERT_EQ(ARBITRARY_TIME, args.downTime);
+}
+
+TEST_F(KeyboardInputMapperUnitTest, Process_UnknownKey) {
+ const int32_t USAGE_UNKNOWN = 0x07ffff;
+ EXPECT_CALL(mMockEventHub, mapKey(EVENTHUB_ID, KEY_UNKNOWN, USAGE_UNKNOWN, _, _, _, _))
+ .WillRepeatedly(Return(NAME_NOT_FOUND));
+
+ // Key down with unknown scan code or usage code.
+ std::list<NotifyArgs> argsList = process(ARBITRARY_TIME, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
+ argsList += process(ARBITRARY_TIME, EV_KEY, KEY_UNKNOWN, 1);
+ argsList += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
+ NotifyKeyArgs args = expectSingleKeyArg(argsList);
+ ASSERT_EQ(DEVICE_ID, args.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+ ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
+ ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
+ ASSERT_EQ(0, args.keyCode);
+ ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
+ ASSERT_EQ(AMETA_NONE, args.metaState);
+ ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
+ ASSERT_EQ(0U, args.policyFlags);
+ ASSERT_EQ(ARBITRARY_TIME, args.downTime);
+
+ // Key up with unknown scan code or usage code.
+ argsList = process(ARBITRARY_TIME + 1, EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
+ argsList += process(ARBITRARY_TIME + 1, EV_KEY, KEY_UNKNOWN, 0);
+ argsList += process(ARBITRARY_TIME + 1, EV_SYN, SYN_REPORT, 0);
+ args = expectSingleKeyArg(argsList);
+ ASSERT_EQ(DEVICE_ID, args.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+ ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
+ ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+ ASSERT_EQ(0, args.keyCode);
+ ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
+ ASSERT_EQ(AMETA_NONE, args.metaState);
+ ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
+ ASSERT_EQ(0U, args.policyFlags);
+ ASSERT_EQ(ARBITRARY_TIME, args.downTime);
+}
+
+/**
+ * Ensure that the readTime is set to the time when the EV_KEY is received.
+ */
+TEST_F(KeyboardInputMapperUnitTest, Process_SendsReadTime) {
+ addKeyByEvdevCode(KEY_HOME, AKEYCODE_HOME);
+
+ // Key down
+ std::list<NotifyArgs> argsList = process(ARBITRARY_TIME, /*readTime=*/12, EV_KEY, KEY_HOME, 1);
+ argsList += process(ARBITRARY_TIME, /*readTime=*/12, EV_SYN, SYN_REPORT, 0);
+ ASSERT_EQ(12, expectSingleKeyArg(argsList).readTime);
+
+ // Key up
+ argsList = process(ARBITRARY_TIME, /*readTime=*/15, EV_KEY, KEY_HOME, 0);
+ argsList += process(ARBITRARY_TIME, /*readTime=*/15, EV_SYN, SYN_REPORT, 0);
+ ASSERT_EQ(15, expectSingleKeyArg(argsList).readTime);
+}
+
+TEST_F(KeyboardInputMapperUnitTest, Process_ShouldUpdateMetaState) {
+ addKeyByEvdevCode(KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT);
+ addKeyByEvdevCode(KEY_A, AKEYCODE_A);
+
+ EXPECT_CALL(mMockInputReaderContext, updateGlobalMetaState()).Times(2);
+
+ // Initial metastate is AMETA_NONE.
+ ASSERT_EQ(AMETA_NONE, mMapper->getMetaState());
+
+ // Metakey down.
+ std::list<NotifyArgs> argsList = processKeyAndSync(ARBITRARY_TIME, KEY_LEFTSHIFT, 1);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, expectSingleKeyArg(argsList).metaState);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mMapper->getMetaState());
+
+ // Key down.
+ argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_A, 1);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, expectSingleKeyArg(argsList).metaState);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mMapper->getMetaState());
+
+ // Key up.
+ argsList = processKeyAndSync(ARBITRARY_TIME + 2, KEY_A, 0);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, expectSingleKeyArg(argsList).metaState);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mMapper->getMetaState());
+
+ // Metakey up.
+ argsList = processKeyAndSync(ARBITRARY_TIME + 3, KEY_LEFTSHIFT, 0);
+ ASSERT_EQ(AMETA_NONE, expectSingleKeyArg(argsList).metaState);
+ ASSERT_EQ(AMETA_NONE, mMapper->getMetaState());
+}
+
+TEST_F(KeyboardInputMapperUnitTest, Process_WhenNotOrientationAware_ShouldNotRotateDPad) {
+ addKeyByEvdevCode(KEY_UP, AKEYCODE_DPAD_UP);
+ addKeyByEvdevCode(KEY_RIGHT, AKEYCODE_DPAD_RIGHT);
+ addKeyByEvdevCode(KEY_DOWN, AKEYCODE_DPAD_DOWN);
+ addKeyByEvdevCode(KEY_LEFT, AKEYCODE_DPAD_LEFT);
+
+ setDisplayOrientation(ui::Rotation::Rotation90);
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(KEY_UP, AKEYCODE_DPAD_UP));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(KEY_RIGHT, AKEYCODE_DPAD_RIGHT));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(KEY_DOWN, AKEYCODE_DPAD_DOWN));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(KEY_LEFT, AKEYCODE_DPAD_LEFT));
+}
+
+TEST_F(KeyboardInputMapperUnitTest, Process_WhenOrientationAware_ShouldRotateDPad) {
+ addKeyByEvdevCode(KEY_UP, AKEYCODE_DPAD_UP);
+ addKeyByEvdevCode(KEY_RIGHT, AKEYCODE_DPAD_RIGHT);
+ addKeyByEvdevCode(KEY_DOWN, AKEYCODE_DPAD_DOWN);
+ addKeyByEvdevCode(KEY_LEFT, AKEYCODE_DPAD_LEFT);
+
+ mPropertyMap.addProperty("keyboard.orientationAware", "1");
+ mMapper = createInputMapper<KeyboardInputMapper>(*mDeviceContext, mReaderConfiguration,
+ AINPUT_SOURCE_KEYBOARD);
+ setDisplayOrientation(ui::ROTATION_0);
+
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(KEY_UP, AKEYCODE_DPAD_UP));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(KEY_RIGHT, AKEYCODE_DPAD_RIGHT));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(KEY_DOWN, AKEYCODE_DPAD_DOWN));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(KEY_LEFT, AKEYCODE_DPAD_LEFT));
+
+ setDisplayOrientation(ui::ROTATION_90);
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(KEY_UP, AKEYCODE_DPAD_LEFT));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(KEY_RIGHT, AKEYCODE_DPAD_UP));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(KEY_DOWN, AKEYCODE_DPAD_RIGHT));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(KEY_LEFT, AKEYCODE_DPAD_DOWN));
+
+ setDisplayOrientation(ui::ROTATION_180);
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(KEY_UP, AKEYCODE_DPAD_DOWN));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(KEY_RIGHT, AKEYCODE_DPAD_LEFT));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(KEY_DOWN, AKEYCODE_DPAD_UP));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(KEY_LEFT, AKEYCODE_DPAD_RIGHT));
+
+ setDisplayOrientation(ui::ROTATION_270);
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(KEY_UP, AKEYCODE_DPAD_RIGHT));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(KEY_RIGHT, AKEYCODE_DPAD_DOWN));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(KEY_DOWN, AKEYCODE_DPAD_LEFT));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(KEY_LEFT, AKEYCODE_DPAD_UP));
+
+ // Special case: if orientation changes while key is down, we still emit the same keycode
+ // in the key up as we did in the key down.
+ setDisplayOrientation(ui::ROTATION_270);
+ std::list<NotifyArgs> argsList = processKeyAndSync(ARBITRARY_TIME, KEY_UP, 1);
+ NotifyKeyArgs args = expectSingleKeyArg(argsList);
+ ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
+ ASSERT_EQ(KEY_UP, args.scanCode);
+ ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
+
+ setDisplayOrientation(ui::ROTATION_180);
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_UP, 0);
+ args = expectSingleKeyArg(argsList);
+ ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+ ASSERT_EQ(KEY_UP, args.scanCode);
+ ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
+}
+
+TEST_F(KeyboardInputMapperUnitTest, DisplayIdConfigurationChange_NotOrientationAware) {
+ // If the keyboard is not orientation aware,
+ // key events should not be associated with a specific display id
+ addKeyByEvdevCode(KEY_UP, AKEYCODE_DPAD_UP);
+
+ // Display id should be LogicalDisplayId::INVALID without any display configuration.
+ std::list<NotifyArgs> argsList = processKeyAndSync(ARBITRARY_TIME, KEY_UP, 1);
+ ASSERT_GT(argsList.size(), 0u);
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_UP, 0);
+ ASSERT_GT(argsList.size(), 0u);
+ ASSERT_EQ(ui::LogicalDisplayId::INVALID, std::get<NotifyKeyArgs>(argsList.front()).displayId);
+}
+
+TEST_F(KeyboardInputMapperUnitTest, DisplayIdConfigurationChange_OrientationAware) {
+ // If the keyboard is orientation aware,
+ // key events should be associated with the internal viewport
+ addKeyByEvdevCode(KEY_UP, AKEYCODE_DPAD_UP);
+
+ mPropertyMap.addProperty("keyboard.orientationAware", "1");
+ mMapper = createInputMapper<KeyboardInputMapper>(*mDeviceContext, mReaderConfiguration,
+ AINPUT_SOURCE_KEYBOARD);
+
+ // Display id should be LogicalDisplayId::INVALID without any display configuration.
+ // ^--- already checked by the previous test
+
+ setDisplayOrientation(ui::ROTATION_0);
+ std::list<NotifyArgs> argsList = processKeyAndSync(ARBITRARY_TIME, KEY_UP, 1);
+ ASSERT_GT(argsList.size(), 0u);
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_UP, 0);
+ ASSERT_GT(argsList.size(), 0u);
+ ASSERT_EQ(DISPLAY_ID, std::get<NotifyKeyArgs>(argsList.front()).displayId);
+
+ constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
+ DisplayViewport newViewport = createPrimaryViewport(ui::ROTATION_0);
+ newViewport.displayId = newDisplayId;
+ EXPECT_CALL((*mDevice), getAssociatedViewport).WillRepeatedly(Return(newViewport));
+ argsList = mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration,
+ InputReaderConfiguration::Change::DISPLAY_INFO);
+ ASSERT_EQ(0u, argsList.size());
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_UP, 1);
+ ASSERT_GT(argsList.size(), 0u);
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_UP, 0);
+ ASSERT_GT(argsList.size(), 0u);
+ ASSERT_EQ(newDisplayId, std::get<NotifyKeyArgs>(argsList.front()).displayId);
+}
+
+TEST_F(KeyboardInputMapperUnitTest, GetKeyCodeState) {
+ EXPECT_CALL(mMockEventHub, getKeyCodeState(EVENTHUB_ID, AKEYCODE_A))
+ .WillRepeatedly(Return(AKEY_STATE_DOWN));
+ ASSERT_EQ(AKEY_STATE_DOWN, mMapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
+
+ EXPECT_CALL(mMockEventHub, getKeyCodeState(EVENTHUB_ID, AKEYCODE_A))
+ .WillRepeatedly(Return(AKEY_STATE_UP));
+ ASSERT_EQ(AKEY_STATE_UP, mMapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
+}
+
+TEST_F(KeyboardInputMapperUnitTest, GetKeyCodeForKeyLocation) {
+ EXPECT_CALL(mMockEventHub, getKeyCodeForKeyLocation(EVENTHUB_ID, _))
+ .WillRepeatedly(ReturnArg<1>());
+ EXPECT_CALL(mMockEventHub, getKeyCodeForKeyLocation(EVENTHUB_ID, AKEYCODE_Y))
+ .WillRepeatedly(Return(AKEYCODE_Z));
+ ASSERT_EQ(AKEYCODE_Z, mMapper->getKeyCodeForKeyLocation(AKEYCODE_Y))
+ << "If a mapping is available, the result is equal to the mapping";
+
+ ASSERT_EQ(AKEYCODE_A, mMapper->getKeyCodeForKeyLocation(AKEYCODE_A))
+ << "If no mapping is available, the result is the key location";
+}
+
+TEST_F(KeyboardInputMapperUnitTest, GetScanCodeState) {
+ EXPECT_CALL(mMockEventHub, getScanCodeState(EVENTHUB_ID, KEY_A))
+ .WillRepeatedly(Return(AKEY_STATE_DOWN));
+ ASSERT_EQ(AKEY_STATE_DOWN, mMapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
+
+ EXPECT_CALL(mMockEventHub, getScanCodeState(EVENTHUB_ID, KEY_A))
+ .WillRepeatedly(Return(AKEY_STATE_UP));
+ ASSERT_EQ(AKEY_STATE_UP, mMapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
+}
+
+TEST_F(KeyboardInputMapperUnitTest, Process_LockedKeysShouldToggleMetaStateAndLeds) {
+ EXPECT_CALL(mMockEventHub,
+ hasLed(EVENTHUB_ID, AnyOf(LED_CAPSL, LED_NUML, LED_SCROLLL /*NOTYPO*/)))
+ .WillRepeatedly(Return(true));
+ bool capsLockLed = true; // Initially on
+ bool numLockLed = false; // Initially off
+ bool scrollLockLed = false; // Initially off
+ EXPECT_CALL(mMockEventHub, setLedState(EVENTHUB_ID, LED_CAPSL, _))
+ .WillRepeatedly(SaveArg<2>(&capsLockLed));
+ EXPECT_CALL(mMockEventHub, setLedState(EVENTHUB_ID, LED_NUML, _))
+ .WillRepeatedly(SaveArg<2>(&numLockLed));
+ EXPECT_CALL(mMockEventHub, setLedState(EVENTHUB_ID, LED_SCROLLL /*NOTYPO*/, _))
+ .WillRepeatedly(SaveArg<2>(&scrollLockLed));
+ addKeyByEvdevCode(KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK);
+ addKeyByEvdevCode(KEY_NUMLOCK, AKEYCODE_NUM_LOCK);
+ addKeyByEvdevCode(KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK);
+
+ // In real operation, mappers pass new LED states to InputReader (via the context), which then
+ // calls back to the mappers to apply that state. Mimic the same thing here with mocks.
+ int32_t ledMetaState;
+ EXPECT_CALL(mMockInputReaderContext, updateLedMetaState(_))
+ .WillRepeatedly([&](int32_t newState) {
+ ledMetaState = newState;
+ mMapper->updateLedState(false);
+ });
+ EXPECT_CALL(mMockInputReaderContext, getLedMetaState())
+ .WillRepeatedly(testing::ReturnPointee(&ledMetaState));
+
+ ASSERT_THAT(mMapper->reset(ARBITRARY_TIME), IsEmpty());
+
+ // Initial metastate is AMETA_NONE.
+ ASSERT_EQ(AMETA_NONE, mMapper->getMetaState());
+
+ // Initialization should have turned all of the lights off.
+ ASSERT_FALSE(capsLockLed);
+ ASSERT_FALSE(numLockLed);
+ ASSERT_FALSE(scrollLockLed);
+
+ // Toggle caps lock on.
+ std::list<NotifyArgs> argsList = processKeyAndSync(ARBITRARY_TIME, KEY_CAPSLOCK, 1);
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_CAPSLOCK, 0);
+ ASSERT_TRUE(capsLockLed);
+ ASSERT_FALSE(numLockLed);
+ ASSERT_FALSE(scrollLockLed);
+ ASSERT_EQ(AMETA_CAPS_LOCK_ON, mMapper->getMetaState());
+
+ // Toggle num lock on.
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_NUMLOCK, 1);
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_NUMLOCK, 0);
+ ASSERT_TRUE(capsLockLed);
+ ASSERT_TRUE(numLockLed);
+ ASSERT_FALSE(scrollLockLed);
+ ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mMapper->getMetaState());
+
+ // Toggle caps lock off.
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_CAPSLOCK, 1);
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_CAPSLOCK, 0);
+ ASSERT_FALSE(capsLockLed);
+ ASSERT_TRUE(numLockLed);
+ ASSERT_FALSE(scrollLockLed);
+ ASSERT_EQ(AMETA_NUM_LOCK_ON, mMapper->getMetaState());
+
+ // Toggle scroll lock on.
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_SCROLLLOCK, 1);
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_SCROLLLOCK, 0);
+ ASSERT_FALSE(capsLockLed);
+ ASSERT_TRUE(numLockLed);
+ ASSERT_TRUE(scrollLockLed);
+ ASSERT_EQ(AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mMapper->getMetaState());
+
+ // Toggle num lock off.
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_NUMLOCK, 1);
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_NUMLOCK, 0);
+ ASSERT_FALSE(capsLockLed);
+ ASSERT_FALSE(numLockLed);
+ ASSERT_TRUE(scrollLockLed);
+ ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mMapper->getMetaState());
+
+ // Toggle scroll lock off.
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_SCROLLLOCK, 1);
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_SCROLLLOCK, 0);
+ ASSERT_FALSE(capsLockLed);
+ ASSERT_FALSE(numLockLed);
+ ASSERT_FALSE(scrollLockLed);
+ ASSERT_EQ(AMETA_NONE, mMapper->getMetaState());
+}
+
+TEST_F(KeyboardInputMapperUnitTest, DisablingDeviceResetsPressedKeys) {
+ const int32_t USAGE_A = 0x070004;
+ addKeyByEvdevCode(KEY_HOME, AKEYCODE_HOME, POLICY_FLAG_WAKE);
+ addKeyByUsageCode(USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
+
+ // Key down by evdev code.
+ std::list<NotifyArgs> argsList = processKeyAndSync(ARBITRARY_TIME, KEY_HOME, 1);
+ NotifyKeyArgs args = expectSingleKeyArg(argsList);
+ ASSERT_EQ(DEVICE_ID, args.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+ ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
+ ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
+ ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
+ ASSERT_EQ(KEY_HOME, args.scanCode);
+ ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
+
+ // Disable device, it should synthesize cancellation events for down events.
+ mReaderConfiguration.disabledDevices.insert(DEVICE_ID);
+ argsList = mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration,
+ InputReaderConfiguration::Change::ENABLED_STATE);
+ argsList += mMapper->reset(ARBITRARY_TIME);
+ args = expectSingleKeyArg(argsList);
+ ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+ ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
+ ASSERT_EQ(KEY_HOME, args.scanCode);
+ ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_CANCELED, args.flags);
+}
+
+TEST_F(KeyboardInputMapperUnitTest, Configure_AssignKeyboardLayoutInfo) {
+ std::list<NotifyArgs> unused =
+ mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration, /*changes=*/{});
+
+ int32_t generation = mDevice->getGeneration();
+ mReaderConfiguration.keyboardLayoutAssociations.insert(
+ {mIdentifier.location, DEVICE_KEYBOARD_LAYOUT_INFO});
+
+ unused += mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration,
+ InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
+
+ InputDeviceInfo deviceInfo;
+ mMapper->populateDeviceInfo(deviceInfo);
+ ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.languageTag,
+ deviceInfo.getKeyboardLayoutInfo()->languageTag);
+ ASSERT_EQ(DEVICE_KEYBOARD_LAYOUT_INFO.layoutType,
+ deviceInfo.getKeyboardLayoutInfo()->layoutType);
+ ASSERT_GT(mDevice->getGeneration(), generation);
+
+ // Call change layout association with the same values: Generation shouldn't change
+ generation = mDevice->getGeneration();
+ unused += mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration,
+ InputReaderConfiguration::Change::KEYBOARD_LAYOUT_ASSOCIATION);
+ ASSERT_EQ(mDevice->getGeneration(), generation);
+}
+
+TEST_F(KeyboardInputMapperUnitTest, LayoutInfoCorrectlyMapped) {
+ EXPECT_CALL(mMockEventHub, getRawLayoutInfo(EVENTHUB_ID))
+ .WillRepeatedly(Return(RawLayoutInfo{.languageTag = "en", .layoutType = "extended"}));
+
+ // Configuration
+ std::list<NotifyArgs> unused =
+ mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration, /*changes=*/{});
+
+ InputDeviceInfo deviceInfo;
+ mMapper->populateDeviceInfo(deviceInfo);
+ ASSERT_EQ("en", deviceInfo.getKeyboardLayoutInfo()->languageTag);
+ ASSERT_EQ("extended", deviceInfo.getKeyboardLayoutInfo()->layoutType);
+}
+
+TEST_F(KeyboardInputMapperUnitTest, Process_GestureEventToSetFlagKeepTouchMode) {
+ addKeyByEvdevCode(KEY_LEFT, AKEYCODE_DPAD_LEFT, POLICY_FLAG_GESTURE);
+
+ // Key down
+ std::list<NotifyArgs> argsList = processKeyAndSync(ARBITRARY_TIME, KEY_LEFT, 1);
+ ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_KEEP_TOUCH_MODE,
+ expectSingleKeyArg(argsList).flags);
+}
+
+TEST_F_WITH_FLAGS(KeyboardInputMapperUnitTest, WakeBehavior_AlphabeticKeyboard,
+ REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
+ enable_alphabetic_keyboard_wake))) {
+ // For internal alphabetic devices, keys will trigger wake on key down.
+
+ addKeyByEvdevCode(KEY_A, AKEYCODE_A);
+ addKeyByEvdevCode(KEY_HOME, AKEYCODE_HOME);
+ addKeyByEvdevCode(KEY_PLAYPAUSE, AKEYCODE_MEDIA_PLAY_PAUSE);
+
+ std::list<NotifyArgs> argsList = processKeyAndSync(ARBITRARY_TIME, KEY_A, 1);
+ ASSERT_EQ(POLICY_FLAG_WAKE, expectSingleKeyArg(argsList).policyFlags);
+
+ argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_A, 0);
+ ASSERT_EQ(uint32_t(0), expectSingleKeyArg(argsList).policyFlags);
+
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_HOME, 1);
+ ASSERT_EQ(POLICY_FLAG_WAKE, expectSingleKeyArg(argsList).policyFlags);
+
+ argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_HOME, 0);
+ ASSERT_EQ(uint32_t(0), expectSingleKeyArg(argsList).policyFlags);
+
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_PLAYPAUSE, 1);
+ ASSERT_EQ(POLICY_FLAG_WAKE, expectSingleKeyArg(argsList).policyFlags);
+
+ argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_PLAYPAUSE, 0);
+ ASSERT_EQ(uint32_t(0), expectSingleKeyArg(argsList).policyFlags);
+}
+
+// --- KeyboardInputMapperTest ---
+
+// TODO(b/283812079): convert the tests for this class, which use multiple mappers each, to use
+// InputMapperUnitTest.
+class KeyboardInputMapperTest : public InputMapperTest {
+protected:
+ void SetUp() override {
+ InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::KEYBOARD |
+ InputDeviceClass::ALPHAKEY);
+ }
+ const std::string UNIQUE_ID = "local:0";
+
+ void testDPadKeyRotation(KeyboardInputMapper& mapper, int32_t originalEvdevCode,
+ int32_t rotatedKeyCode,
+ ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID);
+
+ void processKeyAndSync(InputMapper& mapper, nsecs_t when, nsecs_t readTime, int32_t code,
+ int32_t value) {
+ process(mapper, when, readTime, EV_KEY, code, value);
+ process(mapper, when, readTime, EV_SYN, SYN_REPORT, 0);
+ }
+};
+
+void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper& mapper,
+ int32_t originalEvdevCode, int32_t rotatedKeyCode,
+ ui::LogicalDisplayId displayId) {
+ NotifyKeyArgs args;
+
+ processKeyAndSync(mapper, ARBITRARY_TIME, READ_TIME, originalEvdevCode, 1);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
+ ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
+ ASSERT_EQ(originalEvdevCode, args.scanCode);
+ ASSERT_EQ(rotatedKeyCode, args.keyCode);
+ ASSERT_EQ(displayId, args.displayId);
+
+ processKeyAndSync(mapper, ARBITRARY_TIME, READ_TIME, originalEvdevCode, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
+ ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+ ASSERT_EQ(originalEvdevCode, args.scanCode);
+ ASSERT_EQ(rotatedKeyCode, args.keyCode);
+ ASSERT_EQ(displayId, args.displayId);
+}
+
+TEST_F(KeyboardInputMapperTest, Configure_AssignsDisplayPort) {
+ // keyboard 1.
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
+
+ // keyboard 2.
+ const std::string USB2 = "USB2";
+ const std::string DEVICE_NAME2 = "KEYBOARD2";
+ constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
+ constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
+ std::shared_ptr<InputDevice> device2 =
+ newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
+ ftl::Flags<InputDeviceClass>(0));
+
+ mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
+ mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
+ mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
+ mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
+
+ KeyboardInputMapper& mapper =
+ constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
+
+ device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
+ KeyboardInputMapper& mapper2 =
+ device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
+ mFakePolicy
+ ->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD);
+ std::list<NotifyArgs> unused =
+ device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
+ /*changes=*/{});
+ unused += device2->reset(ARBITRARY_TIME);
+
+ // Prepared displays and associated info.
+ constexpr uint8_t hdmi1 = 0;
+ constexpr uint8_t hdmi2 = 1;
+ const std::string SECONDARY_UNIQUE_ID = "local:1";
+
+ mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1);
+ mFakePolicy->addInputPortAssociation(USB2, hdmi2);
+
+ // No associated display viewport found, should disable the device.
+ unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
+ InputReaderConfiguration::Change::DISPLAY_INFO);
+ ASSERT_FALSE(device2->isEnabled());
+
+ // Prepare second display.
+ constexpr ui::LogicalDisplayId newDisplayId = ui::LogicalDisplayId{2};
+ setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ UNIQUE_ID, hdmi1, ViewportType::INTERNAL);
+ setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ SECONDARY_UNIQUE_ID, hdmi2, ViewportType::EXTERNAL);
+ // Default device will reconfigure above, need additional reconfiguration for another device.
+ unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
+ InputReaderConfiguration::Change::DISPLAY_INFO);
+
+ // Device should be enabled after the associated display is found.
+ ASSERT_TRUE(mDevice->isEnabled());
+ ASSERT_TRUE(device2->isEnabled());
+
+ // Test pad key events
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
+ ASSERT_NO_FATAL_FAILURE(
+ testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_DOWN, AKEYCODE_DPAD_DOWN, DISPLAY_ID));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_LEFT, AKEYCODE_DPAD_LEFT, DISPLAY_ID));
+
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper2, KEY_UP, AKEYCODE_DPAD_UP, newDisplayId));
+ ASSERT_NO_FATAL_FAILURE(
+ testDPadKeyRotation(mapper2, KEY_RIGHT, AKEYCODE_DPAD_RIGHT, newDisplayId));
+ ASSERT_NO_FATAL_FAILURE(
+ testDPadKeyRotation(mapper2, KEY_DOWN, AKEYCODE_DPAD_DOWN, newDisplayId));
+ ASSERT_NO_FATAL_FAILURE(
+ testDPadKeyRotation(mapper2, KEY_LEFT, AKEYCODE_DPAD_LEFT, newDisplayId));
+}
+
+TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleAfterReattach) {
+ mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
+ mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
+ mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
+
+ KeyboardInputMapper& mapper =
+ constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
+ // Initial metastate is AMETA_NONE.
+ ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
+
+ // Initialization should have turned all of the lights off.
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
+
+ // Toggle caps lock on.
+ processKeyAndSync(mapper, ARBITRARY_TIME, READ_TIME, KEY_CAPSLOCK, 1);
+ processKeyAndSync(mapper, ARBITRARY_TIME, READ_TIME, KEY_CAPSLOCK, 0);
+ ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
+ ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
+
+ // Toggle num lock on.
+ processKeyAndSync(mapper, ARBITRARY_TIME, READ_TIME, KEY_NUMLOCK, 1);
+ processKeyAndSync(mapper, ARBITRARY_TIME, READ_TIME, KEY_NUMLOCK, 0);
+ ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
+ ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
+
+ // Toggle scroll lock on.
+ processKeyAndSync(mapper, ARBITRARY_TIME, READ_TIME, KEY_SCROLLLOCK, 1);
+ processKeyAndSync(mapper, ARBITRARY_TIME, READ_TIME, KEY_SCROLLLOCK, 0);
+ ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
+ ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
+
+ mFakeEventHub->removeDevice(EVENTHUB_ID);
+ mReader->loopOnce();
+
+ // keyboard 2 should default toggle keys.
+ const std::string USB2 = "USB2";
+ const std::string DEVICE_NAME2 = "KEYBOARD2";
+ constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
+ constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
+ std::shared_ptr<InputDevice> device2 =
+ newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
+ ftl::Flags<InputDeviceClass>(0));
+ mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
+ mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
+ mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
+ mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
+ mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
+ mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
+
+ device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
+ KeyboardInputMapper& mapper2 =
+ device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
+ mFakePolicy
+ ->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD);
+ std::list<NotifyArgs> unused =
+ device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
+ /*changes=*/{});
+ unused += device2->reset(ARBITRARY_TIME);
+
+ ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_CAPSL));
+ ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_NUML));
+ ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_SCROLLL));
+ ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON,
+ mapper2.getMetaState());
+}
+
+TEST_F(KeyboardInputMapperTest, Process_toggleCapsLockState) {
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
+
+ // Suppose we have two mappers. (DPAD + KEYBOARD)
+ constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD);
+ KeyboardInputMapper& mapper =
+ constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
+ // Initial metastate is AMETA_NONE.
+ ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
+
+ mReader->toggleCapsLockState(DEVICE_ID);
+ ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
+}
+
+TEST_F(KeyboardInputMapperTest, Process_ResetLockedModifierState) {
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
+
+ KeyboardInputMapper& mapper =
+ constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
+ // Initial metastate is AMETA_NONE.
+ ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
+
+ // Toggle caps lock on.
+ processKeyAndSync(mapper, ARBITRARY_TIME, READ_TIME, KEY_CAPSLOCK, 1);
+ processKeyAndSync(mapper, ARBITRARY_TIME, READ_TIME, KEY_CAPSLOCK, 0);
+
+ // Toggle num lock on.
+ processKeyAndSync(mapper, ARBITRARY_TIME, READ_TIME, KEY_NUMLOCK, 1);
+ processKeyAndSync(mapper, ARBITRARY_TIME, READ_TIME, KEY_NUMLOCK, 0);
+
+ // Toggle scroll lock on.
+ processKeyAndSync(mapper, ARBITRARY_TIME, READ_TIME, KEY_SCROLLLOCK, 1);
+ processKeyAndSync(mapper, ARBITRARY_TIME, READ_TIME, KEY_SCROLLLOCK, 0);
+ ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
+
+ mReader->resetLockedModifierState();
+ ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
+}
+
+TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleInMultiDevices) {
+ // keyboard 1.
+ mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
+ mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
+ mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
+
+ KeyboardInputMapper& mapper1 =
+ constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
+
+ // keyboard 2.
+ const std::string USB2 = "USB2";
+ const std::string DEVICE_NAME2 = "KEYBOARD2";
+ constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
+ constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
+ std::shared_ptr<InputDevice> device2 =
+ newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
+ ftl::Flags<InputDeviceClass>(0));
+ mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
+ mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
+ mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
+ mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
+ mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
+ mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
+
+ device2->addEmptyEventHubDevice(SECOND_EVENTHUB_ID);
+ KeyboardInputMapper& mapper2 =
+ device2->constructAndAddMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID,
+ mFakePolicy
+ ->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD);
+ std::list<NotifyArgs> unused =
+ device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
+ /*changes=*/{});
+ unused += device2->reset(ARBITRARY_TIME);
+
+ // Initial metastate is AMETA_NONE.
+ ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
+ ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
+
+ // Toggle num lock on and off.
+ processKeyAndSync(mapper1, ARBITRARY_TIME, READ_TIME, KEY_NUMLOCK, 1);
+ processKeyAndSync(mapper1, ARBITRARY_TIME, READ_TIME, KEY_NUMLOCK, 0);
+ ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
+ ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper1.getMetaState());
+ ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper2.getMetaState());
+
+ processKeyAndSync(mapper1, ARBITRARY_TIME, READ_TIME, KEY_NUMLOCK, 1);
+ processKeyAndSync(mapper1, ARBITRARY_TIME, READ_TIME, KEY_NUMLOCK, 0);
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
+ ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
+ ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
+
+ // Toggle caps lock on and off.
+ processKeyAndSync(mapper1, ARBITRARY_TIME, READ_TIME, KEY_CAPSLOCK, 1);
+ processKeyAndSync(mapper1, ARBITRARY_TIME, READ_TIME, KEY_CAPSLOCK, 0);
+ ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
+ ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper1.getMetaState());
+ ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper2.getMetaState());
+
+ processKeyAndSync(mapper1, ARBITRARY_TIME, READ_TIME, KEY_CAPSLOCK, 1);
+ processKeyAndSync(mapper1, ARBITRARY_TIME, READ_TIME, KEY_CAPSLOCK, 0);
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
+ ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
+ ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
+
+ // Toggle scroll lock on and off.
+ processKeyAndSync(mapper1, ARBITRARY_TIME, READ_TIME, KEY_SCROLLLOCK, 1);
+ processKeyAndSync(mapper1, ARBITRARY_TIME, READ_TIME, KEY_SCROLLLOCK, 0);
+ ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
+ ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper1.getMetaState());
+ ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper2.getMetaState());
+
+ processKeyAndSync(mapper1, ARBITRARY_TIME, READ_TIME, KEY_SCROLLLOCK, 1);
+ processKeyAndSync(mapper1, ARBITRARY_TIME, READ_TIME, KEY_SCROLLLOCK, 0);
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
+ ASSERT_EQ(AMETA_NONE, mapper1.getMetaState());
+ ASSERT_EQ(AMETA_NONE, mapper2.getMetaState());
+}
+
+/**
+ * When there is more than one KeyboardInputMapper for an InputDevice, each mapper should produce
+ * events that use the shared keyboard source across all mappers. This is to ensure that each
+ * input device generates key events in a consistent manner, regardless of which mapper produces
+ * the event.
+ */
+TEST_F(KeyboardInputMapperTest, UsesSharedKeyboardSource) {
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
+
+ // Add a mapper with SOURCE_KEYBOARD
+ KeyboardInputMapper& keyboardMapper =
+ constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD);
+
+ processKeyAndSync(keyboardMapper, ARBITRARY_TIME, 0, KEY_HOME, 1);
+ ASSERT_NO_FATAL_FAILURE(
+ mFakeListener->assertNotifyKeyWasCalled(WithSource(AINPUT_SOURCE_KEYBOARD)));
+ processKeyAndSync(keyboardMapper, ARBITRARY_TIME, 0, KEY_HOME, 0);
+ ASSERT_NO_FATAL_FAILURE(
+ mFakeListener->assertNotifyKeyWasCalled(WithSource(AINPUT_SOURCE_KEYBOARD)));
+
+ // Add a mapper with SOURCE_DPAD
+ KeyboardInputMapper& dpadMapper =
+ constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_DPAD);
+ for (auto* mapper : {&keyboardMapper, &dpadMapper}) {
+ processKeyAndSync(*mapper, ARBITRARY_TIME, 0, KEY_HOME, 1);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
+ WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD)));
+ processKeyAndSync(*mapper, ARBITRARY_TIME, 0, KEY_HOME, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
+ WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD)));
+ }
+
+ // Add a mapper with SOURCE_GAMEPAD
+ KeyboardInputMapper& gamepadMapper =
+ constructAndAddMapper<KeyboardInputMapper>(AINPUT_SOURCE_GAMEPAD);
+ for (auto* mapper : {&keyboardMapper, &dpadMapper, &gamepadMapper}) {
+ processKeyAndSync(*mapper, ARBITRARY_TIME, 0, KEY_HOME, 1);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
+ WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD)));
+ processKeyAndSync(*mapper, ARBITRARY_TIME, 0, KEY_HOME, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(
+ WithSource(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD | AINPUT_SOURCE_GAMEPAD)));
+ }
+}
+
+// --- KeyboardInputMapperTest_ExternalAlphabeticDevice ---
+
+class KeyboardInputMapperTest_ExternalAlphabeticDevice : public KeyboardInputMapperUnitTest {
+protected:
+ void SetUp() override {
+ InputMapperUnitTest::SetUp(/*bus=*/0, /*isExternal=*/true);
+ ON_CALL((*mDevice), getSources).WillByDefault(Return(AINPUT_SOURCE_KEYBOARD));
+ ON_CALL((*mDevice), getKeyboardType).WillByDefault(Return(KeyboardType::ALPHABETIC));
+ EXPECT_CALL(mMockEventHub, getDeviceClasses(EVENTHUB_ID))
+ .WillRepeatedly(Return(InputDeviceClass::KEYBOARD | InputDeviceClass::ALPHAKEY |
+ InputDeviceClass::EXTERNAL));
+ mMapper = createInputMapper<KeyboardInputMapper>(*mDeviceContext, mReaderConfiguration,
+ AINPUT_SOURCE_KEYBOARD);
+ }
+};
+
+// --- KeyboardInputMapperTest_ExternalNonAlphabeticDevice ---
+
+class KeyboardInputMapperTest_ExternalNonAlphabeticDevice : public KeyboardInputMapperUnitTest {
+protected:
+ void SetUp() override {
+ InputMapperUnitTest::SetUp(/*bus=*/0, /*isExternal=*/true);
+ ON_CALL((*mDevice), getSources).WillByDefault(Return(AINPUT_SOURCE_KEYBOARD));
+ ON_CALL((*mDevice), getKeyboardType).WillByDefault(Return(KeyboardType::NON_ALPHABETIC));
+ EXPECT_CALL(mMockEventHub, getDeviceClasses(EVENTHUB_ID))
+ .WillRepeatedly(Return(InputDeviceClass::KEYBOARD | InputDeviceClass::EXTERNAL));
+ mMapper = createInputMapper<KeyboardInputMapper>(*mDeviceContext, mReaderConfiguration,
+ AINPUT_SOURCE_KEYBOARD);
+ }
+};
+
+TEST_F(KeyboardInputMapperTest_ExternalAlphabeticDevice, WakeBehavior_AlphabeticKeyboard) {
+ // For external devices, keys will trigger wake on key down. Media keys should also trigger
+ // wake if triggered from external devices.
+
+ addKeyByEvdevCode(KEY_HOME, AKEYCODE_HOME);
+ addKeyByEvdevCode(KEY_PLAY, AKEYCODE_MEDIA_PLAY);
+ addKeyByEvdevCode(KEY_PLAYPAUSE, AKEYCODE_MEDIA_PLAY_PAUSE, POLICY_FLAG_WAKE);
+
+ std::list<NotifyArgs> argsList = processKeyAndSync(ARBITRARY_TIME, KEY_HOME, 1);
+ ASSERT_EQ(POLICY_FLAG_WAKE, expectSingleKeyArg(argsList).policyFlags);
+
+ argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_HOME, 0);
+ ASSERT_EQ(uint32_t(0), expectSingleKeyArg(argsList).policyFlags);
+
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_PLAY, 1);
+ ASSERT_EQ(POLICY_FLAG_WAKE, expectSingleKeyArg(argsList).policyFlags);
+
+ argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_PLAY, 0);
+ ASSERT_EQ(uint32_t(0), expectSingleKeyArg(argsList).policyFlags);
+
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_PLAYPAUSE, 1);
+ ASSERT_EQ(POLICY_FLAG_WAKE, expectSingleKeyArg(argsList).policyFlags);
+
+ argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_PLAYPAUSE, 0);
+ ASSERT_EQ(POLICY_FLAG_WAKE, expectSingleKeyArg(argsList).policyFlags);
+}
+
+TEST_F(KeyboardInputMapperTest_ExternalNonAlphabeticDevice, WakeBehavior_NonAlphabeticKeyboard) {
+ // For external devices, keys will trigger wake on key down. Media keys should not trigger
+ // wake if triggered from external non-alphaebtic keyboard (e.g. headsets).
+
+ addKeyByEvdevCode(KEY_PLAY, AKEYCODE_MEDIA_PLAY);
+ addKeyByEvdevCode(KEY_PLAYPAUSE, AKEYCODE_MEDIA_PLAY_PAUSE, POLICY_FLAG_WAKE);
+
+ std::list<NotifyArgs> argsList = processKeyAndSync(ARBITRARY_TIME, KEY_PLAY, 1);
+ ASSERT_EQ(uint32_t(0), expectSingleKeyArg(argsList).policyFlags);
+
+ argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_PLAY, 0);
+ ASSERT_EQ(uint32_t(0), expectSingleKeyArg(argsList).policyFlags);
+
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_PLAYPAUSE, 1);
+ ASSERT_EQ(POLICY_FLAG_WAKE, expectSingleKeyArg(argsList).policyFlags);
+
+ argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_PLAYPAUSE, 0);
+ ASSERT_EQ(POLICY_FLAG_WAKE, expectSingleKeyArg(argsList).policyFlags);
+}
+
+TEST_F(KeyboardInputMapperTest_ExternalAlphabeticDevice, DoNotWakeByDefaultBehavior) {
+ // Tv Remote key's wake behavior is prescribed by the keylayout file.
+
+ addKeyByEvdevCode(KEY_HOME, AKEYCODE_HOME, POLICY_FLAG_WAKE);
+ addKeyByEvdevCode(KEY_DOWN, AKEYCODE_DPAD_DOWN);
+ addKeyByEvdevCode(KEY_PLAY, AKEYCODE_MEDIA_PLAY, POLICY_FLAG_WAKE);
+
+ mPropertyMap.addProperty("keyboard.doNotWakeByDefault", "1");
+ mMapper = createInputMapper<KeyboardInputMapper>(*mDeviceContext, mReaderConfiguration,
+ AINPUT_SOURCE_KEYBOARD);
+
+ std::list<NotifyArgs> argsList = processKeyAndSync(ARBITRARY_TIME, KEY_HOME, 1);
+ ASSERT_EQ(POLICY_FLAG_WAKE, expectSingleKeyArg(argsList).policyFlags);
+
+ argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_HOME, 0);
+ ASSERT_EQ(POLICY_FLAG_WAKE, expectSingleKeyArg(argsList).policyFlags);
+
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_DOWN, 1);
+ ASSERT_EQ(uint32_t(0), expectSingleKeyArg(argsList).policyFlags);
+
+ argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_DOWN, 0);
+ ASSERT_EQ(uint32_t(0), expectSingleKeyArg(argsList).policyFlags);
+
+ argsList = processKeyAndSync(ARBITRARY_TIME, KEY_PLAY, 1);
+ ASSERT_EQ(POLICY_FLAG_WAKE, expectSingleKeyArg(argsList).policyFlags);
+
+ argsList = processKeyAndSync(ARBITRARY_TIME + 1, KEY_PLAY, 0);
+ ASSERT_EQ(POLICY_FLAG_WAKE, expectSingleKeyArg(argsList).policyFlags);
+}
+
} // namespace android
diff --git a/services/inputflinger/tests/LatencyTracker_test.cpp b/services/inputflinger/tests/LatencyTracker_test.cpp
index 3f14c23..d8c5eac 100644
--- a/services/inputflinger/tests/LatencyTracker_test.cpp
+++ b/services/inputflinger/tests/LatencyTracker_test.cpp
@@ -16,10 +16,14 @@
#include "../dispatcher/LatencyTracker.h"
#include "../InputDeviceMetricsSource.h"
+#include "NotifyArgsBuilders.h"
+#include "android/input.h"
+#include <android-base/logging.h>
#include <android-base/properties.h>
#include <binder/Binder.h>
#include <gtest/gtest.h>
+#include <input/PrintTools.h>
#include <inttypes.h>
#include <linux/input.h>
#include <log/log.h>
@@ -48,11 +52,46 @@
}
void setDefaultInputDeviceInfo(LatencyTracker& tracker) {
- InputDeviceInfo deviceInfo = generateTestDeviceInfo(
- /*vendorId=*/0, /*productId=*/0, DEVICE_ID);
+ InputDeviceInfo deviceInfo = generateTestDeviceInfo(/*vendorId=*/0, /*productId=*/0, DEVICE_ID);
tracker.setInputDevices({deviceInfo});
}
+const auto FIRST_TOUCH_POINTER = PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200);
+const auto FIRST_MOUSE_POINTER = PointerBuilder(/*id=*/1, ToolType::MOUSE);
+
+/**
+ * This is a convenience method for comparing timelines that also prints the difference between
+ * the two structures. This helps debugging when the timelines don't match.
+ * @param received the timeline that was actually received
+ * @param expected the timeline that we expected to receive
+ * @return true if the two timelines match, false otherwise.
+ */
+bool timelinesAreEqual(const InputEventTimeline& received, const InputEventTimeline& expected) {
+ LOG_IF(ERROR, expected.eventTime != received.eventTime)
+ << "Received timeline with eventTime=" << received.eventTime
+ << " instead of expected eventTime=" << expected.eventTime;
+ LOG_IF(ERROR, expected.readTime != received.readTime)
+ << "Received timeline with readTime=" << received.readTime
+ << " instead of expected readTime=" << expected.readTime;
+ LOG_IF(ERROR, expected.vendorId != received.vendorId)
+ << "Received timeline with vendorId=" << received.vendorId
+ << " instead of expected vendorId=" << expected.vendorId;
+ LOG_IF(ERROR, expected.productId != received.productId)
+ << "Received timeline with productId=" << received.productId
+ << " instead of expected productId=" << expected.productId;
+ LOG_IF(ERROR, expected.sources != received.sources)
+ << "Received timeline with sources="
+ << dumpContainer(received.sources, ftl::enum_string)
+ << " instead of expected sources=" << dumpContainer(expected.sources, ftl::enum_string);
+ LOG_IF(ERROR, expected.inputEventActionType != received.inputEventActionType)
+ << "Received timeline with inputEventActionType="
+ << ftl::enum_string(received.inputEventActionType)
+ << " instead of expected inputEventActionType="
+ << ftl::enum_string(expected.inputEventActionType);
+
+ return received == expected;
+}
+
} // namespace
const std::chrono::duration ANR_TIMEOUT = std::chrono::milliseconds(
@@ -64,15 +103,14 @@
/*eventTime=*/2,
/*readTime=*/3,
/*vendorId=*/0,
- /*productId=*/0,
- /*sources=*/{InputDeviceUsageSource::UNKNOWN},
+ /*productId=*/0, {InputDeviceUsageSource::TOUCHSCREEN},
/*inputEventActionType=*/InputEventActionType::UNKNOWN_INPUT_EVENT);
ConnectionTimeline expectedCT(/*deliveryTime=*/6, /*consumeTime=*/7, /*finishTime=*/8);
- std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
+ std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline{};
graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 9;
graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 10;
- expectedCT.setGraphicsTimeline(std::move(graphicsTimeline));
- t.connectionTimelines.emplace(sp<BBinder>::make(), std::move(expectedCT));
+ expectedCT.setGraphicsTimeline(graphicsTimeline);
+ t.connectionTimelines.emplace(sp<BBinder>::make(), expectedCT);
return t;
}
@@ -118,16 +156,19 @@
void LatencyTrackerTest::triggerEventReporting(nsecs_t lastEventTime) {
const nsecs_t triggerEventTime =
lastEventTime + std::chrono::nanoseconds(ANR_TIMEOUT).count() + 1;
- mTracker->trackListener(/*inputEventId=*/1, triggerEventTime,
- /*readTime=*/3, DEVICE_ID,
- /*sources=*/{InputDeviceUsageSource::UNKNOWN},
- AMOTION_EVENT_ACTION_CANCEL, InputEventType::MOTION);
+ mTracker->trackListener(MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL,
+ AINPUT_SOURCE_TOUCHSCREEN, /*inputEventId=*/1)
+ .eventTime(triggerEventTime)
+ .readTime(3)
+ .deviceId(DEVICE_ID)
+ .pointer(FIRST_TOUCH_POINTER)
+ .build());
}
-void LatencyTrackerTest::assertReceivedTimeline(const InputEventTimeline& timeline) {
+void LatencyTrackerTest::assertReceivedTimeline(const InputEventTimeline& expectedTimeline) {
ASSERT_FALSE(mReceivedTimelines.empty());
- const InputEventTimeline& t = mReceivedTimelines.front();
- ASSERT_EQ(timeline, t);
+ const InputEventTimeline& received = mReceivedTimelines.front();
+ ASSERT_TRUE(timelinesAreEqual(received, expectedTimeline));
mReceivedTimelines.pop_front();
}
@@ -148,6 +189,11 @@
break;
}
}
+ if (!found) {
+ for (const InputEventTimeline& receivedTimeline : mReceivedTimelines) {
+ LOG(ERROR) << "Received timeline with eventTime=" << receivedTimeline.eventTime;
+ }
+ }
ASSERT_TRUE(found) << "Could not find expected timeline with eventTime="
<< expectedTimeline.eventTime;
}
@@ -170,14 +216,20 @@
* any additional ConnectionTimeline's.
*/
TEST_F(LatencyTrackerTest, TrackListener_DoesNotTriggerReporting) {
- mTracker->trackListener(/*inputEventId=*/1, /*eventTime=*/2,
- /*readTime=*/3, DEVICE_ID, {InputDeviceUsageSource::UNKNOWN},
- AMOTION_EVENT_ACTION_CANCEL, InputEventType::MOTION);
+ mTracker->trackListener(MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL,
+ AINPUT_SOURCE_TOUCHSCREEN, /*inputEventId=*/1)
+ .eventTime(2)
+ .readTime(3)
+ .deviceId(DEVICE_ID)
+ .pointer(FIRST_TOUCH_POINTER)
+ .build());
triggerEventReporting(/*eventTime=*/2);
assertReceivedTimeline(
InputEventTimeline{/*eventTime=*/2,
- /*readTime=*/3, /*vendorId=*/0, /*productID=*/0,
- /*sources=*/{InputDeviceUsageSource::UNKNOWN},
+ /*readTime=*/3,
+ /*vendorId=*/0,
+ /*productID=*/0,
+ {InputDeviceUsageSource::TOUCHSCREEN},
/*inputEventActionType=*/InputEventActionType::UNKNOWN_INPUT_EVENT});
}
@@ -209,9 +261,13 @@
const auto& [connectionToken, expectedCT] = *expected.connectionTimelines.begin();
- mTracker->trackListener(inputEventId, expected.eventTime, expected.readTime, DEVICE_ID,
- {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL,
- InputEventType::MOTION);
+ mTracker->trackListener(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN, inputEventId)
+ .eventTime(expected.eventTime)
+ .readTime(expected.readTime)
+ .deviceId(DEVICE_ID)
+ .pointer(FIRST_TOUCH_POINTER)
+ .build());
mTracker->trackFinishedEvent(inputEventId, connectionToken, expectedCT.deliveryTime,
expectedCT.consumeTime, expectedCT.finishTime);
mTracker->trackGraphicsLatency(inputEventId, connectionToken, expectedCT.graphicsTimeline);
@@ -230,12 +286,20 @@
// In the following 2 calls to trackListener, the inputEventId's are the same, but event times
// are different.
- mTracker->trackListener(inputEventId, /*eventTime=*/1, readTime, DEVICE_ID,
- {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL,
- InputEventType::MOTION);
- mTracker->trackListener(inputEventId, /*eventTime=*/2, readTime, DEVICE_ID,
- {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL,
- InputEventType::MOTION);
+ mTracker->trackListener(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN, inputEventId)
+ .eventTime(1)
+ .readTime(readTime)
+ .deviceId(DEVICE_ID)
+ .pointer(FIRST_TOUCH_POINTER)
+ .build());
+ mTracker->trackListener(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN, inputEventId)
+ .eventTime(2)
+ .readTime(readTime)
+ .deviceId(DEVICE_ID)
+ .pointer(FIRST_TOUCH_POINTER)
+ .build());
triggerEventReporting(/*eventTime=*/2);
// Since we sent duplicate input events, the tracker should just delete all of them, because it
@@ -249,8 +313,7 @@
/*eventTime*/ 2,
/*readTime*/ 3,
/*vendorId=*/0,
- /*productId=*/0,
- /*sources=*/{InputDeviceUsageSource::UNKNOWN},
+ /*productId=*/0, {InputDeviceUsageSource::TOUCHSCREEN},
/*inputEventType=*/InputEventActionType::UNKNOWN_INPUT_EVENT);
timeline1.connectionTimelines.emplace(connection1,
ConnectionTimeline(/*deliveryTime*/ 6, /*consumeTime*/ 7,
@@ -266,8 +329,7 @@
/*eventTime=*/20,
/*readTime=*/30,
/*vendorId=*/0,
- /*productId=*/0,
- /*sources=*/{InputDeviceUsageSource::UNKNOWN},
+ /*productId=*/0, {InputDeviceUsageSource::TOUCHSCREEN},
/*inputEventActionType=*/InputEventActionType::UNKNOWN_INPUT_EVENT);
timeline2.connectionTimelines.emplace(connection2,
ConnectionTimeline(/*deliveryTime=*/60,
@@ -280,13 +342,21 @@
connectionTimeline2.setGraphicsTimeline(std::move(graphicsTimeline2));
// Start processing first event
- mTracker->trackListener(inputEventId1, timeline1.eventTime, timeline1.readTime, DEVICE_ID,
- {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL,
- InputEventType::MOTION);
+ mTracker->trackListener(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN, inputEventId1)
+ .eventTime(timeline1.eventTime)
+ .readTime(timeline1.readTime)
+ .deviceId(DEVICE_ID)
+ .pointer(FIRST_TOUCH_POINTER)
+ .build());
// Start processing second event
- mTracker->trackListener(inputEventId2, timeline2.eventTime, timeline2.readTime, DEVICE_ID,
- {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL,
- InputEventType::MOTION);
+ mTracker->trackListener(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN, inputEventId2)
+ .eventTime(timeline2.eventTime)
+ .readTime(timeline2.readTime)
+ .deviceId(DEVICE_ID)
+ .pointer(FIRST_TOUCH_POINTER)
+ .build());
mTracker->trackFinishedEvent(inputEventId1, connection1, connectionTimeline1.deliveryTime,
connectionTimeline1.consumeTime, connectionTimeline1.finishTime);
@@ -311,10 +381,13 @@
const sp<IBinder>& token = timeline.connectionTimelines.begin()->first;
for (size_t i = 1; i <= 100; i++) {
- mTracker->trackListener(/*inputEventId=*/i, timeline.eventTime, timeline.readTime,
- /*deviceId=*/DEVICE_ID,
- /*sources=*/{InputDeviceUsageSource::UNKNOWN},
- AMOTION_EVENT_ACTION_CANCEL, InputEventType::MOTION);
+ mTracker->trackListener(MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL,
+ AINPUT_SOURCE_TOUCHSCREEN, /*inputEventId=*/i)
+ .eventTime(timeline.eventTime)
+ .readTime(timeline.readTime)
+ .deviceId(DEVICE_ID)
+ .pointer(FIRST_TOUCH_POINTER)
+ .build());
expectedTimelines.push_back(InputEventTimeline{timeline.eventTime, timeline.readTime,
timeline.vendorId, timeline.productId,
timeline.sources,
@@ -344,9 +417,13 @@
expectedCT.consumeTime, expectedCT.finishTime);
mTracker->trackGraphicsLatency(inputEventId, connection1, expectedCT.graphicsTimeline);
- mTracker->trackListener(inputEventId, expected.eventTime, expected.readTime, DEVICE_ID,
- {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL,
- InputEventType::MOTION);
+ mTracker->trackListener(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN, inputEventId)
+ .eventTime(expected.eventTime)
+ .readTime(expected.readTime)
+ .deviceId(DEVICE_ID)
+ .pointer(FIRST_TOUCH_POINTER)
+ .build());
triggerEventReporting(expected.eventTime);
assertReceivedTimeline(InputEventTimeline{expected.eventTime, expected.readTime,
expected.vendorId, expected.productId,
@@ -362,20 +439,25 @@
constexpr int32_t inputEventId = 1;
InputEventTimeline timeline(
/*eventTime*/ 2, /*readTime*/ 3,
- /*vendorId=*/50, /*productId=*/60,
- /*sources=*/
- {InputDeviceUsageSource::TOUCHSCREEN, InputDeviceUsageSource::STYLUS_DIRECT},
+ /*vendorId=*/50, /*productId=*/60, {InputDeviceUsageSource::STYLUS_DIRECT},
/*inputEventActionType=*/InputEventActionType::UNKNOWN_INPUT_EVENT);
InputDeviceInfo deviceInfo1 = generateTestDeviceInfo(
/*vendorId=*/5, /*productId=*/6, /*deviceId=*/DEVICE_ID + 1);
InputDeviceInfo deviceInfo2 = generateTestDeviceInfo(
/*vendorId=*/50, /*productId=*/60, /*deviceId=*/DEVICE_ID);
+ deviceInfo2.addSource(AINPUT_SOURCE_TOUCHSCREEN);
+ deviceInfo2.addSource(AINPUT_SOURCE_STYLUS);
mTracker->setInputDevices({deviceInfo1, deviceInfo2});
- mTracker->trackListener(inputEventId, timeline.eventTime, timeline.readTime, DEVICE_ID,
- {InputDeviceUsageSource::TOUCHSCREEN,
- InputDeviceUsageSource::STYLUS_DIRECT},
- AMOTION_EVENT_ACTION_CANCEL, InputEventType::MOTION);
+ mTracker->trackListener(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL,
+ AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, inputEventId)
+
+ .eventTime(timeline.eventTime)
+ .readTime(timeline.readTime)
+ .deviceId(DEVICE_ID)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(100).y(200))
+ .build());
triggerEventReporting(timeline.eventTime);
assertReceivedTimeline(timeline);
}
@@ -388,64 +470,93 @@
// Create timelines for different event types (Motion, Key)
InputEventTimeline motionDownTimeline(
/*eventTime*/ 2, /*readTime*/ 3,
- /*vendorId*/ 0, /*productId*/ 0,
- /*sources*/ {InputDeviceUsageSource::UNKNOWN},
- /*inputEventActionType*/ InputEventActionType::MOTION_ACTION_DOWN);
+ /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::TOUCHSCREEN},
+ InputEventActionType::MOTION_ACTION_DOWN);
InputEventTimeline motionMoveTimeline(
/*eventTime*/ 4, /*readTime*/ 5,
- /*vendorId*/ 0, /*productId*/ 0,
- /*sources*/ {InputDeviceUsageSource::UNKNOWN},
- /*inputEventActionType*/ InputEventActionType::MOTION_ACTION_MOVE);
+ /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::TOUCHSCREEN},
+ InputEventActionType::MOTION_ACTION_MOVE);
InputEventTimeline motionUpTimeline(
/*eventTime*/ 6, /*readTime*/ 7,
- /*vendorId*/ 0, /*productId*/ 0,
- /*sources*/ {InputDeviceUsageSource::UNKNOWN},
- /*inputEventActionType*/ InputEventActionType::MOTION_ACTION_UP);
+ /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::TOUCHSCREEN},
+ InputEventActionType::MOTION_ACTION_UP);
InputEventTimeline keyDownTimeline(
/*eventTime*/ 8, /*readTime*/ 9,
- /*vendorId*/ 0, /*productId*/ 0,
- /*sources*/ {InputDeviceUsageSource::UNKNOWN},
- /*inputEventActionType*/ InputEventActionType::KEY);
+ /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::BUTTONS},
+ InputEventActionType::KEY);
InputEventTimeline keyUpTimeline(
/*eventTime*/ 10, /*readTime*/ 11,
- /*vendorId*/ 0, /*productId*/ 0,
- /*sources*/ {InputDeviceUsageSource::UNKNOWN},
- /*inputEventActionType*/ InputEventActionType::KEY);
+ /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::BUTTONS},
+ InputEventActionType::KEY);
+
+ InputEventTimeline motionScrollTimeline(
+ /*eventTime*/ 12, /*readTime*/ 13,
+ /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::MOUSE},
+ InputEventActionType::MOTION_ACTION_SCROLL);
InputEventTimeline unknownTimeline(
- /*eventTime*/ 12, /*readTime*/ 13,
- /*vendorId*/ 0, /*productId*/ 0,
- /*sources*/ {InputDeviceUsageSource::UNKNOWN},
- /*inputEventActionType*/ InputEventActionType::UNKNOWN_INPUT_EVENT);
+ /*eventTime*/ 14, /*readTime*/ 15,
+ /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::TOUCHSCREEN},
+ InputEventActionType::UNKNOWN_INPUT_EVENT);
- mTracker->trackListener(inputEventId, motionDownTimeline.eventTime, motionDownTimeline.readTime,
- DEVICE_ID, motionDownTimeline.sources, AMOTION_EVENT_ACTION_DOWN,
- InputEventType::MOTION);
- mTracker->trackListener(inputEventId + 1, motionMoveTimeline.eventTime,
- motionMoveTimeline.readTime, DEVICE_ID, motionMoveTimeline.sources,
- AMOTION_EVENT_ACTION_MOVE, InputEventType::MOTION);
- mTracker->trackListener(inputEventId + 2, motionUpTimeline.eventTime, motionUpTimeline.readTime,
- DEVICE_ID, motionUpTimeline.sources, AMOTION_EVENT_ACTION_UP,
- InputEventType::MOTION);
- mTracker->trackListener(inputEventId + 3, keyDownTimeline.eventTime, keyDownTimeline.readTime,
- DEVICE_ID, keyDownTimeline.sources, AKEY_EVENT_ACTION_DOWN,
- InputEventType::KEY);
- mTracker->trackListener(inputEventId + 4, keyUpTimeline.eventTime, keyUpTimeline.readTime,
- DEVICE_ID, keyUpTimeline.sources, AKEY_EVENT_ACTION_UP,
- InputEventType::KEY);
- mTracker->trackListener(inputEventId + 5, unknownTimeline.eventTime, unknownTimeline.readTime,
- DEVICE_ID, unknownTimeline.sources, AMOTION_EVENT_ACTION_POINTER_DOWN,
- InputEventType::MOTION);
+ mTracker->trackListener(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, inputEventId)
+ .eventTime(motionDownTimeline.eventTime)
+ .readTime(motionDownTimeline.readTime)
+ .deviceId(DEVICE_ID)
+ .pointer(FIRST_TOUCH_POINTER)
+ .build());
+ mTracker->trackListener(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
+ inputEventId + 1)
+ .eventTime(motionMoveTimeline.eventTime)
+ .readTime(motionMoveTimeline.readTime)
+ .deviceId(DEVICE_ID)
+ .pointer(FIRST_TOUCH_POINTER)
+ .build());
+ mTracker->trackListener(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, inputEventId + 2)
+ .eventTime(motionUpTimeline.eventTime)
+ .readTime(motionUpTimeline.readTime)
+ .deviceId(DEVICE_ID)
+ .pointer(FIRST_TOUCH_POINTER)
+ .build());
+ mTracker->trackListener(
+ KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD, inputEventId + 3)
+ .eventTime(keyDownTimeline.eventTime)
+ .readTime(keyDownTimeline.readTime)
+ .deviceId(DEVICE_ID)
+ .build());
+ mTracker->trackListener(
+ KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD, inputEventId + 4)
+ .eventTime(keyUpTimeline.eventTime)
+ .readTime(keyUpTimeline.readTime)
+ .deviceId(DEVICE_ID)
+ .build());
+ mTracker->trackListener(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_SCROLL, AINPUT_SOURCE_MOUSE, inputEventId + 5)
+ .eventTime(motionScrollTimeline.eventTime)
+ .readTime(motionScrollTimeline.readTime)
+ .deviceId(DEVICE_ID)
+ .pointer(FIRST_MOUSE_POINTER)
+ .build());
+ mTracker->trackListener(MotionArgsBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, inputEventId + 6)
+ .eventTime(unknownTimeline.eventTime)
+ .readTime(unknownTimeline.readTime)
+ .deviceId(DEVICE_ID)
+ .pointer(FIRST_TOUCH_POINTER)
+ .build());
triggerEventReporting(unknownTimeline.eventTime);
std::vector<InputEventTimeline> expectedTimelines = {motionDownTimeline, motionMoveTimeline,
motionUpTimeline, keyDownTimeline,
- keyUpTimeline, unknownTimeline};
+ keyUpTimeline, motionScrollTimeline,
+ unknownTimeline};
assertReceivedTimelines(expectedTimelines);
}
diff --git a/services/inputflinger/tests/MultiTouchInputMapper_test.cpp b/services/inputflinger/tests/MultiTouchInputMapper_test.cpp
index 9a6b266..cc3d123 100644
--- a/services/inputflinger/tests/MultiTouchInputMapper_test.cpp
+++ b/services/inputflinger/tests/MultiTouchInputMapper_test.cpp
@@ -23,6 +23,7 @@
#include "InputMapperTest.h"
#include "InterfaceMocks.h"
+#include "ScopedFlagOverride.h"
#include "TestEventMatchers.h"
#define TAG "MultiTouchpadInputMapperUnit_test"
@@ -30,29 +31,44 @@
namespace android {
using testing::_;
+using testing::AllOf;
using testing::IsEmpty;
using testing::Return;
using testing::SetArgPointee;
using testing::VariantWith;
-static constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
-static constexpr int32_t DISPLAY_WIDTH = 480;
-static constexpr int32_t DISPLAY_HEIGHT = 800;
-static constexpr std::optional<uint8_t> NO_PORT = std::nullopt; // no physical port is specified
-static constexpr int32_t SLOT_COUNT = 5;
+namespace {
-static constexpr int32_t ACTION_POINTER_0_UP =
+constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
+constexpr ui::LogicalDisplayId SECOND_DISPLAY_ID = ui::LogicalDisplayId{DISPLAY_ID.val() + 1};
+constexpr int32_t DISPLAY_WIDTH = 480;
+constexpr int32_t DISPLAY_HEIGHT = 800;
+constexpr std::optional<uint8_t> NO_PORT = std::nullopt; // no physical port is specified
+constexpr int32_t SLOT_COUNT = 5;
+
+constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
+constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
+constexpr int32_t ACTION_POINTER_0_UP =
AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
-static constexpr int32_t ACTION_POINTER_1_DOWN =
+constexpr int32_t ACTION_POINTER_1_DOWN =
AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+template <typename... Args>
+void assertNotifyArgs(const std::list<NotifyArgs>& args, Args... matchers) {
+ ASSERT_THAT(args, ElementsAre(matchers...))
+ << "Got instead: " << dumpContainer(args, streamableToString);
+}
+
+} // namespace
+
/**
* Unit tests for MultiTouchInputMapper.
*/
class MultiTouchInputMapperUnitTest : public InputMapperUnitTest {
protected:
- void SetUp() override {
- InputMapperUnitTest::SetUp();
+ void SetUp() override { SetUp(/*bus=*/0, /*isExternal=*/false); }
+ void SetUp(int bus, bool isExternal) override {
+ InputMapperUnitTest::SetUp(bus, isExternal);
// Present scan codes
expectScanCodes(/*present=*/true,
@@ -81,6 +97,17 @@
EXPECT_CALL(mMockEventHub, hasInputProperty(EVENTHUB_ID, _)).WillRepeatedly(Return(false));
EXPECT_CALL(mMockEventHub, hasInputProperty(EVENTHUB_ID, INPUT_PROP_DIRECT))
.WillRepeatedly(Return(true));
+ // The following EXPECT_CALL lines are not load-bearing, but without them gtest prints
+ // warnings about "uninteresting mocked call", which are distracting when developing the
+ // tests because this text is interleaved with logs of interest.
+ EXPECT_CALL(mMockEventHub, getVirtualKeyDefinitions(EVENTHUB_ID, _))
+ .WillRepeatedly(Return());
+ EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, _))
+ .WillRepeatedly(testing::Return(false));
+ EXPECT_CALL(mMockEventHub, getVideoFrames(EVENTHUB_ID))
+ .WillRepeatedly(testing::Return(std::vector<TouchVideoFrame>{}));
+ EXPECT_CALL(mMockInputReaderContext, getExternalStylusDevices(_)).WillRepeatedly(Return());
+ EXPECT_CALL(mMockInputReaderContext, getGlobalMetaState()).WillRepeatedly(Return(0));
// Axes that the device has
setupAxis(ABS_MT_SLOT, /*valid=*/true, /*min=*/0, /*max=*/SLOT_COUNT - 1, /*resolution=*/0);
@@ -106,9 +133,10 @@
mockSlotValues({});
mFakePolicy->setDefaultPointerDisplayId(DISPLAY_ID);
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, "local:0", NO_PORT,
- ViewportType::INTERNAL);
+ DisplayViewport internalViewport =
+ createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(internalViewport);
mMapper = createInputMapper<MultiTouchInputMapper>(*mDeviceContext,
mFakePolicy->getReaderConfiguration());
}
@@ -147,24 +175,97 @@
});
}
- std::list<NotifyArgs> processPosition(int32_t x, int32_t y) {
+ [[nodiscard]] std::list<NotifyArgs> processPosition(int32_t x, int32_t y) {
std::list<NotifyArgs> args;
args += process(EV_ABS, ABS_MT_POSITION_X, x);
args += process(EV_ABS, ABS_MT_POSITION_Y, y);
return args;
}
- std::list<NotifyArgs> processId(int32_t id) { return process(EV_ABS, ABS_MT_TRACKING_ID, id); }
+ [[nodiscard]] std::list<NotifyArgs> processId(int32_t id) {
+ return process(EV_ABS, ABS_MT_TRACKING_ID, id);
+ }
- std::list<NotifyArgs> processKey(int32_t code, int32_t value) {
+ [[nodiscard]] std::list<NotifyArgs> processKey(int32_t code, int32_t value) {
return process(EV_KEY, code, value);
}
- std::list<NotifyArgs> processSlot(int32_t slot) { return process(EV_ABS, ABS_MT_SLOT, slot); }
+ [[nodiscard]] std::list<NotifyArgs> processSlot(int32_t slot) {
+ return process(EV_ABS, ABS_MT_SLOT, slot);
+ }
- std::list<NotifyArgs> processSync() { return process(EV_SYN, SYN_REPORT, 0); }
+ [[nodiscard]] std::list<NotifyArgs> processSync() { return process(EV_SYN, SYN_REPORT, 0); }
};
+/**
+ * While a gesture is active, change the display that the device is associated with. Make sure that
+ * the CANCEL event that's generated has the display id of the original DOWN event, rather than the
+ * new display id.
+ */
+TEST_F(MultiTouchInputMapperUnitTest, ChangeAssociatedDisplayIdWhenTouchIsActive) {
+ std::list<NotifyArgs> args;
+
+ // Add a second viewport that later will be associated with our device.
+ DisplayViewport secondViewport =
+ createViewport(SECOND_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, "local:1", NO_PORT, ViewportType::EXTERNAL);
+ mFakePolicy->addDisplayViewport(secondViewport);
+ std::optional<DisplayViewport> firstViewport =
+ mFakePolicy->getDisplayViewportByUniqueId("local:0");
+
+ // InputReaderConfiguration contains information about how devices are associated with displays.
+ // The mapper receives this information. However, it doesn't actually parse it - that's done by
+ // InputDevice. The mapper asks InputDevice about the associated viewport, so that's what we
+ // need to mock here to simulate association. This abstraction is confusing and should be
+ // refactored.
+
+ // Start with the first viewport
+ ON_CALL((*mDevice), getAssociatedViewport).WillByDefault(Return(firstViewport));
+ args += mMapper->reconfigure(systemTime(SYSTEM_TIME_MONOTONIC), mReaderConfiguration,
+ InputReaderConfiguration::Change::DISPLAY_INFO);
+
+ int32_t x1 = 100, y1 = 125;
+ args += processKey(BTN_TOUCH, 1);
+ args += processPosition(x1, y1);
+ args += processId(1);
+ args += processSync();
+ ASSERT_THAT(args,
+ ElementsAre(VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(DISPLAY_ID)))));
+ args.clear();
+
+ // Now associate with the second viewport, and reconfigure.
+ ON_CALL((*mDevice), getAssociatedViewport).WillByDefault(Return(secondViewport));
+ args += mMapper->reconfigure(systemTime(SYSTEM_TIME_MONOTONIC), mReaderConfiguration,
+ InputReaderConfiguration::Change::DISPLAY_INFO);
+ assertNotifyArgs(args,
+ VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(DISPLAY_ID))),
+ VariantWith<NotifyDeviceResetArgs>(WithDeviceId(DEVICE_ID)));
+
+ // The remainder of the gesture is ignored
+ // Move.
+ x1 += 10;
+ y1 += 15;
+ args = processPosition(x1, y1);
+ args += processSync();
+ // Up
+ args += processKey(BTN_TOUCH, 0);
+ args += processId(-1);
+ args += processSync();
+
+ ASSERT_THAT(args, IsEmpty());
+
+ // New touch is delivered with the new display id.
+ args += processId(2);
+ args += processKey(BTN_TOUCH, 1);
+ args += processPosition(x1 + 20, y1 + 40);
+ args += processSync();
+ assertNotifyArgs(args,
+ VariantWith<NotifyMotionArgs>(AllOf(WithMotionAction(ACTION_DOWN),
+ WithDisplayId(SECOND_DISPLAY_ID))));
+}
+
// This test simulates a multi-finger gesture with unexpected reset in between. This might happen
// due to buffer overflow and device with report a SYN_DROPPED. In this case we expect mapper to be
// reset, MT slot state to be re-populated and the gesture should be cancelled and restarted.
@@ -174,7 +275,7 @@
// Two fingers down at once.
constexpr int32_t FIRST_TRACKING_ID = 1, SECOND_TRACKING_ID = 2;
int32_t x1 = 100, y1 = 125, x2 = 200, y2 = 225;
- processKey(BTN_TOUCH, 1);
+ args += processKey(BTN_TOUCH, 1);
args += processPosition(x1, y1);
args += processId(FIRST_TRACKING_ID);
args += processSlot(1);
@@ -182,7 +283,7 @@
args += processId(SECOND_TRACKING_ID);
ASSERT_THAT(args, IsEmpty());
- args = processSync();
+ args += processSync();
ASSERT_THAT(args,
ElementsAre(VariantWith<NotifyMotionArgs>(
WithMotionAction(AMOTION_EVENT_ACTION_DOWN)),
@@ -255,8 +356,8 @@
ElementsAre(VariantWith<NotifyMotionArgs>(WithMotionAction(ACTION_POINTER_0_UP))));
// Second finger up.
- processKey(BTN_TOUCH, 0);
- args = processSlot(1);
+ args = processKey(BTN_TOUCH, 0);
+ args += processSlot(1);
args += processId(-1);
ASSERT_THAT(args, IsEmpty());
@@ -266,4 +367,146 @@
VariantWith<NotifyMotionArgs>(WithMotionAction(AMOTION_EVENT_ACTION_UP))));
}
+class ExternalMultiTouchInputMapperTest : public MultiTouchInputMapperUnitTest {
+protected:
+ void SetUp() override { MultiTouchInputMapperUnitTest::SetUp(/*bus=*/0, /*isExternal=*/true); }
+};
+
+/**
+ * Expect fallback to internal viewport if device is external and external viewport is not present.
+ */
+TEST_F(ExternalMultiTouchInputMapperTest, Viewports_Fallback) {
+ std::list<NotifyArgs> args;
+
+ // Expect the event to be sent to the internal viewport,
+ // because an external viewport is not present.
+ args += processKey(BTN_TOUCH, 1);
+ args += processId(1);
+ args += processPosition(100, 200);
+ args += processSync();
+
+ assertNotifyArgs(args,
+ VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(DISPLAY_ID))));
+
+ // Expect the event to be sent to the external viewport if it is present.
+ DisplayViewport externalViewport =
+ createViewport(SECOND_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, "local:1", NO_PORT, ViewportType::EXTERNAL);
+ mFakePolicy->addDisplayViewport(externalViewport);
+ std::optional<DisplayViewport> internalViewport =
+ mFakePolicy->getDisplayViewportByUniqueId("local:0");
+ mReaderConfiguration.setDisplayViewports({*internalViewport, externalViewport});
+ args = mMapper->reconfigure(systemTime(SYSTEM_TIME_MONOTONIC), mReaderConfiguration,
+ InputReaderConfiguration::Change::DISPLAY_INFO);
+
+ assertNotifyArgs(args,
+ VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(DISPLAY_ID))),
+ VariantWith<NotifyDeviceResetArgs>(WithDeviceId(DEVICE_ID)));
+ // Lift up the old pointer.
+ args = processKey(BTN_TOUCH, 0);
+ args += processId(-1);
+ args += processSync();
+
+ // Send new pointer
+ args += processKey(BTN_TOUCH, 1);
+ args += processId(2);
+ args += processPosition(111, 211);
+ args += processSync();
+ assertNotifyArgs(args,
+ VariantWith<NotifyMotionArgs>(AllOf(WithMotionAction(ACTION_DOWN),
+ WithDisplayId(SECOND_DISPLAY_ID))));
+}
+
+class MultiTouchInputMapperPointerModeUnitTest : public MultiTouchInputMapperUnitTest {
+protected:
+ void SetUp() override {
+ MultiTouchInputMapperUnitTest::SetUp();
+
+ // TouchInputMapper goes into POINTER mode whenever INPUT_PROP_DIRECT is not set.
+ EXPECT_CALL(mMockEventHub, hasInputProperty(EVENTHUB_ID, INPUT_PROP_DIRECT))
+ .WillRepeatedly(Return(false));
+
+ mMapper = createInputMapper<MultiTouchInputMapper>(*mDeviceContext,
+ mFakePolicy->getReaderConfiguration());
+ }
+};
+
+TEST_F(MultiTouchInputMapperPointerModeUnitTest, MouseToolOnlyDownWhenMouseButtonsAreDown) {
+ SCOPED_FLAG_OVERRIDE(disable_touch_input_mapper_pointer_usage, true);
+
+ std::list<NotifyArgs> args;
+
+ // Set the tool type to mouse.
+ args += processKey(BTN_TOOL_MOUSE, 1);
+
+ args += processPosition(100, 100);
+ args += processId(1);
+ ASSERT_THAT(args, IsEmpty());
+
+ args = processSync();
+ ASSERT_THAT(args,
+ ElementsAre(VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
+ WithToolType(ToolType::MOUSE))),
+ VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
+ WithToolType(ToolType::MOUSE)))));
+
+ // Setting BTN_TOUCH does not make a mouse pointer go down.
+ args = processKey(BTN_TOUCH, 1);
+ args += processSync();
+ ASSERT_THAT(args,
+ ElementsAre(VariantWith<NotifyMotionArgs>(
+ WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))));
+
+ // The mouse button is pressed, so the mouse goes down.
+ args = processKey(BTN_MOUSE, 1);
+ args += processSync();
+ ASSERT_THAT(args,
+ ElementsAre(VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
+ WithToolType(ToolType::MOUSE))),
+ VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
+ WithToolType(ToolType::MOUSE),
+ WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY))),
+ VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS),
+ WithToolType(ToolType::MOUSE),
+ WithButtonState(AMOTION_EVENT_BUTTON_PRIMARY),
+ WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY)))));
+
+ // The mouse button is released, so the mouse starts hovering.
+ args = processKey(BTN_MOUSE, 0);
+ args += processSync();
+ ASSERT_THAT(args,
+ ElementsAre(VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE),
+ WithButtonState(0), WithToolType(ToolType::MOUSE),
+ WithActionButton(AMOTION_EVENT_BUTTON_PRIMARY))),
+ VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
+ WithToolType(ToolType::MOUSE), WithButtonState(0))),
+ VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
+ WithToolType(ToolType::MOUSE))),
+ VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
+ WithToolType(ToolType::MOUSE)))));
+
+ // Change the tool type so that it is no longer a mouse.
+ // The default tool type is finger, and the finger is already down.
+ args = processKey(BTN_TOOL_MOUSE, 0);
+ args += processSync();
+ ASSERT_THAT(args,
+ ElementsAre(VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
+ WithToolType(ToolType::MOUSE))),
+ VariantWith<NotifyMotionArgs>(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
+ WithToolType(ToolType::FINGER)))));
+}
+
} // namespace android
diff --git a/services/inputflinger/tests/PointerChoreographer_test.cpp b/services/inputflinger/tests/PointerChoreographer_test.cpp
index 411c7ba..38d0679 100644
--- a/services/inputflinger/tests/PointerChoreographer_test.cpp
+++ b/services/inputflinger/tests/PointerChoreographer_test.cpp
@@ -24,6 +24,7 @@
#include "FakePointerController.h"
#include "InterfaceMocks.h"
#include "NotifyArgsBuilders.h"
+#include "ScopedFlagOverride.h"
#include "TestEventMatchers.h"
#include "TestInputListener.h"
@@ -114,6 +115,10 @@
}) {}
class PointerChoreographerTest : public testing::Test {
+public:
+ static constexpr int DENSITY_MEDIUM = 160;
+ static constexpr int DENSITY_HIGH = 320;
+
protected:
TestInputListener mTestListener;
sp<gui::WindowInfosListener> mRegisteredWindowInfoListener;
@@ -135,11 +140,27 @@
});
ON_CALL(mMockPolicy, notifyPointerDisplayIdChanged)
- .WillByDefault([this](ui::LogicalDisplayId displayId, const FloatPoint& position) {
+ .WillByDefault([this](ui::LogicalDisplayId displayId, const vec2& position) {
mPointerDisplayIdNotified = displayId;
});
}
+ void setDefaultMouseDisplayId(ui::LogicalDisplayId displayId) {
+ if (input_flags::connected_displays_cursor()) {
+ // setDefaultMouseDisplayId is no-op if connected displays are enabled, mouse display is
+ // set based on primary display of the topology.
+ // Setting topology with the primary display should have same effect as calling
+ // setDefaultMouseDisplayId without topology.
+ // For this reason in tests we mock this behavior by creating topology with a single
+ // display.
+ mChoreographer.setDisplayTopology({.primaryDisplayId = displayId,
+ .graph{{displayId, {}}},
+ .displaysDensity = {{displayId, DENSITY_MEDIUM}}});
+ } else {
+ mChoreographer.setDefaultMouseDisplayId(displayId);
+ }
+ }
+
std::shared_ptr<FakePointerController> assertPointerControllerCreated(
ControllerType expectedType) {
EXPECT_FALSE(mCreatedControllers.empty()) << "No PointerController was created";
@@ -292,7 +313,7 @@
TEST_F(PointerChoreographerTest, SetsDefaultMouseViewportForPointerController) {
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
// For a mouse event without a target display, default viewport should be set for
// the PointerController.
@@ -309,7 +330,7 @@
WhenDefaultMouseDisplayChangesSetsDefaultMouseViewportForPointerController) {
// Set one display as a default mouse display and emit mouse event to create PointerController.
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID, ANOTHER_DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
@@ -320,7 +341,7 @@
// Change default mouse display. Existing PointerController should be removed and a new one
// should be created.
- mChoreographer.setDefaultMouseDisplayId(ANOTHER_DISPLAY_ID);
+ setDefaultMouseDisplayId(ANOTHER_DISPLAY_ID);
assertPointerControllerRemoved(firstDisplayPc);
auto secondDisplayPc = assertPointerControllerCreated(ControllerType::MOUSE);
@@ -329,7 +350,7 @@
}
TEST_F(PointerChoreographerTest, CallsNotifyPointerDisplayIdChanged) {
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
@@ -341,7 +362,7 @@
}
TEST_F(PointerChoreographerTest, WhenViewportIsSetLaterCallsNotifyPointerDisplayIdChanged) {
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
@@ -354,7 +375,7 @@
}
TEST_F(PointerChoreographerTest, WhenMouseIsRemovedCallsNotifyPointerDisplayIdChanged) {
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
@@ -373,7 +394,7 @@
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID, ANOTHER_DISPLAY_ID}));
// Set one viewport as a default mouse display ID.
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
@@ -382,7 +403,7 @@
assertPointerDisplayIdNotified(DISPLAY_ID);
// Set another viewport as a default mouse display ID. The mouse is moved to the other display.
- mChoreographer.setDefaultMouseDisplayId(ANOTHER_DISPLAY_ID);
+ setDefaultMouseDisplayId(ANOTHER_DISPLAY_ID);
assertPointerControllerRemoved(firstDisplayPc);
assertPointerControllerCreated(ControllerType::MOUSE);
@@ -391,7 +412,7 @@
TEST_F(PointerChoreographerTest, MouseMovesPointerAndReturnsNewArgs) {
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
@@ -421,7 +442,7 @@
TEST_F(PointerChoreographerTest, AbsoluteMouseMovesPointerAndReturnsNewArgs) {
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
@@ -457,7 +478,7 @@
AssociatedMouseMovesPointerOnAssociatedDisplayAndDoesNotMovePointerOnDefaultDisplay) {
// Add two displays and set one to default.
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID, ANOTHER_DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
// Add two devices, one unassociated and the other associated with non-default mouse display.
mChoreographer.notifyInputDevicesChanged(
@@ -496,7 +517,7 @@
TEST_F(PointerChoreographerTest, DoesNotMovePointerForMouseRelativeSource) {
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
@@ -543,7 +564,7 @@
TEST_F(PointerChoreographerTest, WhenPointerCaptureEnabledHidesPointer) {
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
@@ -562,7 +583,7 @@
TEST_F(PointerChoreographerTest, MultipleMiceConnectionAndRemoval) {
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
// A mouse is connected, and the pointer is shown.
mChoreographer.notifyInputDevicesChanged(
@@ -599,7 +620,7 @@
TEST_F(PointerChoreographerTest, UnrelatedChangeDoesNotUnfadePointer) {
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
@@ -628,7 +649,7 @@
TEST_F(PointerChoreographerTest, DisabledMouseConnected) {
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
InputDeviceInfo mouseDeviceInfo =
generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ui::LogicalDisplayId::INVALID);
// Disable this mouse device.
@@ -641,7 +662,7 @@
TEST_F(PointerChoreographerTest, MouseDeviceDisableLater) {
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
InputDeviceInfo mouseDeviceInfo =
generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ui::LogicalDisplayId::INVALID);
@@ -660,7 +681,7 @@
TEST_F(PointerChoreographerTest, MultipleEnabledAndDisabledMiceConnectionAndRemoval) {
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
InputDeviceInfo disabledMouseDeviceInfo =
generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ui::LogicalDisplayId::INVALID);
disabledMouseDeviceInfo.setEnabled(false);
@@ -1008,6 +1029,34 @@
pc->assertPointerIconSet(PointerIconStyle::TYPE_SPOT_HOVER);
}
+TEST_F(PointerChoreographerTest, StylusHoverEnterFadesMouseOnDisplay) {
+ // Make sure there are PointerControllers for a mouse and a stylus.
+ mChoreographer.setStylusPointerIconEnabled(true);
+ setDefaultMouseDisplayId(DISPLAY_ID);
+ mChoreographer.notifyInputDevicesChanged(
+ {/*id=*/0,
+ {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ui::LogicalDisplayId::INVALID),
+ generateTestDeviceInfo(SECOND_DEVICE_ID, AINPUT_SOURCE_STYLUS, DISPLAY_ID)}});
+ mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
+ mChoreographer.notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
+ .pointer(MOUSE_POINTER)
+ .deviceId(DEVICE_ID)
+ .displayId(ui::LogicalDisplayId::INVALID)
+ .build());
+ auto mousePc = assertPointerControllerCreated(ControllerType::MOUSE);
+ ASSERT_TRUE(mousePc->isPointerShown());
+
+ // Start hovering with a stylus. This should fade the mouse cursor.
+ mChoreographer.notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
+ .pointer(STYLUS_POINTER)
+ .deviceId(SECOND_DEVICE_ID)
+ .displayId(DISPLAY_ID)
+ .build());
+ ASSERT_FALSE(mousePc->isPointerShown());
+}
+
using StylusFixtureParam =
std::tuple</*name*/ std::string_view, /*source*/ uint32_t, ControllerType>;
@@ -1378,7 +1427,7 @@
TEST_F(PointerChoreographerTest, SetsDefaultTouchpadViewportForPointerController) {
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
// For a touchpad event without a target display, default viewport should be set for
// the PointerController.
@@ -1394,7 +1443,7 @@
WhenDefaultTouchpadDisplayChangesSetsDefaultTouchpadViewportForPointerController) {
// Set one display as a default touchpad display and create PointerController.
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID, ANOTHER_DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
@@ -1403,7 +1452,7 @@
firstDisplayPc->assertViewportSet(DISPLAY_ID);
// Change default mouse display. Existing PointerController should be removed.
- mChoreographer.setDefaultMouseDisplayId(ANOTHER_DISPLAY_ID);
+ setDefaultMouseDisplayId(ANOTHER_DISPLAY_ID);
assertPointerControllerRemoved(firstDisplayPc);
auto secondDisplayPc = assertPointerControllerCreated(ControllerType::MOUSE);
@@ -1411,7 +1460,7 @@
}
TEST_F(PointerChoreographerTest, TouchpadCallsNotifyPointerDisplayIdChanged) {
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
@@ -1423,7 +1472,7 @@
}
TEST_F(PointerChoreographerTest, WhenViewportIsSetLaterTouchpadCallsNotifyPointerDisplayIdChanged) {
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
@@ -1436,7 +1485,7 @@
}
TEST_F(PointerChoreographerTest, WhenTouchpadIsRemovedCallsNotifyPointerDisplayIdChanged) {
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
@@ -1456,7 +1505,7 @@
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID, ANOTHER_DISPLAY_ID}));
// Set one viewport as a default mouse display ID.
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
@@ -1466,7 +1515,7 @@
// Set another viewport as a default mouse display ID. ui::LogicalDisplayId::INVALID will be
// notified before a touchpad event.
- mChoreographer.setDefaultMouseDisplayId(ANOTHER_DISPLAY_ID);
+ setDefaultMouseDisplayId(ANOTHER_DISPLAY_ID);
assertPointerControllerRemoved(firstDisplayPc);
assertPointerControllerCreated(ControllerType::MOUSE);
@@ -1475,7 +1524,7 @@
TEST_F(PointerChoreographerTest, TouchpadMovesPointerAndReturnsNewArgs) {
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
@@ -1505,7 +1554,7 @@
TEST_F(PointerChoreographerTest, TouchpadAddsPointerPositionToTheCoords) {
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
@@ -1582,7 +1631,7 @@
AssociatedTouchpadMovesPointerOnAssociatedDisplayAndDoesNotMovePointerOnDefaultDisplay) {
// Add two displays and set one to default.
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID, ANOTHER_DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
// Add two devices, one unassociated and the other associated with non-default mouse display.
mChoreographer.notifyInputDevicesChanged(
@@ -1623,7 +1672,7 @@
TEST_F(PointerChoreographerTest, DoesNotMovePointerForTouchpadSource) {
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
@@ -1660,7 +1709,7 @@
TEST_F(PointerChoreographerTest, WhenPointerCaptureEnabledTouchpadHidesPointer) {
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
@@ -1680,7 +1729,7 @@
TEST_F(PointerChoreographerTest, SetsPointerIconForMouse) {
// Make sure there is a PointerController.
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
@@ -1696,7 +1745,7 @@
TEST_F(PointerChoreographerTest, DoesNotSetMousePointerIconForWrongDisplayId) {
// Make sure there is a PointerController.
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
@@ -1713,7 +1762,7 @@
TEST_F(PointerChoreographerTest, DoesNotSetPointerIconForWrongDeviceId) {
// Make sure there is a PointerController.
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
@@ -1730,7 +1779,7 @@
TEST_F(PointerChoreographerTest, SetsCustomPointerIconForMouse) {
// Make sure there is a PointerController.
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
@@ -1754,7 +1803,7 @@
TEST_F(PointerChoreographerTest, SetsPointerIconForMouseOnTwoDisplays) {
// Make sure there are two PointerControllers on different displays.
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID, ANOTHER_DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ui::LogicalDisplayId::INVALID),
@@ -1776,6 +1825,89 @@
firstMousePc->assertPointerIconNotSet();
}
+TEST_F(PointerChoreographerTest, A11yPointerMotionFilterMouse) {
+ mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
+ setDefaultMouseDisplayId(DISPLAY_ID);
+ mChoreographer.notifyInputDevicesChanged(
+ {/*id=*/0,
+ {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+ ui::LogicalDisplayId::INVALID)}});
+ auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
+ ASSERT_EQ(DISPLAY_ID, pc->getDisplayId());
+
+ pc->setPosition(100, 200);
+ mChoreographer.setAccessibilityPointerMotionFilterEnabled(true);
+
+ EXPECT_CALL(mMockPolicy,
+ filterPointerMotionForAccessibility(testing::Eq(vec2{100, 200}),
+ testing::Eq(vec2{10.f, 20.f}),
+ testing::Eq(DISPLAY_ID)))
+ .Times(1)
+ .WillOnce(testing::Return(vec2{4, 13}));
+
+ mChoreographer.notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
+ .pointer(MOUSE_POINTER)
+ .deviceId(DEVICE_ID)
+ .displayId(ui::LogicalDisplayId::INVALID)
+ .build());
+
+ // Cursor position is decided by filtered delta, but pointer coord's relative values are kept.
+ pc->assertPosition(104, 213);
+ mTestListener.assertNotifyMotionWasCalled(AllOf(WithCoords(104, 213), WithDisplayId(DISPLAY_ID),
+ WithCursorPosition(104, 213),
+ WithRelativeMotion(10, 20)));
+}
+
+TEST_F(PointerChoreographerTest, A11yPointerMotionFilterTouchpad) {
+ mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
+ setDefaultMouseDisplayId(DISPLAY_ID);
+ mChoreographer.notifyInputDevicesChanged(
+ {/*id=*/0,
+ {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
+ ui::LogicalDisplayId::INVALID)}});
+ auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
+ ASSERT_EQ(DISPLAY_ID, pc->getDisplayId());
+
+ pc->setPosition(100, 200);
+ mChoreographer.setAccessibilityPointerMotionFilterEnabled(true);
+
+ EXPECT_CALL(mMockPolicy,
+ filterPointerMotionForAccessibility(testing::Eq(vec2{100, 200}),
+ testing::Eq(vec2{10.f, 20.f}),
+ testing::Eq(DISPLAY_ID)))
+ .Times(1)
+ .WillOnce(testing::Return(vec2{4, 13}));
+
+ mChoreographer.notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
+ .pointer(TOUCHPAD_POINTER)
+ .deviceId(DEVICE_ID)
+ .displayId(ui::LogicalDisplayId::INVALID)
+ .build());
+
+ // Cursor position is decided by filtered delta, but pointer coord's relative values are kept.
+ pc->assertPosition(104, 213);
+ mTestListener.assertNotifyMotionWasCalled(AllOf(WithCoords(104, 213), WithDisplayId(DISPLAY_ID),
+ WithCursorPosition(104, 213),
+ WithRelativeMotion(10, 20)));
+}
+
+TEST_F(PointerChoreographerTest, A11yPointerMotionFilterNotFilterTouch) {
+ mChoreographer.notifyInputDevicesChanged(
+ {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID)}});
+ mChoreographer.setAccessibilityPointerMotionFilterEnabled(true);
+
+ EXPECT_CALL(mMockPolicy, filterPointerMotionForAccessibility).Times(0);
+
+ mChoreographer.notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .pointer(FIRST_TOUCH_POINTER)
+ .deviceId(DEVICE_ID)
+ .displayId(DISPLAY_ID)
+ .build());
+}
+
using SkipPointerScreenshotForPrivacySensitiveDisplaysFixtureParam =
std::tuple<std::string_view /*name*/, uint32_t /*source*/, ControllerType, PointerBuilder,
std::function<void(PointerChoreographer&)>, int32_t /*action*/>;
@@ -2127,7 +2259,7 @@
// Make sure there are PointerControllers for a mouse and a stylus.
mChoreographer.setStylusPointerIconEnabled(true);
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ui::LogicalDisplayId::INVALID),
@@ -2162,7 +2294,7 @@
TEST_F(PointerChoreographerTest, SetPointerIconVisibilityHidesPointerOnDisplay) {
// Make sure there are two PointerControllers on different displays.
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID, ANOTHER_DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
{generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, ui::LogicalDisplayId::INVALID),
@@ -2216,7 +2348,7 @@
TEST_F(PointerChoreographerTest, SetPointerIconVisibilityHidesPointerWhenDeviceConnected) {
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
// Hide the pointer on the display, and then connect the mouse.
mChoreographer.setPointerIconVisibility(DISPLAY_ID, false);
@@ -2233,7 +2365,7 @@
TEST_F(PointerChoreographerTest, SetPointerIconVisibilityHidesPointerForTouchpad) {
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
// Hide the pointer on the display.
mChoreographer.setPointerIconVisibility(DISPLAY_ID, false);
@@ -2282,7 +2414,7 @@
TEST_F(PointerChoreographerTest, DrawingTabletCanReportMouseEvent) {
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
mChoreographer.notifyInputDevicesChanged(
{/*id=*/0,
@@ -2309,7 +2441,7 @@
TEST_F(PointerChoreographerTest, MultipleDrawingTabletsReportMouseEvents) {
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
// First drawing tablet is added
mChoreographer.notifyInputDevicesChanged(
@@ -2357,7 +2489,7 @@
TEST_F(PointerChoreographerTest, MouseAndDrawingTabletReportMouseEvents) {
mChoreographer.setDisplayViewports(createViewports({DISPLAY_ID}));
- mChoreographer.setDefaultMouseDisplayId(DISPLAY_ID);
+ setDefaultMouseDisplayId(DISPLAY_ID);
// Mouse and drawing tablet connected
mChoreographer.notifyInputDevicesChanged(
@@ -2601,6 +2733,429 @@
metaKeyCombinationDoesNotHidePointer(*pc, AKEYCODE_A, AKEYCODE_META_RIGHT);
}
+class PointerChoreographerDisplayTopologyTests : public PointerChoreographerTest {
+protected:
+ DisplayViewport createViewport(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
+ ui::Rotation orientation) {
+ DisplayViewport viewport;
+ viewport.displayId = displayId;
+ viewport.logicalRight = width;
+ viewport.logicalBottom = height;
+ viewport.orientation = orientation;
+ return viewport;
+ }
+};
+
+using PointerChoreographerDisplayTopologyCursorTestFixtureParam =
+ std::tuple<std::string_view /*name*/, int32_t /*source device*/,
+ ControllerType /*PointerController*/, ToolType /*pointer tool type*/,
+ vec2 /*source position*/, vec2 /*hover move X/Y*/,
+ ui::LogicalDisplayId /*destination display*/, vec2 /*destination position*/>;
+
+class PointerChoreographerDisplayTopologyCursorTestFixture
+ : public PointerChoreographerDisplayTopologyTests,
+ public testing::WithParamInterface<
+ PointerChoreographerDisplayTopologyCursorTestFixtureParam> {
+public:
+ static constexpr ui::LogicalDisplayId DISPLAY_CENTER_ID = ui::LogicalDisplayId{10};
+ static constexpr ui::LogicalDisplayId DISPLAY_TOP_ID = ui::LogicalDisplayId{20};
+ static constexpr ui::LogicalDisplayId DISPLAY_RIGHT_ID = ui::LogicalDisplayId{30};
+ static constexpr ui::LogicalDisplayId DISPLAY_BOTTOM_ID = ui::LogicalDisplayId{40};
+ static constexpr ui::LogicalDisplayId DISPLAY_LEFT_ID = ui::LogicalDisplayId{50};
+ static constexpr ui::LogicalDisplayId DISPLAY_TOP_RIGHT_CORNER_ID = ui::LogicalDisplayId{60};
+ static constexpr ui::LogicalDisplayId DISPLAY_HIGH_DENSITY_ID = ui::LogicalDisplayId{70};
+
+protected:
+ // Note: viewport size is in pixels and offsets in topology are in dp
+ std::vector<DisplayViewport> mViewports{
+ createViewport(DISPLAY_CENTER_ID, /*width*/ 100, /*height*/ 100, ui::ROTATION_0),
+ createViewport(DISPLAY_TOP_ID, /*width*/ 90, /*height*/ 90, ui::ROTATION_0),
+ createViewport(DISPLAY_RIGHT_ID, /*width*/ 90, /*height*/ 90, ui::ROTATION_90),
+ createViewport(DISPLAY_BOTTOM_ID, /*width*/ 90, /*height*/ 90, ui::ROTATION_180),
+ createViewport(DISPLAY_LEFT_ID, /*width*/ 90, /*height*/ 90, ui::ROTATION_270),
+ createViewport(DISPLAY_TOP_RIGHT_CORNER_ID, /*width*/ 90, /*height*/ 90,
+ ui::ROTATION_0),
+ // Create a high density display size 100x100 dp i.e. 200x200 px
+ createViewport(DISPLAY_HIGH_DENSITY_ID, /*width*/ 200, /*height*/ 200, ui::ROTATION_0),
+ };
+
+ DisplayTopologyGraph
+ mTopology{DISPLAY_CENTER_ID,
+ {{DISPLAY_CENTER_ID,
+ {{DISPLAY_TOP_ID, DisplayTopologyPosition::TOP, 50.0f},
+ // Place a high density display on the left of DISPLAY_TOP_ID with 25 dp
+ // gap
+ {DISPLAY_HIGH_DENSITY_ID, DisplayTopologyPosition::TOP, -75.0f},
+ {DISPLAY_RIGHT_ID, DisplayTopologyPosition::RIGHT, 10.0f},
+ {DISPLAY_BOTTOM_ID, DisplayTopologyPosition::BOTTOM, 10.0f},
+ {DISPLAY_LEFT_ID, DisplayTopologyPosition::LEFT, 10.0f},
+ {DISPLAY_TOP_RIGHT_CORNER_ID, DisplayTopologyPosition::RIGHT, -90.0f}}}},
+ {{DISPLAY_CENTER_ID, DENSITY_MEDIUM},
+ {DISPLAY_TOP_ID, DENSITY_MEDIUM},
+ {DISPLAY_RIGHT_ID, DENSITY_MEDIUM},
+ {DISPLAY_BOTTOM_ID, DENSITY_MEDIUM},
+ {DISPLAY_LEFT_ID, DENSITY_MEDIUM},
+ {DISPLAY_TOP_RIGHT_CORNER_ID, DENSITY_MEDIUM},
+ {DISPLAY_HIGH_DENSITY_ID, DENSITY_HIGH}}};
+};
+
+TEST_P(PointerChoreographerDisplayTopologyCursorTestFixture,
+ PointerChoreographerDisplayTopologyTest) {
+ SCOPED_FLAG_OVERRIDE(connected_displays_cursor, true);
+
+ const auto& [_, device, pointerControllerType, pointerToolType, initialPosition, hoverMove,
+ destinationDisplay, destinationPosition] = GetParam();
+
+ mChoreographer.setDisplayViewports(mViewports);
+ setDefaultMouseDisplayId(DISPLAY_CENTER_ID);
+ mChoreographer.setDisplayTopology(mTopology);
+
+ mChoreographer.notifyInputDevicesChanged(
+ {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, device, ui::LogicalDisplayId::INVALID)}});
+
+ auto pc = assertPointerControllerCreated(pointerControllerType);
+ ASSERT_EQ(DISPLAY_CENTER_ID, pc->getDisplayId());
+
+ // Set initial position of the PointerController.
+ pc->setPosition(initialPosition.x, initialPosition.y);
+ ASSERT_TRUE(pc->isPointerShown());
+
+ // Make NotifyMotionArgs and notify Choreographer.
+ auto pointerBuilder = PointerBuilder(/*id=*/0, pointerToolType)
+ .axis(AMOTION_EVENT_AXIS_RELATIVE_X, hoverMove.x)
+ .axis(AMOTION_EVENT_AXIS_RELATIVE_Y, hoverMove.y);
+
+ mChoreographer.notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, device)
+ .pointer(pointerBuilder)
+ .deviceId(DEVICE_ID)
+ .displayId(ui::LogicalDisplayId::INVALID)
+ .build());
+
+ // Check that the PointerController updated the position and the pointer is shown.
+ ASSERT_TRUE(pc->isPointerShown());
+ ASSERT_EQ(pc->getDisplayId(), destinationDisplay);
+ auto position = pc->getPosition();
+ ASSERT_EQ(position.x, destinationPosition.x);
+ ASSERT_EQ(position.y, destinationPosition.y);
+
+ // Check that x-y coordinates, displayId and cursor position are correctly updated.
+ mTestListener.assertNotifyMotionWasCalled(
+ AllOf(WithCoords(destinationPosition.x, destinationPosition.y),
+ WithDisplayId(destinationDisplay),
+ WithCursorPosition(destinationPosition.x, destinationPosition.y)));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ PointerChoreographerTest, PointerChoreographerDisplayTopologyCursorTestFixture,
+ testing::Values(
+ // Note: Upon viewport transition cursor will be positioned at the boundary of the
+ // destination, as we drop any unconsumed delta.
+ std::make_tuple(
+ "PrimaryDisplayIsDefault", AINPUT_SOURCE_MOUSE, ControllerType::MOUSE,
+ ToolType::MOUSE, vec2(50, 50) /* initial x/y */, vec2(0, 0) /* delta x/y */,
+ PointerChoreographerDisplayTopologyCursorTestFixture::DISPLAY_CENTER_ID,
+ vec2(50, 50) /* destination x/y */),
+ std::make_tuple(
+ "UnchangedDisplay", AINPUT_SOURCE_MOUSE, ControllerType::MOUSE,
+ ToolType::MOUSE, vec2(50, 50) /* initial x/y */,
+ vec2(25, 25) /* delta x/y */,
+ PointerChoreographerDisplayTopologyCursorTestFixture::DISPLAY_CENTER_ID,
+ vec2(75, 75) /* destination x/y */),
+ std::make_tuple(
+ "TransitionToRightDisplay", AINPUT_SOURCE_MOUSE, ControllerType::MOUSE,
+ ToolType::MOUSE, vec2(50, 50) /* initial x/y */,
+ vec2(100, 25) /* delta x/y */,
+ PointerChoreographerDisplayTopologyCursorTestFixture::DISPLAY_RIGHT_ID,
+ vec2(0, 50 + 25 - 10) /* Left edge: (0, source + delta - offset) */),
+ std::make_tuple(
+ "TransitionToLeftDisplay", AINPUT_SOURCE_MOUSE, ControllerType::MOUSE,
+ ToolType::MOUSE, vec2(50, 50) /* initial x/y */,
+ vec2(-100, 25) /* delta x/y */,
+ PointerChoreographerDisplayTopologyCursorTestFixture::DISPLAY_LEFT_ID,
+ vec2(90, 50 + 25 - 10) /* Right edge: (width, source + delta - offset*/),
+ std::make_tuple(
+ "TransitionToTopDisplay", AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
+ ControllerType::MOUSE, ToolType::FINGER, vec2(50, 50) /* initial x/y */,
+ vec2(25, -100) /* delta x/y */,
+ PointerChoreographerDisplayTopologyCursorTestFixture::DISPLAY_TOP_ID,
+ vec2(50 + 25 - 50,
+ 90) /* Bottom edge: (source + delta - offset, height) */),
+ std::make_tuple(
+ "TransitionToBottomDisplay", AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
+ ControllerType::MOUSE, ToolType::FINGER, vec2(50, 50) /* initial x/y */,
+ vec2(25, 100) /* delta x/y */,
+ PointerChoreographerDisplayTopologyCursorTestFixture::DISPLAY_BOTTOM_ID,
+ vec2(50 + 25 - 10, 0) /* Top edge: (source + delta - offset, 0) */),
+ // move towards 25 dp gap between DISPLAY_HIGH_DENSITY_ID and DISPLAY_TOP_ID
+ std::make_tuple(
+ "NoTransitionAtTopOffset", AINPUT_SOURCE_MOUSE, ControllerType::MOUSE,
+ ToolType::MOUSE, vec2(35, 50) /* initial x/y */,
+ vec2(0, -100) /* Move Up */,
+ PointerChoreographerDisplayTopologyCursorTestFixture::DISPLAY_CENTER_ID,
+ vec2(35, 0) /* Top edge */),
+ std::make_tuple(
+ "NoTransitionAtRightOffset", AINPUT_SOURCE_MOUSE, ControllerType::MOUSE,
+ ToolType::MOUSE, vec2(95, 5) /* initial x/y */,
+ vec2(100, 0) /* Move Right */,
+ PointerChoreographerDisplayTopologyCursorTestFixture::DISPLAY_CENTER_ID,
+ vec2(99, 5) /* Top edge */),
+ std::make_tuple(
+ "NoTransitionAtBottomOffset", AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
+ ControllerType::MOUSE, ToolType::FINGER, vec2(5, 95) /* initial x/y */,
+ vec2(0, 100) /* Move Down */,
+ PointerChoreographerDisplayTopologyCursorTestFixture::DISPLAY_CENTER_ID,
+ vec2(5, 99) /* Bottom edge */),
+ std::make_tuple(
+ "NoTransitionAtLeftOffset", AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
+ ControllerType::MOUSE, ToolType::FINGER, vec2(5, 5) /* initial x/y */,
+ vec2(-100, 0) /* Move Left */,
+ PointerChoreographerDisplayTopologyCursorTestFixture::DISPLAY_CENTER_ID,
+ vec2(0, 5) /* Left edge */),
+ std::make_tuple("TransitionAtTopRightCorner",
+ AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD, ControllerType::MOUSE,
+ ToolType::FINGER, vec2(95, 5) /* initial x/y */,
+ vec2(10, -10) /* Move diagonally to top right corner */,
+ PointerChoreographerDisplayTopologyCursorTestFixture::
+ DISPLAY_TOP_RIGHT_CORNER_ID,
+ vec2(0, 90) /* bottom left corner */),
+ std::make_tuple("TransitionToHighDpDisplay",
+ AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD, ControllerType::MOUSE,
+ ToolType::MOUSE, vec2(20, 20) /* initial x/y */,
+ vec2(0, -50) /* delta x/y */,
+ PointerChoreographerDisplayTopologyCursorTestFixture::
+ DISPLAY_HIGH_DENSITY_ID,
+ /* Bottom edge: ((source + delta - offset) * density, height) */
+ vec2((20 + 0 + 75) * 2, 200))),
+ [](const testing::TestParamInfo<PointerChoreographerDisplayTopologyCursorTestFixtureParam>&
+ p) { return std::string{std::get<0>(p.param)}; });
+
+class PointerChoreographerDisplayTopologyDefaultMouseDisplayTests
+ : public PointerChoreographerDisplayTopologyTests {
+protected:
+ static constexpr ui::LogicalDisplayId FIRST_DISPLAY_ID = ui::LogicalDisplayId{10};
+ static constexpr ui::LogicalDisplayId SECOND_DISPLAY_ID = ui::LogicalDisplayId{20};
+ static constexpr ui::LogicalDisplayId THIRD_DISPLAY_ID = ui::LogicalDisplayId{30};
+
+ DisplayViewport createViewport(ui::LogicalDisplayId displayId) {
+ return PointerChoreographerDisplayTopologyTests::createViewport(displayId, /*width=*/100,
+ /*height=*/100,
+ ui::ROTATION_0);
+ }
+
+ void setDisplayTopologyWithDisplays(
+ ui::LogicalDisplayId primaryDisplayId,
+ const std::vector<ui::LogicalDisplayId>& adjacentDisplays = {}) {
+ // Prepare a topology with all display connected from left to right.
+ ui::LogicalDisplayId previousDisplay = primaryDisplayId;
+
+ std::unordered_map<ui::LogicalDisplayId, std::vector<DisplayTopologyAdjacentDisplay>>
+ topologyGraph;
+ topologyGraph[primaryDisplayId] = {};
+
+ std::unordered_map<ui::LogicalDisplayId, int> displaysDensity;
+ displaysDensity[primaryDisplayId] = DENSITY_MEDIUM;
+
+ for (ui::LogicalDisplayId adjacentDisplayId : adjacentDisplays) {
+ topologyGraph[previousDisplay].push_back({.displayId = adjacentDisplayId,
+ .position = DisplayTopologyPosition::RIGHT,
+ .offsetDp = 0.0f});
+ topologyGraph[adjacentDisplayId].push_back({.displayId = previousDisplay,
+ .position = DisplayTopologyPosition::LEFT,
+ .offsetDp = 0.0f});
+
+ displaysDensity[adjacentDisplayId] = DENSITY_MEDIUM;
+ }
+
+ mChoreographer.setDisplayTopology({primaryDisplayId, topologyGraph, displaysDensity});
+ }
+};
+
+TEST_F(PointerChoreographerDisplayTopologyDefaultMouseDisplayTests,
+ UnrelatedTopologyUpdatesDoNotChangeCursorDisplay) {
+ SCOPED_FLAG_OVERRIDE(connected_displays_cursor, true);
+
+ // Set first display as primary display and emit mouse event to create PointerController.
+ mChoreographer.setDisplayViewports({createViewport(FIRST_DISPLAY_ID)});
+ setDisplayTopologyWithDisplays(/*primaryDisplayId=*/FIRST_DISPLAY_ID);
+
+ mChoreographer.notifyInputDevicesChanged(
+ {/*id=*/0,
+ {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+ ui::LogicalDisplayId::INVALID)}});
+ auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
+ pc->assertViewportSet(FIRST_DISPLAY_ID);
+ ASSERT_TRUE(pc->isPointerShown());
+
+ // Add another display keeping the primary display unchanged
+ mChoreographer.setDisplayViewports(
+ {createViewport(FIRST_DISPLAY_ID), createViewport(SECOND_DISPLAY_ID)});
+ setDisplayTopologyWithDisplays(/*primaryDisplayId=*/FIRST_DISPLAY_ID,
+ /*adjacentDisplays=*/{SECOND_DISPLAY_ID});
+
+ assertPointerControllerNotCreated();
+ pc->assertViewportSet(FIRST_DISPLAY_ID);
+ ASSERT_TRUE(pc->isPointerShown());
+
+ // Move cursor to second display and add a third display
+ auto pointerBuilder = PointerBuilder(/*id=*/0, ToolType::MOUSE)
+ .axis(AMOTION_EVENT_AXIS_RELATIVE_X, /*x=*/100)
+ .axis(AMOTION_EVENT_AXIS_RELATIVE_Y, /*y=*/0);
+ mChoreographer.notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
+ .pointer(pointerBuilder)
+ .deviceId(DEVICE_ID)
+ .displayId(ui::LogicalDisplayId::INVALID)
+ .build());
+
+ assertPointerControllerNotCreated();
+ pc->assertViewportSet(SECOND_DISPLAY_ID);
+ ASSERT_TRUE(pc->isPointerShown());
+
+ mChoreographer.setDisplayViewports({createViewport(FIRST_DISPLAY_ID),
+ createViewport(SECOND_DISPLAY_ID),
+ createViewport(THIRD_DISPLAY_ID)});
+ setDisplayTopologyWithDisplays(/*primaryDisplayId=*/FIRST_DISPLAY_ID, /*adjacentDisplays=*/
+ {SECOND_DISPLAY_ID, THIRD_DISPLAY_ID});
+
+ assertPointerControllerNotCreated();
+ pc->assertViewportSet(SECOND_DISPLAY_ID);
+ ASSERT_TRUE(pc->isPointerShown());
+
+ // Change the primary display to the third display
+ setDisplayTopologyWithDisplays(/*primaryDisplayId=*/THIRD_DISPLAY_ID, /*adjacentDisplays=*/
+ {SECOND_DISPLAY_ID, THIRD_DISPLAY_ID});
+
+ assertPointerControllerNotCreated();
+ pc->assertViewportSet(SECOND_DISPLAY_ID);
+ ASSERT_TRUE(pc->isPointerShown());
+}
+
+TEST_F(PointerChoreographerDisplayTopologyDefaultMouseDisplayTests,
+ PrimaryDisplayIsFallbackOnPointerDisplayRemoved) {
+ SCOPED_FLAG_OVERRIDE(connected_displays_cursor, true);
+
+ // Add two displays and move cursor to the secondary display
+ mChoreographer.setDisplayViewports(
+ {createViewport(FIRST_DISPLAY_ID), createViewport(SECOND_DISPLAY_ID)});
+ setDisplayTopologyWithDisplays(/*primaryDisplayId=*/FIRST_DISPLAY_ID,
+ /*adjacentDisplays=*/{SECOND_DISPLAY_ID});
+
+ mChoreographer.notifyInputDevicesChanged(
+ {/*id=*/0,
+ {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+ ui::LogicalDisplayId::INVALID)}});
+ auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
+ pc->assertViewportSet(FIRST_DISPLAY_ID);
+ ASSERT_TRUE(pc->isPointerShown());
+
+ auto pointerBuilder = PointerBuilder(/*id=*/0, ToolType::MOUSE)
+ .axis(AMOTION_EVENT_AXIS_RELATIVE_X, /*x=*/100)
+ .axis(AMOTION_EVENT_AXIS_RELATIVE_Y, /*y=*/0);
+ mChoreographer.notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
+ .pointer(pointerBuilder)
+ .deviceId(DEVICE_ID)
+ .displayId(ui::LogicalDisplayId::INVALID)
+ .build());
+
+ assertPointerControllerNotCreated();
+ pc->assertViewportSet(SECOND_DISPLAY_ID);
+ ASSERT_TRUE(pc->isPointerShown());
+
+ // Remove the secondary display
+ mChoreographer.setDisplayViewports({createViewport(FIRST_DISPLAY_ID)});
+ setDisplayTopologyWithDisplays(/*primaryDisplayId=*/FIRST_DISPLAY_ID);
+
+ assertPointerControllerRemoved(pc);
+ pc = assertPointerControllerCreated(ControllerType::MOUSE);
+ pc->assertViewportSet(FIRST_DISPLAY_ID);
+ ASSERT_TRUE(pc->isPointerShown());
+}
+
+TEST_F(PointerChoreographerDisplayTopologyDefaultMouseDisplayTests,
+ UsePrimaryDisplayIfAssociatedDisplayIsInTopology) {
+ SCOPED_FLAG_OVERRIDE(connected_displays_cursor, true);
+ SCOPED_FLAG_OVERRIDE(connected_displays_associated_display_cursor_bugfix, true);
+
+ // Add two displays
+ mChoreographer.setDisplayViewports(
+ {createViewport(FIRST_DISPLAY_ID), createViewport(SECOND_DISPLAY_ID)});
+ setDisplayTopologyWithDisplays(/*primaryDisplayId=*/SECOND_DISPLAY_ID,
+ /*adjacentDisplays=*/{FIRST_DISPLAY_ID});
+
+ mChoreographer.notifyInputDevicesChanged(
+ {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, FIRST_DISPLAY_ID)}});
+
+ auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
+ pc->assertViewportSet(SECOND_DISPLAY_ID);
+ ASSERT_TRUE(pc->isPointerShown());
+}
+
+TEST_F(PointerChoreographerDisplayTopologyDefaultMouseDisplayTests,
+ AllowCrossingDisplayEvenWithAssociatedDisplaySet) {
+ SCOPED_FLAG_OVERRIDE(connected_displays_cursor, true);
+ SCOPED_FLAG_OVERRIDE(connected_displays_associated_display_cursor_bugfix, true);
+
+ // Add two displays
+ mChoreographer.setDisplayViewports(
+ {createViewport(FIRST_DISPLAY_ID), createViewport(SECOND_DISPLAY_ID)});
+ setDisplayTopologyWithDisplays(/*primaryDisplayId=*/FIRST_DISPLAY_ID,
+ /*adjacentDisplays=*/{SECOND_DISPLAY_ID});
+
+ mChoreographer.notifyInputDevicesChanged(
+ {/*id=*/0,
+ {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, SECOND_DISPLAY_ID)}});
+
+ auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
+ pc->assertViewportSet(FIRST_DISPLAY_ID);
+ ASSERT_TRUE(pc->isPointerShown());
+
+ // Move cursor to the secondary display
+ auto pointerBuilder = PointerBuilder(/*id=*/0, ToolType::MOUSE)
+ .axis(AMOTION_EVENT_AXIS_RELATIVE_X, /*x=*/100)
+ .axis(AMOTION_EVENT_AXIS_RELATIVE_Y, /*y=*/0);
+ mChoreographer.notifyMotion(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
+ .pointer(pointerBuilder)
+ .deviceId(DEVICE_ID)
+ .displayId(ui::LogicalDisplayId::INVALID)
+ .build());
+
+ assertPointerControllerNotCreated();
+ pc->assertViewportSet(SECOND_DISPLAY_ID);
+ ASSERT_TRUE(pc->isPointerShown());
+}
+
+TEST_F(PointerChoreographerDisplayTopologyDefaultMouseDisplayTests,
+ AddAssociatedDisplayCursorOutsideOfDisplayTopology) {
+ SCOPED_FLAG_OVERRIDE(connected_displays_cursor, true);
+ SCOPED_FLAG_OVERRIDE(connected_displays_associated_display_cursor_bugfix, true);
+
+ // Add three displays, with only first and second display in DisplayTopolgoy
+ mChoreographer.setDisplayViewports({createViewport(FIRST_DISPLAY_ID),
+ createViewport(SECOND_DISPLAY_ID),
+ createViewport(THIRD_DISPLAY_ID)});
+ setDisplayTopologyWithDisplays(/*primaryDisplayId=*/FIRST_DISPLAY_ID,
+ /*adjacentDisplays=*/{SECOND_DISPLAY_ID});
+
+ mChoreographer.notifyInputDevicesChanged(
+ {/*id=*/0,
+ {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE,
+ ui::LogicalDisplayId::INVALID)}});
+
+ auto pc = assertPointerControllerCreated(ControllerType::MOUSE);
+ pc->assertViewportSet(FIRST_DISPLAY_ID);
+ ASSERT_TRUE(pc->isPointerShown());
+
+ // Adds a new mouse associated with third display
+ mChoreographer.notifyInputDevicesChanged(
+ {/*id=*/1, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_MOUSE, THIRD_DISPLAY_ID)}});
+
+ pc = assertPointerControllerCreated(ControllerType::MOUSE);
+ pc->assertViewportSet(THIRD_DISPLAY_ID);
+ ASSERT_TRUE(pc->isPointerShown());
+}
+
class PointerChoreographerWindowInfoListenerTest : public testing::Test {};
TEST_F_WITH_FLAGS(
diff --git a/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp b/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp
index 157bee3..548df22 100644
--- a/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp
+++ b/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp
@@ -89,9 +89,9 @@
*/
class RotaryEncoderInputMapperTest : public InputMapperUnitTest {
protected:
- void SetUp() override { SetUpWithBus(BUS_USB); }
- void SetUpWithBus(int bus) override {
- InputMapperUnitTest::SetUpWithBus(bus);
+ void SetUp() override { SetUp(/*bus=*/0, /*isExternal=*/false); }
+ void SetUp(int bus, bool isExternal) override {
+ InputMapperUnitTest::SetUp(bus, isExternal);
EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL))
.WillRepeatedly(Return(true));
diff --git a/services/inputflinger/tests/ScopedFlagOverride.h b/services/inputflinger/tests/ScopedFlagOverride.h
new file mode 100644
index 0000000..883673c
--- /dev/null
+++ b/services/inputflinger/tests/ScopedFlagOverride.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2025 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 <com_android_input_flags.h>
+#include <functional>
+
+namespace android {
+
+/**
+ * Provide a local override for a flag value. The value is restored when the object of this class
+ * goes out of scope.
+ * This class is not intended to be used directly, because its usage is cumbersome.
+ * Instead, a wrapper macro SCOPED_FLAG_OVERRIDE is provided.
+ */
+class ScopedFlagOverride {
+public:
+ ScopedFlagOverride(std::function<bool()> read, std::function<void(bool)> write, bool value)
+ : mInitialValue(read()), mWriteValue(write) {
+ mWriteValue(value);
+ }
+ ~ScopedFlagOverride() { mWriteValue(mInitialValue); }
+
+private:
+ const bool mInitialValue;
+ std::function<void(bool)> mWriteValue;
+};
+
+typedef bool (*ReadFlagValueFunction)();
+typedef void (*WriteFlagValueFunction)(bool);
+
+/**
+ * Use this macro to locally override a flag value.
+ * Example usage:
+ * SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
+ * Note: this works by creating a local variable in your current scope. Don't call this twice for
+ * the same flag, because the variable names will clash!
+ */
+#define SCOPED_FLAG_OVERRIDE(NAME, VALUE) \
+ ReadFlagValueFunction read##NAME = com::android::input::flags::NAME; \
+ WriteFlagValueFunction write##NAME = com::android::input::flags::NAME; \
+ ScopedFlagOverride override##NAME(read##NAME, write##NAME, (VALUE))
+
+} // namespace android
diff --git a/services/inputflinger/tests/SensorInputMapper_test.cpp b/services/inputflinger/tests/SensorInputMapper_test.cpp
new file mode 100644
index 0000000..ac2e99e
--- /dev/null
+++ b/services/inputflinger/tests/SensorInputMapper_test.cpp
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2024 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 "SensorInputMapper.h"
+
+#include <cstdint>
+#include <list>
+#include <optional>
+#include <utility>
+#include <vector>
+
+#include <EventHub.h>
+#include <NotifyArgs.h>
+#include <ftl/enum.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <input/Input.h>
+#include <input/InputDevice.h>
+#include <input/PrintTools.h>
+#include <linux/input-event-codes.h>
+
+#include "InputMapperTest.h"
+#include "TestEventMatchers.h"
+
+namespace android {
+
+using testing::AllOf;
+using testing::ElementsAre;
+using testing::Return;
+using testing::VariantWith;
+
+namespace {
+
+constexpr int32_t ACCEL_RAW_MIN = -32768;
+constexpr int32_t ACCEL_RAW_MAX = 32768;
+constexpr int32_t ACCEL_RAW_FUZZ = 16;
+constexpr int32_t ACCEL_RAW_FLAT = 0;
+constexpr int32_t ACCEL_RAW_RESOLUTION = 8192;
+
+constexpr int32_t GYRO_RAW_MIN = -2097152;
+constexpr int32_t GYRO_RAW_MAX = 2097152;
+constexpr int32_t GYRO_RAW_FUZZ = 16;
+constexpr int32_t GYRO_RAW_FLAT = 0;
+constexpr int32_t GYRO_RAW_RESOLUTION = 1024;
+
+constexpr float GRAVITY_MS2_UNIT = 9.80665f;
+constexpr float DEGREE_RADIAN_UNIT = 0.0174533f;
+
+} // namespace
+
+class SensorInputMapperTest : public InputMapperUnitTest {
+protected:
+ void SetUp() override {
+ InputMapperUnitTest::SetUp();
+ EXPECT_CALL(mMockEventHub, getDeviceClasses(EVENTHUB_ID))
+ .WillRepeatedly(Return(InputDeviceClass::SENSOR));
+ // The mapper requests info on all ABS axes, including ones which aren't actually used, so
+ // just return nullopt for all axes we don't explicitly set up.
+ EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, testing::_))
+ .WillRepeatedly(Return(std::nullopt));
+ }
+
+ void setupSensor(int32_t absCode, InputDeviceSensorType type, int32_t sensorDataIndex) {
+ EXPECT_CALL(mMockEventHub, mapSensor(EVENTHUB_ID, absCode))
+ .WillRepeatedly(Return(std::make_pair(type, sensorDataIndex)));
+ }
+};
+
+TEST_F(SensorInputMapperTest, GetSources) {
+ mMapper = createInputMapper<SensorInputMapper>(*mDeviceContext,
+ mFakePolicy->getReaderConfiguration());
+
+ ASSERT_EQ(static_cast<uint32_t>(AINPUT_SOURCE_SENSOR), mMapper->getSources());
+}
+
+TEST_F(SensorInputMapperTest, ProcessAccelerometerSensor) {
+ EXPECT_CALL(mMockEventHub, hasMscEvent(EVENTHUB_ID, MSC_TIMESTAMP))
+ .WillRepeatedly(Return(true));
+ setupSensor(ABS_X, InputDeviceSensorType::ACCELEROMETER, /*sensorDataIndex=*/0);
+ setupSensor(ABS_Y, InputDeviceSensorType::ACCELEROMETER, /*sensorDataIndex=*/1);
+ setupSensor(ABS_Z, InputDeviceSensorType::ACCELEROMETER, /*sensorDataIndex=*/2);
+ setupAxis(ABS_X, /*valid=*/true, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_RESOLUTION,
+ ACCEL_RAW_FLAT, ACCEL_RAW_FUZZ);
+ setupAxis(ABS_Y, /*valid=*/true, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_RESOLUTION,
+ ACCEL_RAW_FLAT, ACCEL_RAW_FUZZ);
+ setupAxis(ABS_Z, /*valid=*/true, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_RESOLUTION,
+ ACCEL_RAW_FLAT, ACCEL_RAW_FUZZ);
+ mPropertyMap.addProperty("sensor.accelerometer.reportingMode", "0");
+ mPropertyMap.addProperty("sensor.accelerometer.maxDelay", "100000");
+ mPropertyMap.addProperty("sensor.accelerometer.minDelay", "5000");
+ mPropertyMap.addProperty("sensor.accelerometer.power", "1.5");
+ mMapper = createInputMapper<SensorInputMapper>(*mDeviceContext,
+ mFakePolicy->getReaderConfiguration());
+
+ EXPECT_CALL(mMockEventHub, enableDevice(EVENTHUB_ID));
+ ASSERT_TRUE(mMapper->enableSensor(InputDeviceSensorType::ACCELEROMETER,
+ std::chrono::microseconds(10000),
+ std::chrono::microseconds(0)));
+ std::list<NotifyArgs> args;
+ args += process(ARBITRARY_TIME, EV_ABS, ABS_X, 20000);
+ args += process(ARBITRARY_TIME, EV_ABS, ABS_Y, -20000);
+ args += process(ARBITRARY_TIME, EV_ABS, ABS_Z, 40000);
+ args += process(ARBITRARY_TIME, EV_MSC, MSC_TIMESTAMP, 1000);
+ args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
+
+ std::vector<float> values = {20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT,
+ -20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT,
+ 40000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT};
+
+ ASSERT_EQ(args.size(), 1u);
+ const NotifySensorArgs& arg = std::get<NotifySensorArgs>(args.front());
+ ASSERT_EQ(arg.source, AINPUT_SOURCE_SENSOR);
+ ASSERT_EQ(arg.deviceId, DEVICE_ID);
+ ASSERT_EQ(arg.sensorType, InputDeviceSensorType::ACCELEROMETER);
+ ASSERT_EQ(arg.accuracy, InputDeviceSensorAccuracy::HIGH);
+ ASSERT_EQ(arg.hwTimestamp, ARBITRARY_TIME);
+ ASSERT_EQ(arg.values, values);
+ mMapper->flushSensor(InputDeviceSensorType::ACCELEROMETER);
+}
+
+TEST_F(SensorInputMapperTest, ProcessGyroscopeSensor) {
+ EXPECT_CALL(mMockEventHub, hasMscEvent(EVENTHUB_ID, MSC_TIMESTAMP))
+ .WillRepeatedly(Return(true));
+ setupSensor(ABS_RX, InputDeviceSensorType::GYROSCOPE, /*sensorDataIndex=*/0);
+ setupSensor(ABS_RY, InputDeviceSensorType::GYROSCOPE, /*sensorDataIndex=*/1);
+ setupSensor(ABS_RZ, InputDeviceSensorType::GYROSCOPE, /*sensorDataIndex=*/2);
+ setupAxis(ABS_RX, /*valid=*/true, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_RESOLUTION,
+ GYRO_RAW_FLAT, GYRO_RAW_FUZZ);
+ setupAxis(ABS_RY, /*valid=*/true, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_RESOLUTION,
+ GYRO_RAW_FLAT, GYRO_RAW_FUZZ);
+ setupAxis(ABS_RZ, /*valid=*/true, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_RESOLUTION,
+ GYRO_RAW_FLAT, GYRO_RAW_FUZZ);
+ mPropertyMap.addProperty("sensor.gyroscope.reportingMode", "0");
+ mPropertyMap.addProperty("sensor.gyroscope.maxDelay", "100000");
+ mPropertyMap.addProperty("sensor.gyroscope.minDelay", "5000");
+ mPropertyMap.addProperty("sensor.gyroscope.power", "0.8");
+ mMapper = createInputMapper<SensorInputMapper>(*mDeviceContext,
+ mFakePolicy->getReaderConfiguration());
+
+ EXPECT_CALL(mMockEventHub, enableDevice(EVENTHUB_ID));
+ ASSERT_TRUE(mMapper->enableSensor(InputDeviceSensorType::GYROSCOPE,
+ std::chrono::microseconds(10000),
+ std::chrono::microseconds(0)));
+ std::list<NotifyArgs> args;
+ args += process(ARBITRARY_TIME, EV_ABS, ABS_RX, 20000);
+ args += process(ARBITRARY_TIME, EV_ABS, ABS_RY, -20000);
+ args += process(ARBITRARY_TIME, EV_ABS, ABS_RZ, 40000);
+ args += process(ARBITRARY_TIME, EV_MSC, MSC_TIMESTAMP, 1000);
+ args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
+
+ std::vector<float> values = {20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT,
+ -20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT,
+ 40000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT};
+
+ ASSERT_EQ(args.size(), 1u);
+ const NotifySensorArgs& arg = std::get<NotifySensorArgs>(args.front());
+ ASSERT_EQ(arg.source, AINPUT_SOURCE_SENSOR);
+ ASSERT_EQ(arg.deviceId, DEVICE_ID);
+ ASSERT_EQ(arg.sensorType, InputDeviceSensorType::GYROSCOPE);
+ ASSERT_EQ(arg.accuracy, InputDeviceSensorAccuracy::HIGH);
+ ASSERT_EQ(arg.hwTimestamp, ARBITRARY_TIME);
+ ASSERT_EQ(arg.values, values);
+ mMapper->flushSensor(InputDeviceSensorType::GYROSCOPE);
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/inputflinger/tests/TestEventMatchers.h b/services/inputflinger/tests/TestEventMatchers.h
index 6fa3365..1262af7 100644
--- a/services/inputflinger/tests/TestEventMatchers.h
+++ b/services/inputflinger/tests/TestEventMatchers.h
@@ -38,10 +38,23 @@
auto operator<=>(const PointF&) const = default;
};
+namespace internal {
+
+template <typename T>
+static bool valuesMatch(T value1, T value2) {
+ if constexpr (std::is_floating_point_v<T>) {
+ return std::abs(value1 - value2) < EPSILON;
+ } else {
+ return value1 == value2;
+ }
+}
+
inline std::string pointFToString(const PointF& p) {
return std::string("(") + std::to_string(p.x) + ", " + std::to_string(p.y) + ")";
}
+} // namespace internal
+
/// Source
class WithSourceMatcher {
public:
@@ -108,20 +121,33 @@
using is_gtest_matcher = void;
explicit WithMotionActionMatcher(int32_t action) : mAction(action) {}
- bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
- bool matches = mAction == args.action;
- if (args.action == AMOTION_EVENT_ACTION_CANCEL) {
- matches &= (args.flags & AMOTION_EVENT_FLAG_CANCELED) != 0;
+ bool MatchAndExplain(const NotifyMotionArgs& args,
+ testing::MatchResultListener* listener) const {
+ if (mAction != args.action) {
+ *listener << "expected " << MotionEvent::actionToString(mAction) << ", but got "
+ << MotionEvent::actionToString(args.action);
+ return false;
}
- return matches;
+ if (args.action == AMOTION_EVENT_ACTION_CANCEL &&
+ (args.flags & AMOTION_EVENT_FLAG_CANCELED) == 0) {
+ *listener << "event with CANCEL action is missing FLAG_CANCELED";
+ return false;
+ }
+ return true;
}
- bool MatchAndExplain(const MotionEvent& event, std::ostream*) const {
- bool matches = mAction == event.getAction();
- if (event.getAction() == AMOTION_EVENT_ACTION_CANCEL) {
- matches &= (event.getFlags() & AMOTION_EVENT_FLAG_CANCELED) != 0;
+ bool MatchAndExplain(const MotionEvent& event, testing::MatchResultListener* listener) const {
+ if (mAction != event.getAction()) {
+ *listener << "expected " << MotionEvent::actionToString(mAction) << ", but got "
+ << MotionEvent::actionToString(event.getAction());
+ return false;
}
- return matches;
+ if (event.getAction() == AMOTION_EVENT_ACTION_CANCEL &&
+ (event.getFlags() & AMOTION_EVENT_FLAG_CANCELED) == 0) {
+ *listener << "event with CANCEL action is missing FLAG_CANCELED";
+ return false;
+ }
+ return true;
}
void DescribeTo(std::ostream* os) const {
@@ -427,8 +453,10 @@
}
if (mPointers != actualPointers) {
- *os << "expected pointers " << dumpMap(mPointers, constToString, pointFToString)
- << ", but got " << dumpMap(actualPointers, constToString, pointFToString);
+ *os << "expected pointers "
+ << dumpMap(mPointers, constToString, internal::pointFToString)
+ << ", but got "
+ << dumpMap(actualPointers, constToString, internal::pointFToString);
return false;
}
return true;
@@ -443,15 +471,17 @@
}
if (mPointers != actualPointers) {
- *os << "expected pointers " << dumpMap(mPointers, constToString, pointFToString)
- << ", but got " << dumpMap(actualPointers, constToString, pointFToString);
+ *os << "expected pointers "
+ << dumpMap(mPointers, constToString, internal::pointFToString)
+ << ", but got "
+ << dumpMap(actualPointers, constToString, internal::pointFToString);
return false;
}
return true;
}
void DescribeTo(std::ostream* os) const {
- *os << "with pointers " << dumpMap(mPointers, constToString, pointFToString);
+ *os << "with pointers " << dumpMap(mPointers, constToString, internal::pointFToString);
}
void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointers"; }
@@ -479,8 +509,8 @@
}
if (mPointerIds != actualPointerIds) {
- *os << "expected pointer ids " << dumpSet(mPointerIds) << ", but got "
- << dumpSet(actualPointerIds);
+ *os << "expected pointer ids " << dumpContainer(mPointerIds) << ", but got "
+ << dumpContainer(actualPointerIds);
return false;
}
return true;
@@ -493,14 +523,16 @@
}
if (mPointerIds != actualPointerIds) {
- *os << "expected pointer ids " << dumpSet(mPointerIds) << ", but got "
- << dumpSet(actualPointerIds);
+ *os << "expected pointer ids " << dumpContainer(mPointerIds) << ", but got "
+ << dumpContainer(actualPointerIds);
return false;
}
return true;
}
- void DescribeTo(std::ostream* os) const { *os << "with pointer ids " << dumpSet(mPointerIds); }
+ void DescribeTo(std::ostream* os) const {
+ *os << "with pointer ids " << dumpContainer(mPointerIds);
+ }
void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointer ids"; }
@@ -540,6 +572,34 @@
return WithKeyCodeMatcher(keyCode);
}
+/// Scan code
+class WithScanCodeMatcher {
+public:
+ using is_gtest_matcher = void;
+ explicit WithScanCodeMatcher(int32_t scanCode) : mScanCode(scanCode) {}
+
+ bool MatchAndExplain(const NotifyKeyArgs& args, std::ostream*) const {
+ return mScanCode == args.scanCode;
+ }
+
+ bool MatchAndExplain(const KeyEvent& event, std::ostream*) const {
+ return mScanCode == event.getKeyCode();
+ }
+
+ void DescribeTo(std::ostream* os) const {
+ *os << "with scan code " << KeyEvent::getLabel(mScanCode);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const { *os << "wrong scan code"; }
+
+private:
+ const int32_t mScanCode;
+};
+
+inline WithScanCodeMatcher WithScanCode(int32_t scanCode) {
+ return WithScanCodeMatcher(scanCode);
+}
+
/// EventId
class WithEventIdMatcher {
public:
@@ -665,8 +725,9 @@
}
const PointerCoords& coords = event.pointerCoords[mPointerIndex];
- bool matches = mRelX == coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X) &&
- mRelY == coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y);
+ bool matches =
+ internal::valuesMatch(mRelX, coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X)) &&
+ internal::valuesMatch(mRelY, coords.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y));
if (!matches) {
*os << "expected relative motion (" << mRelX << ", " << mRelY << ") at pointer index "
<< mPointerIndex << ", but got ("
diff --git a/services/inputflinger/tests/TouchpadInputMapper_test.cpp b/services/inputflinger/tests/TouchpadInputMapper_test.cpp
index ea69fff..5f5aa63 100644
--- a/services/inputflinger/tests/TouchpadInputMapper_test.cpp
+++ b/services/inputflinger/tests/TouchpadInputMapper_test.cpp
@@ -18,10 +18,13 @@
#include <android-base/logging.h>
#include <gtest/gtest.h>
+#include <input/AccelerationCurve.h>
+#include <log/log.h>
#include <thread>
#include "InputMapperTest.h"
#include "InterfaceMocks.h"
+#include "TestConstants.h"
#include "TestEventMatchers.h"
#define TAG "TouchpadInputMapper_test"
@@ -121,9 +124,10 @@
*/
TEST_F(TouchpadInputMapperTest, HoverAndLeftButtonPress) {
mFakePolicy->setDefaultPointerDisplayId(DISPLAY_ID);
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
- /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL);
-
+ DisplayViewport viewport =
+ createViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ /*isActive=*/true, "local:0", NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(viewport);
std::list<NotifyArgs> args;
args += mMapper->reconfigure(systemTime(SYSTEM_TIME_MONOTONIC), mReaderConfiguration,
@@ -190,4 +194,67 @@
mFakePolicy->assertTouchpadHardwareStateNotified();
}
+TEST_F(TouchpadInputMapperTest, TouchpadAccelerationDisabled) {
+ mReaderConfiguration.touchpadAccelerationEnabled = false;
+ mReaderConfiguration.touchpadPointerSpeed = 3;
+
+ std::list<NotifyArgs> args =
+ mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration,
+ InputReaderConfiguration::Change::TOUCHPAD_SETTINGS);
+ auto* touchpadMapper = static_cast<TouchpadInputMapper*>(mMapper.get());
+
+ const auto accelCurvePropsDisabled =
+ touchpadMapper->getGesturePropertyForTesting("Pointer Accel Curve");
+ ASSERT_TRUE(accelCurvePropsDisabled.has_value());
+ std::vector<double> curveValuesDisabled = accelCurvePropsDisabled.value().getRealValues();
+ std::vector<AccelerationCurveSegment> curve =
+ createFlatAccelerationCurve(mReaderConfiguration.touchpadPointerSpeed);
+ double expectedBaseGain = curve[0].baseGain;
+ ASSERT_EQ(curveValuesDisabled[0], std::numeric_limits<double>::infinity());
+ ASSERT_EQ(curveValuesDisabled[1], 0);
+ ASSERT_NEAR(curveValuesDisabled[2], expectedBaseGain, EPSILON);
+ ASSERT_EQ(curveValuesDisabled[3], 0);
+}
+
+TEST_F(TouchpadInputMapperTest, TouchpadAccelerationEnabled) {
+ // Enable touchpad acceleration.
+ mReaderConfiguration.touchpadAccelerationEnabled = true;
+ mReaderConfiguration.touchpadPointerSpeed = 3;
+
+ std::list<NotifyArgs> args =
+ mMapper->reconfigure(ARBITRARY_TIME, mReaderConfiguration,
+ InputReaderConfiguration::Change::TOUCHPAD_SETTINGS);
+ ASSERT_THAT(args, testing::IsEmpty());
+
+ auto* touchpadMapper = static_cast<TouchpadInputMapper*>(mMapper.get());
+
+ // Get the acceleration curve properties when acceleration is enabled.
+ const auto accelCurvePropsEnabled =
+ touchpadMapper->getGesturePropertyForTesting("Pointer Accel Curve");
+ ASSERT_TRUE(accelCurvePropsEnabled.has_value());
+
+ // Get the curve values.
+ std::vector<double> curveValuesEnabled = accelCurvePropsEnabled.value().getRealValues();
+
+ // Use createAccelerationCurveForPointerSensitivity to get expected curve segments.
+ std::vector<AccelerationCurveSegment> expectedCurveSegments =
+ createAccelerationCurveForPointerSensitivity(mReaderConfiguration.touchpadPointerSpeed);
+
+ // Iterate through the segments and compare the values.
+ for (size_t i = 0; i < expectedCurveSegments.size(); ++i) {
+ // Check max speed.
+ if (std::isinf(expectedCurveSegments[i].maxPointerSpeedMmPerS)) {
+ ASSERT_TRUE(std::isinf(curveValuesEnabled[i * 4 + 0]));
+ } else {
+ ASSERT_NEAR(curveValuesEnabled[i * 4 + 0],
+ expectedCurveSegments[i].maxPointerSpeedMmPerS, EPSILON);
+ }
+
+ // Check that the x^2 term is zero.
+ ASSERT_NEAR(curveValuesEnabled[i * 4 + 1], 0, EPSILON);
+ ASSERT_NEAR(curveValuesEnabled[i * 4 + 2], expectedCurveSegments[i].baseGain, EPSILON);
+ ASSERT_NEAR(curveValuesEnabled[i * 4 + 3], expectedCurveSegments[i].reciprocal, EPSILON);
+ }
+}
+
} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/Android.bp b/services/inputflinger/tests/fuzzers/Android.bp
index 48e1954..5000db7 100644
--- a/services/inputflinger/tests/fuzzers/Android.bp
+++ b/services/inputflinger/tests/fuzzers/Android.bp
@@ -33,8 +33,8 @@
"frameworks/native/services/inputflinger",
],
shared_libs: [
- "libinputreader",
"libinputflinger_base",
+ "libinputreader",
],
sanitize: {
hwaddress: true,
diff --git a/services/inputflinger/tests/fuzzers/FuzzedInputStream.h b/services/inputflinger/tests/fuzzers/FuzzedInputStream.h
index 812969b..43975f0 100644
--- a/services/inputflinger/tests/fuzzers/FuzzedInputStream.h
+++ b/services/inputflinger/tests/fuzzers/FuzzedInputStream.h
@@ -18,10 +18,16 @@
namespace android {
-namespace {
static constexpr int32_t MAX_RANDOM_POINTERS = 4;
static constexpr int32_t MAX_RANDOM_DEVICES = 4;
-} // namespace
+
+// The maximum value that we use for the action button field of NotifyMotionArgs. (We allow multiple
+// bits to be set for this since we're just trying to generate a fuzzed event stream that doesn't
+// cause crashes when enum values are converted to Rust — we don't necessarily want it to be valid.)
+//
+// AMOTION_EVENT_BUTTON_STYLUS_SECONDARY should be replaced with whatever AMOTION_EVENT_BUTTON_
+// value is highest if the enum is edited.
+static constexpr int8_t MAX_ACTION_BUTTON_VALUE = (AMOTION_EVENT_BUTTON_STYLUS_SECONDARY << 1) - 1;
int getFuzzedMotionAction(FuzzedDataProvider& fdp) {
int actionMasked = fdp.PickValueInArray<int>({
@@ -187,18 +193,16 @@
fdp.ConsumeIntegralInRange<nsecs_t>(currentTime - 5E9, currentTime + 5E9);
const nsecs_t readTime = downTime;
const nsecs_t eventTime = fdp.ConsumeIntegralInRange<nsecs_t>(downTime, downTime + 1E9);
+ const int32_t actionButton = fdp.ConsumeIntegralInRange<int32_t>(0, MAX_ACTION_BUTTON_VALUE);
const float cursorX = fdp.ConsumeIntegralInRange<int>(-10000, 10000);
const float cursorY = fdp.ConsumeIntegralInRange<int>(-10000, 10000);
return NotifyMotionArgs(idGenerator.nextId(), eventTime, readTime, deviceId, source, displayId,
- POLICY_FLAG_PASS_TO_USER, action,
- /*actionButton=*/fdp.ConsumeIntegral<int32_t>(),
+ POLICY_FLAG_PASS_TO_USER, action, actionButton,
getFuzzedFlags(fdp, action), AMETA_NONE, getFuzzedButtonState(fdp),
MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount,
- pointerProperties.data(), pointerCoords.data(),
- /*xPrecision=*/0,
- /*yPrecision=*/0, cursorX, cursorY, downTime,
- /*videoFrames=*/{});
+ pointerProperties.data(), pointerCoords.data(), /*xPrecision=*/0,
+ /*yPrecision=*/0, cursorX, cursorY, downTime, /*videoFrames=*/{});
}
} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/InputDispatcherFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputDispatcherFuzzer.cpp
index 79a5ff6..abce931 100644
--- a/services/inputflinger/tests/fuzzers/InputDispatcherFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/InputDispatcherFuzzer.cpp
@@ -48,9 +48,9 @@
auto [it, _] = mVerifiers.emplace(args.displayId, "Fuzz Verifier");
InputVerifier& verifier = it->second;
const Result<void> result =
- verifier.processMovement(args.deviceId, args.source, args.action,
+ verifier.processMovement(args.deviceId, args.source, args.action, args.actionButton,
args.getPointerCount(), args.pointerProperties.data(),
- args.pointerCoords.data(), args.flags);
+ args.pointerCoords.data(), args.flags, args.buttonState);
if (result.ok()) {
return args;
}
@@ -76,7 +76,6 @@
window.setDupTouchToWallpaper(fdp.ConsumeBool());
window.setIsWallpaper(fdp.ConsumeBool());
window.setVisible(fdp.ConsumeBool());
- window.setPreventSplitting(fdp.ConsumeBool());
const bool isTrustedOverlay = fdp.ConsumeBool();
window.setTrustedOverlay(isTrustedOverlay);
if (isTrustedOverlay) {
diff --git a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
index 5442a65..6be922d 100644
--- a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
@@ -75,6 +75,8 @@
void toggleCapsLockState(int32_t deviceId) { reader->toggleCapsLockState(deviceId); }
+ void resetLockedModifierState() { reader->resetLockedModifierState(); }
+
bool hasKeys(int32_t deviceId, uint32_t sourceMask, const std::vector<int32_t>& keyCodes,
uint8_t* outFlags) {
return reader->hasKeys(deviceId, sourceMask, keyCodes, outFlags);
@@ -171,6 +173,10 @@
void notifyMouseCursorFadedOnTyping() override { reader->notifyMouseCursorFadedOnTyping(); }
+ bool setKernelWakeEnabled(int32_t deviceId, bool enabled) override {
+ return reader->setKernelWakeEnabled(deviceId, enabled);
+ }
+
private:
std::unique_ptr<InputReaderInterface> reader;
};
@@ -222,6 +228,7 @@
fdp->ConsumeIntegral<int32_t>());
},
[&]() -> void { reader->toggleCapsLockState(fdp->ConsumeIntegral<int32_t>()); },
+ [&]() -> void { reader->resetLockedModifierState(); },
[&]() -> void {
size_t count = fdp->ConsumeIntegralInRange<size_t>(1, 1024);
std::vector<uint8_t> outFlags(count);
diff --git a/services/inputflinger/tests/fuzzers/LatencyTrackerFuzzer.cpp b/services/inputflinger/tests/fuzzers/LatencyTrackerFuzzer.cpp
index 908fa40..157a333 100644
--- a/services/inputflinger/tests/fuzzers/LatencyTrackerFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/LatencyTrackerFuzzer.cpp
@@ -19,6 +19,7 @@
#include "../../InputDeviceMetricsSource.h"
#include "../InputEventTimeline.h"
+#include "NotifyArgsBuilders.h"
#include "dispatcher/LatencyTracker.h"
namespace android {
@@ -61,40 +62,49 @@
// Make some pre-defined tokens to ensure that some timelines are complete.
std::array<sp<IBinder> /*token*/, 10> predefinedTokens;
- for (size_t i = 0; i < predefinedTokens.size(); i++) {
- predefinedTokens[i] = sp<BBinder>::make();
+ for (sp<IBinder>& token : predefinedTokens) {
+ token = sp<BBinder>::make();
}
// Randomly invoke LatencyTracker api's until randomness is exhausted.
while (fdp.remaining_bytes() > 0) {
fdp.PickValueInArray<std::function<void()>>({
[&]() -> void {
- int32_t inputEventId = fdp.ConsumeIntegral<int32_t>();
- nsecs_t eventTime = fdp.ConsumeIntegral<nsecs_t>();
- nsecs_t readTime = fdp.ConsumeIntegral<nsecs_t>();
+ const int32_t inputEventId = fdp.ConsumeIntegral<int32_t>();
+ const nsecs_t eventTime = fdp.ConsumeIntegral<nsecs_t>();
+ const nsecs_t readTime = fdp.ConsumeIntegral<nsecs_t>();
const DeviceId deviceId = fdp.ConsumeIntegral<int32_t>();
+ const int32_t source = fdp.ConsumeIntegral<int32_t>();
std::set<InputDeviceUsageSource> sources = {
fdp.ConsumeEnum<InputDeviceUsageSource>()};
const int32_t inputEventActionType = fdp.ConsumeIntegral<int32_t>();
const InputEventType inputEventType = fdp.ConsumeEnum<InputEventType>();
- tracker.trackListener(inputEventId, eventTime, readTime, deviceId, sources,
- inputEventActionType, inputEventType);
+ const NotifyMotionArgs args =
+ MotionArgsBuilder(inputEventActionType, source, inputEventId)
+ .eventTime(eventTime)
+ .readTime(readTime)
+ .deviceId(deviceId)
+ .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
+ .x(100)
+ .y(200))
+ .build();
+ tracker.trackListener(args);
},
[&]() -> void {
- int32_t inputEventId = fdp.ConsumeIntegral<int32_t>();
+ const int32_t inputEventId = fdp.ConsumeIntegral<int32_t>();
sp<IBinder> connectionToken = getConnectionToken(fdp, predefinedTokens);
- nsecs_t deliveryTime = fdp.ConsumeIntegral<nsecs_t>();
- nsecs_t consumeTime = fdp.ConsumeIntegral<nsecs_t>();
- nsecs_t finishTime = fdp.ConsumeIntegral<nsecs_t>();
+ const nsecs_t deliveryTime = fdp.ConsumeIntegral<nsecs_t>();
+ const nsecs_t consumeTime = fdp.ConsumeIntegral<nsecs_t>();
+ const nsecs_t finishTime = fdp.ConsumeIntegral<nsecs_t>();
tracker.trackFinishedEvent(inputEventId, connectionToken, deliveryTime,
consumeTime, finishTime);
},
[&]() -> void {
- int32_t inputEventId = fdp.ConsumeIntegral<int32_t>();
+ const int32_t inputEventId = fdp.ConsumeIntegral<int32_t>();
sp<IBinder> connectionToken = getConnectionToken(fdp, predefinedTokens);
- std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
- for (size_t i = 0; i < graphicsTimeline.size(); i++) {
- graphicsTimeline[i] = fdp.ConsumeIntegral<nsecs_t>();
+ std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline{};
+ for (nsecs_t& t : graphicsTimeline) {
+ t = fdp.ConsumeIntegral<nsecs_t>();
}
tracker.trackGraphicsLatency(inputEventId, connectionToken, graphicsTimeline);
},
diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h
index fa8270a..bba7389 100644
--- a/services/inputflinger/tests/fuzzers/MapperHelpers.h
+++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h
@@ -34,6 +34,28 @@
android::EventHubInterface::DEVICE_ADDED,
android::EventHubInterface::DEVICE_REMOVED};
+static const android::InputDeviceClass kInputDeviceClasses[] = {
+ android::InputDeviceClass::KEYBOARD,
+ android::InputDeviceClass::ALPHAKEY,
+ android::InputDeviceClass::TOUCH,
+ android::InputDeviceClass::CURSOR,
+ android::InputDeviceClass::TOUCH_MT,
+ android::InputDeviceClass::DPAD,
+ android::InputDeviceClass::GAMEPAD,
+ android::InputDeviceClass::SWITCH,
+ android::InputDeviceClass::JOYSTICK,
+ android::InputDeviceClass::VIBRATOR,
+ android::InputDeviceClass::MIC,
+ android::InputDeviceClass::EXTERNAL_STYLUS,
+ android::InputDeviceClass::ROTARY_ENCODER,
+ android::InputDeviceClass::SENSOR,
+ android::InputDeviceClass::BATTERY,
+ android::InputDeviceClass::LIGHT,
+ android::InputDeviceClass::TOUCHPAD,
+ android::InputDeviceClass::VIRTUAL,
+ android::InputDeviceClass::EXTERNAL,
+};
+
constexpr size_t kValidCodes[] = {
SYN_REPORT,
ABS_MT_SLOT,
@@ -105,7 +127,13 @@
void addProperty(std::string key, std::string value) { mFuzzConfig.addProperty(key, value); }
ftl::Flags<InputDeviceClass> getDeviceClasses(int32_t deviceId) const override {
- return ftl::Flags<InputDeviceClass>(mFdp->ConsumeIntegral<uint32_t>());
+ uint32_t flags = 0;
+ for (auto inputDeviceClass : kInputDeviceClasses) {
+ if (mFdp->ConsumeBool()) {
+ flags |= static_cast<uint32_t>(inputDeviceClass);
+ }
+ }
+ return ftl::Flags<InputDeviceClass>(flags);
}
InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override {
return mIdentifier;
@@ -269,6 +297,9 @@
status_t enableDevice(int32_t deviceId) override { return mFdp->ConsumeIntegral<status_t>(); }
status_t disableDevice(int32_t deviceId) override { return mFdp->ConsumeIntegral<status_t>(); }
void sysfsNodeChanged(const std::string& sysfsNodePath) override {}
+ bool setKernelWakeEnabled(int32_t deviceId, bool enabled) override {
+ return mFdp->ConsumeBool();
+ }
};
class FuzzInputReaderPolicy : public InputReaderPolicyInterface {
@@ -285,6 +316,7 @@
void notifyTouchpadHardwareState(const SelfContainedHardwareState& schs,
int32_t deviceId) override {}
void notifyTouchpadGestureInfo(GestureType type, int32_t deviceId) override {}
+ void notifyTouchpadThreeFingerTap() override {}
std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay(
const InputDeviceIdentifier& identifier,
const std::optional<KeyboardLayoutInfo> layoutInfo) override {
@@ -342,7 +374,7 @@
}
InputReaderPolicyInterface* getPolicy() override { return mPolicy.get(); }
EventHubInterface* getEventHub() override { return mEventHub.get(); }
- int32_t getNextId() override { return mFdp->ConsumeIntegral<int32_t>(); }
+ int32_t getNextId() const override { return mFdp->ConsumeIntegral<int32_t>(); }
void updateLedMetaState(int32_t metaState) override{};
int32_t getLedMetaState() override { return mFdp->ConsumeIntegral<int32_t>(); };
@@ -363,8 +395,8 @@
template <class Fdp>
InputDevice getFuzzedInputDevice(Fdp& fdp, FuzzInputReaderContext* context) {
InputDeviceIdentifier identifier;
- identifier.name = fdp.ConsumeRandomLengthString(16);
- identifier.location = fdp.ConsumeRandomLengthString(12);
+ identifier.name = fdp.ConsumeRandomLengthUtf8String(16);
+ identifier.location = fdp.ConsumeRandomLengthUtf8String(12);
int32_t deviceID = fdp.ConsumeIntegralInRange(0, 5);
int32_t deviceGeneration = fdp.ConsumeIntegralInRange(0, 5);
return InputDevice(context, deviceID, deviceGeneration, identifier);
diff --git a/services/inputflinger/tests/fuzzers/ThreadSafeFuzzedDataProvider.h b/services/inputflinger/tests/fuzzers/ThreadSafeFuzzedDataProvider.h
index 2f76f18..b258118 100644
--- a/services/inputflinger/tests/fuzzers/ThreadSafeFuzzedDataProvider.h
+++ b/services/inputflinger/tests/fuzzers/ThreadSafeFuzzedDataProvider.h
@@ -15,7 +15,7 @@
*/
#include <fuzzer/FuzzedDataProvider.h>
-
+#include <algorithm>
/**
* A thread-safe interface to the FuzzedDataProvider
*/
@@ -60,6 +60,44 @@
return FuzzedDataProvider::ConsumeRandomLengthString();
}
+ // Converting the string to a UTF-8 string by setting the prefix bits of each
+ // byte according to UTF-8 encoding rules.
+ std::string ConsumeRandomLengthUtf8String(size_t max_length) {
+ std::scoped_lock _l(mLock);
+ std::string result = FuzzedDataProvider::ConsumeRandomLengthString(max_length);
+ size_t remaining_bytes = result.length(), idx = 0;
+ while (remaining_bytes > 0) {
+ size_t random_byte_size = FuzzedDataProvider::ConsumeIntegralInRange(1, 4);
+ size_t byte_size = std::min(random_byte_size, remaining_bytes);
+ switch (byte_size) {
+ // Prefix byte: 0xxxxxxx
+ case 1:
+ result[idx++] &= 0b01111111;
+ break;
+ // Prefix bytes: 110xxxxx 10xxxxxx
+ case 2:
+ result[idx++] = (result[idx] & 0b00011111) | 0b11000000;
+ result[idx++] = (result[idx] & 0b00111111) | 0b10000000;
+ break;
+ // Prefix bytes: 1110xxxx 10xxxxxx 10xxxxxx
+ case 3:
+ result[idx++] = (result[idx] & 0b00001111) | 0b11100000;
+ result[idx++] = (result[idx] & 0b00111111) | 0b10000000;
+ result[idx++] = (result[idx] & 0b00111111) | 0b10000000;
+ break;
+ // Prefix bytes: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ case 4:
+ result[idx++] = (result[idx] & 0b00000111) | 0b11110000;
+ result[idx++] = (result[idx] & 0b00111111) | 0b10000000;
+ result[idx++] = (result[idx] & 0b00111111) | 0b10000000;
+ result[idx++] = (result[idx] & 0b00111111) | 0b10000000;
+ break;
+ }
+ remaining_bytes -= byte_size;
+ }
+ return result;
+ }
+
std::string ConsumeRemainingBytesAsString() {
std::scoped_lock _l(mLock);
return FuzzedDataProvider::ConsumeRemainingBytesAsString();
diff --git a/services/powermanager/PowerHalController.cpp b/services/powermanager/PowerHalController.cpp
index 40fd097..0ba1909 100644
--- a/services/powermanager/PowerHalController.cpp
+++ b/services/powermanager/PowerHalController.cpp
@@ -168,6 +168,11 @@
"closeSessionChannel"));
}
+HalResult<aidl::android::hardware::power::SupportInfo> PowerHalController::getSupportInfo() {
+ std::shared_ptr<HalWrapper> handle = initHal();
+ return CACHE_SUPPORT(6, processHalResult(handle->getSupportInfo(), "getSupportInfo"));
+}
+
} // namespace power
} // namespace android
diff --git a/services/powermanager/PowerHalWrapper.cpp b/services/powermanager/PowerHalWrapper.cpp
index bd6685c..068c23f 100644
--- a/services/powermanager/PowerHalWrapper.cpp
+++ b/services/powermanager/PowerHalWrapper.cpp
@@ -18,6 +18,7 @@
#include <aidl/android/hardware/power/Boost.h>
#include <aidl/android/hardware/power/IPowerHintSession.h>
#include <aidl/android/hardware/power/Mode.h>
+#include <aidl/android/hardware/power/SupportInfo.h>
#include <powermanager/HalResult.h>
#include <powermanager/PowerHalWrapper.h>
#include <utils/Log.h>
@@ -73,6 +74,11 @@
return HalResult<void>::unsupported();
}
+HalResult<Aidl::SupportInfo> EmptyHalWrapper::getSupportInfo() {
+ ALOGV("Skipped getSupportInfo because %s", getUnsupportedMessage());
+ return HalResult<Aidl::SupportInfo>::unsupported();
+}
+
const char* EmptyHalWrapper::getUnsupportedMessage() {
return "Power HAL is not supported";
}
@@ -280,6 +286,12 @@
return HalResult<void>::fromStatus(mHandle->closeSessionChannel(tgid, uid));
}
+HalResult<Aidl::SupportInfo> AidlHalWrapper::getSupportInfo() {
+ Aidl::SupportInfo support;
+ auto result = mHandle->getSupportInfo(&support);
+ return HalResult<Aidl::SupportInfo>::fromStatus(result, std::move(support));
+}
+
const char* AidlHalWrapper::getUnsupportedMessage() {
return "Power HAL doesn't support it";
}
diff --git a/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp b/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp
index 61ab47a..3a1b426 100644
--- a/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp
+++ b/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp
@@ -40,10 +40,10 @@
using namespace std::chrono_literals;
// Values from Boost.aidl and Mode.aidl.
-static constexpr int64_t FIRST_BOOST = static_cast<int64_t>(Boost::INTERACTION);
-static constexpr int64_t LAST_BOOST = static_cast<int64_t>(Boost::CAMERA_SHOT);
-static constexpr int64_t FIRST_MODE = static_cast<int64_t>(Mode::DOUBLE_TAP_TO_WAKE);
-static constexpr int64_t LAST_MODE = static_cast<int64_t>(Mode::CAMERA_STREAMING_HIGH);
+static constexpr int64_t FIRST_BOOST = static_cast<int64_t>(*ndk::enum_range<Boost>().begin());
+static constexpr int64_t LAST_BOOST = static_cast<int64_t>(*(ndk::enum_range<Boost>().end()-1));
+static constexpr int64_t FIRST_MODE = static_cast<int64_t>(*ndk::enum_range<Mode>().begin());
+static constexpr int64_t LAST_MODE = static_cast<int64_t>(*(ndk::enum_range<Mode>().end()-1));
class DurationWrapper : public WorkDuration {
public:
@@ -81,14 +81,17 @@
return;
}
- while (state.KeepRunning()) {
+ for (auto _ : state) {
ret = (*hal.*fn)(std::forward<Args1>(args1)...);
- state.PauseTiming();
- if (!ret.isOk()) state.SkipWithError(ret.getDescription().c_str());
- if (delay > 0us) {
- testDelaySpin(std::chrono::duration_cast<std::chrono::duration<float>>(delay).count());
+ if (!ret.isOk()) {
+ state.SkipWithError(ret.getDescription().c_str());
+ break;
}
- state.ResumeTiming();
+ if (delay > 0us) {
+ state.PauseTiming();
+ testDelaySpin(std::chrono::duration_cast<std::chrono::duration<float>>(delay).count());
+ state.ResumeTiming();
+ }
}
}
@@ -123,14 +126,15 @@
return;
}
- while (state.KeepRunning()) {
+ for (auto _ : state) {
ret = (*session.*fn)(std::forward<Args1>(args1)...);
- state.PauseTiming();
- if (!ret.isOk()) state.SkipWithError(ret.getDescription().c_str());
- if (ONEWAY_API_DELAY > 0us) {
- testDelaySpin(std::chrono::duration_cast<std::chrono::duration<float>>(ONEWAY_API_DELAY)
- .count());
+ if (!ret.isOk()) {
+ state.SkipWithError(ret.getDescription().c_str());
+ break;
}
+ state.PauseTiming();
+ testDelaySpin(std::chrono::duration_cast<std::chrono::duration<float>>(ONEWAY_API_DELAY)
+ .count());
state.ResumeTiming();
}
session->close();
@@ -150,11 +154,41 @@
static void BM_PowerHalAidlBenchmarks_setBoost(benchmark::State& state) {
Boost boost = static_cast<Boost>(state.range(0));
+ bool isSupported;
+ std::shared_ptr<IPower> hal = PowerHalLoader::loadAidl();
+
+ if (hal == nullptr) {
+ ALOGV("Power HAL not available, skipping test...");
+ state.SkipWithMessage("Power HAL unavailable");
+ return;
+ }
+
+ ndk::ScopedAStatus ret = hal->isBoostSupported(boost, &isSupported);
+ if (!ret.isOk() || !isSupported) {
+ state.SkipWithMessage("operation unsupported");
+ return;
+ }
+
runBenchmark(state, ONEWAY_API_DELAY, &IPower::setBoost, boost, 1);
}
static void BM_PowerHalAidlBenchmarks_setMode(benchmark::State& state) {
Mode mode = static_cast<Mode>(state.range(0));
+ bool isSupported;
+ std::shared_ptr<IPower> hal = PowerHalLoader::loadAidl();
+
+ if (hal == nullptr) {
+ ALOGV("Power HAL not available, skipping test...");
+ state.SkipWithMessage("Power HAL unavailable");
+ return;
+ }
+
+ ndk::ScopedAStatus ret = hal->isModeSupported(mode, &isSupported);
+ if (!ret.isOk() || !isSupported) {
+ state.SkipWithMessage("operation unsupported");
+ return;
+ }
+
runBenchmark(state, ONEWAY_API_DELAY, &IPower::setMode, mode, false);
}
@@ -178,12 +212,20 @@
ALOGV("Power HAL does not support this operation, skipping test...");
state.SkipWithMessage("operation unsupported");
return;
+ } else if (!ret.isOk()) {
+ state.SkipWithError(ret.getDescription().c_str());
+ return;
+ } else {
+ appSession->close();
}
- while (state.KeepRunning()) {
+ for (auto _ : state) {
ret = hal->createHintSession(tgid, uid, threadIds, durationNanos, &appSession);
+ if (!ret.isOk()) {
+ state.SkipWithError(ret.getDescription().c_str());
+ break;
+ }
state.PauseTiming();
- if (!ret.isOk()) state.SkipWithError(ret.getDescription().c_str());
appSession->close();
state.ResumeTiming();
}
diff --git a/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp b/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp
index effddda..0fda686 100644
--- a/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp
+++ b/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp
@@ -19,9 +19,9 @@
#include <aidl/android/hardware/power/Boost.h>
#include <aidl/android/hardware/power/Mode.h>
#include <benchmark/benchmark.h>
+#include <chrono>
#include <powermanager/PowerHalController.h>
#include <testUtil.h>
-#include <chrono>
using aidl::android::hardware::power::Boost;
using aidl::android::hardware::power::Mode;
@@ -32,10 +32,10 @@
using namespace std::chrono_literals;
// Values from Boost.aidl and Mode.aidl.
-static constexpr int64_t FIRST_BOOST = static_cast<int64_t>(Boost::INTERACTION);
-static constexpr int64_t LAST_BOOST = static_cast<int64_t>(Boost::CAMERA_SHOT);
-static constexpr int64_t FIRST_MODE = static_cast<int64_t>(Mode::DOUBLE_TAP_TO_WAKE);
-static constexpr int64_t LAST_MODE = static_cast<int64_t>(Mode::CAMERA_STREAMING_HIGH);
+static constexpr int64_t FIRST_BOOST = static_cast<int64_t>(*ndk::enum_range<Boost>().begin());
+static constexpr int64_t LAST_BOOST = static_cast<int64_t>(*(ndk::enum_range<Boost>().end()-1));
+static constexpr int64_t FIRST_MODE = static_cast<int64_t>(*ndk::enum_range<Mode>().begin());
+static constexpr int64_t LAST_MODE = static_cast<int64_t>(*(ndk::enum_range<Mode>().end()-1));
// Delay between oneway method calls to avoid overflowing the binder buffers.
static constexpr std::chrono::microseconds ONEWAY_API_DELAY = 100us;
@@ -43,11 +43,27 @@
template <typename T, class... Args0, class... Args1>
static void runBenchmark(benchmark::State& state, HalResult<T> (PowerHalController::*fn)(Args0...),
Args1&&... args1) {
- while (state.KeepRunning()) {
- PowerHalController controller;
+ PowerHalController initController;
+ HalResult<T> result = (initController.*fn)(std::forward<Args1>(args1)...);
+ if (result.isFailed()) {
+ state.SkipWithError(result.errorMessage());
+ return;
+ } else if (result.isUnsupported()) {
+ ALOGV("Power HAL does not support this operation, skipping test...");
+ state.SkipWithMessage("operation unsupported");
+ return;
+ }
+
+ for (auto _ : state) {
+ PowerHalController controller; // new controller to avoid caching
HalResult<T> ret = (controller.*fn)(std::forward<Args1>(args1)...);
+ if (ret.isFailed()) {
+ state.SkipWithError(ret.errorMessage());
+ break;
+ }
state.PauseTiming();
- if (ret.isFailed()) state.SkipWithError("Power HAL request failed");
+ testDelaySpin(
+ std::chrono::duration_cast<std::chrono::duration<float>>(ONEWAY_API_DELAY).count());
state.ResumeTiming();
}
}
@@ -57,22 +73,27 @@
HalResult<T> (PowerHalController::*fn)(Args0...), Args1&&... args1) {
PowerHalController controller;
// First call out of test, to cache HAL service and isSupported result.
- (controller.*fn)(std::forward<Args1>(args1)...);
+ HalResult<T> result = (controller.*fn)(std::forward<Args1>(args1)...);
+ if (result.isFailed()) {
+ state.SkipWithError(result.errorMessage());
+ return;
+ } else if (result.isUnsupported()) {
+ ALOGV("Power HAL does not support this operation, skipping test...");
+ state.SkipWithMessage("operation unsupported");
+ return;
+ }
- while (state.KeepRunning()) {
+ for (auto _ : state) {
HalResult<T> ret = (controller.*fn)(std::forward<Args1>(args1)...);
- state.PauseTiming();
if (ret.isFailed()) {
- state.SkipWithError("Power HAL request failed");
+ state.SkipWithError(ret.errorMessage());
+ break;
}
- testDelaySpin(
- std::chrono::duration_cast<std::chrono::duration<float>>(ONEWAY_API_DELAY).count());
- state.ResumeTiming();
}
}
static void BM_PowerHalControllerBenchmarks_init(benchmark::State& state) {
- while (state.KeepRunning()) {
+ for (auto _ : state) {
PowerHalController controller;
controller.init();
}
@@ -90,12 +111,12 @@
static void BM_PowerHalControllerBenchmarks_setBoost(benchmark::State& state) {
Boost boost = static_cast<Boost>(state.range(0));
- runBenchmark(state, &PowerHalController::setBoost, boost, 0);
+ runBenchmark(state, &PowerHalController::setBoost, boost, 1);
}
static void BM_PowerHalControllerBenchmarks_setBoostCached(benchmark::State& state) {
Boost boost = static_cast<Boost>(state.range(0));
- runCachedBenchmark(state, &PowerHalController::setBoost, boost, 0);
+ runCachedBenchmark(state, &PowerHalController::setBoost, boost, 1);
}
static void BM_PowerHalControllerBenchmarks_setMode(benchmark::State& state) {
diff --git a/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp b/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp
index bcb376b..95fd0c2 100644
--- a/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp
+++ b/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp
@@ -54,14 +54,17 @@
return;
}
- while (state.KeepRunning()) {
+ for (auto _ : state) {
Return<R> ret = (*hal.*fn)(std::forward<Args1>(args1)...);
- state.PauseTiming();
- if (!ret.isOk()) state.SkipWithError(ret.description().c_str());
- if (delay > 0us) {
- testDelaySpin(std::chrono::duration_cast<std::chrono::duration<float>>(delay).count());
+ if (!ret.isOk()) {
+ state.SkipWithError(ret.description().c_str());
+ break;
}
- state.ResumeTiming();
+ if (delay > 0us) {
+ state.PauseTiming();
+ testDelaySpin(std::chrono::duration_cast<std::chrono::duration<float>>(delay).count());
+ state.ResumeTiming();
+ }
}
}
diff --git a/services/powermanager/tests/PowerHalWrapperAidlTest.cpp b/services/powermanager/tests/PowerHalWrapperAidlTest.cpp
index 1589c99..682d1f4 100644
--- a/services/powermanager/tests/PowerHalWrapperAidlTest.cpp
+++ b/services/powermanager/tests/PowerHalWrapperAidlTest.cpp
@@ -28,15 +28,10 @@
#include <unistd.h>
#include <thread>
-using aidl::android::hardware::power::Boost;
-using aidl::android::hardware::power::ChannelConfig;
-using aidl::android::hardware::power::IPower;
-using aidl::android::hardware::power::IPowerHintSession;
-using aidl::android::hardware::power::Mode;
-using aidl::android::hardware::power::SessionConfig;
-using aidl::android::hardware::power::SessionTag;
+
using android::binder::Status;
+using namespace aidl::android::hardware::power;
using namespace android;
using namespace android::power;
using namespace std::chrono_literals;
@@ -65,10 +60,19 @@
(int32_t tgid, int32_t uid, ChannelConfig* _aidl_return), (override));
MOCK_METHOD(ndk::ScopedAStatus, closeSessionChannel, (int32_t tgid, int32_t uid), (override));
MOCK_METHOD(ndk::ScopedAStatus, getHintSessionPreferredRate, (int64_t * rate), (override));
+ MOCK_METHOD(ndk::ScopedAStatus, getSupportInfo, (SupportInfo * _aidl_return), (override));
MOCK_METHOD(ndk::ScopedAStatus, getInterfaceVersion, (int32_t * version), (override));
MOCK_METHOD(ndk::ScopedAStatus, getInterfaceHash, (std::string * hash), (override));
MOCK_METHOD(ndk::SpAIBinder, asBinder, (), (override));
MOCK_METHOD(bool, isRemote, (), (override));
+ MOCK_METHOD(ndk::ScopedAStatus, getCpuHeadroom,
+ (const CpuHeadroomParams& params, CpuHeadroomResult* headroom), (override));
+ MOCK_METHOD(ndk::ScopedAStatus, getGpuHeadroom,
+ (const GpuHeadroomParams& params, GpuHeadroomResult* headroom), (override));
+ MOCK_METHOD(ndk::ScopedAStatus, sendCompositionData,
+ (const std::vector<CompositionData>& in_data), (override));
+ MOCK_METHOD(ndk::ScopedAStatus, sendCompositionUpdate,
+ (const CompositionUpdate& in_update), (override));
};
// -------------------------------------------------------------------------------------------------
diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp
index 7b2596a..9ecd101 100644
--- a/services/sensorservice/Android.bp
+++ b/services/sensorservice/Android.bp
@@ -11,7 +11,7 @@
name: "sensorservice_flags",
package: "com.android.frameworks.sensorservice.flags",
container: "system",
- srcs: ["senserservice_flags.aconfig"],
+ srcs: ["sensorservice_flags.aconfig"],
}
cc_aconfig_library {
@@ -61,38 +61,38 @@
],
shared_libs: [
- "libcutils",
- "libhardware",
- "libhardware_legacy",
- "libutils",
- "liblog",
- "libactivitymanager_aidl",
- "libbatterystats_aidl",
- "libbinder",
- "libsensor",
- "libsensorprivacy",
- "libpermission",
- "libprotoutil",
- "libcrypto",
- "libbase",
- "libhidlbase",
- "libfmq",
- "libbinder_ndk",
- "packagemanager_aidl-cpp",
+ "android.hardware.common-V2-ndk",
+ "android.hardware.common.fmq-V1-ndk",
"android.hardware.sensors@1.0",
"android.hardware.sensors@2.0",
"android.hardware.sensors@2.1",
- "android.hardware.common-V2-ndk",
- "android.hardware.common.fmq-V1-ndk",
- "server_configurable_flags",
"libaconfig_storage_read_api_cc",
+ "libactivitymanager_aidl",
+ "libbase",
+ "libbatterystats_aidl",
+ "libbinder",
+ "libbinder_ndk",
+ "libcrypto",
+ "libcutils",
+ "libfmq",
+ "libhardware",
+ "libhardware_legacy",
+ "libhidlbase",
+ "liblog",
+ "libpermission",
+ "libprotoutil",
+ "libsensor",
+ "libsensorprivacy",
+ "libutils",
+ "packagemanager_aidl-cpp",
+ "server_configurable_flags",
],
static_libs: [
- "libaidlcommonsupport",
- "android.hardware.sensors@1.0-convert",
"android.hardware.sensors-V1-convert",
- "android.hardware.sensors-V2-ndk",
+ "android.hardware.sensors-V3-ndk",
+ "android.hardware.sensors@1.0-convert",
+ "libaidlcommonsupport",
"sensorservice_flags_c_lib",
],
@@ -100,9 +100,9 @@
export_shared_lib_headers: [
"libactivitymanager_aidl",
+ "libpermission",
"libsensor",
"libsensorprivacy",
- "libpermission",
],
afdo: true,
@@ -120,9 +120,9 @@
srcs: ["main_sensorservice.cpp"],
shared_libs: [
- "libsensorservice",
- "libsensorprivacy",
"libbinder",
+ "libsensorprivacy",
+ "libsensorservice",
"libutils",
],
diff --git a/services/sensorservice/OWNERS b/services/sensorservice/OWNERS
index 7347ac7..3ccdc17 100644
--- a/services/sensorservice/OWNERS
+++ b/services/sensorservice/OWNERS
@@ -1 +1,3 @@
bduddie@google.com
+arthuri@google.com
+rockyfang@google.com
diff --git a/services/sensorservice/aidl/Android.bp b/services/sensorservice/aidl/Android.bp
index 542fcae..b9a3491 100644
--- a/services/sensorservice/aidl/Android.bp
+++ b/services/sensorservice/aidl/Android.bp
@@ -28,7 +28,7 @@
"libbinder_ndk",
"libsensor",
"android.frameworks.sensorservice-V1-ndk",
- "android.hardware.sensors-V2-ndk",
+ "android.hardware.sensors-V3-ndk",
],
export_include_dirs: [
"include/",
diff --git a/services/sensorservice/aidl/fuzzer/Android.bp b/services/sensorservice/aidl/fuzzer/Android.bp
index b2dc89b..f38cf5a 100644
--- a/services/sensorservice/aidl/fuzzer/Android.bp
+++ b/services/sensorservice/aidl/fuzzer/Android.bp
@@ -20,8 +20,9 @@
"android.companion.virtual.virtualdevice_aidl-cpp",
"android.frameworks.sensorservice-V1-ndk",
"android.hardware.sensors-V1-convert",
- "android.hardware.sensors-V2-ndk",
+ "android.hardware.sensors-V3-ndk",
"android.hardware.common-V2-ndk",
+ "framework-permission-aidl-cpp",
"libsensor",
"libfakeservicemanager",
"libcutils",
diff --git a/services/sensorservice/senserservice_flags.aconfig b/services/sensorservice/sensorservice_flags.aconfig
similarity index 79%
rename from services/sensorservice/senserservice_flags.aconfig
rename to services/sensorservice/sensorservice_flags.aconfig
index 7abfbaa..452b428 100644
--- a/services/sensorservice/senserservice_flags.aconfig
+++ b/services/sensorservice/sensorservice_flags.aconfig
@@ -28,3 +28,13 @@
description: "When this flag is enabled, sensor service will only erase dynamic sensor data at the end of the threadLoop to prevent race condition."
bug: "329020894"
}
+
+flag {
+ name: "enforce_permissions_for_all_target_sdk"
+ namespace: "sensors"
+ description: "When this flag is enabled, sensor service will enforce permissions for all target sdks."
+ bug: "389176817"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
\ No newline at end of file
diff --git a/services/stats/Android.bp b/services/stats/Android.bp
index 6b99627..f698515 100644
--- a/services/stats/Android.bp
+++ b/services/stats/Android.bp
@@ -7,6 +7,11 @@
default_applicable_licenses: ["frameworks_native_license"],
}
+vintf_fragment {
+ name: "android.frameworks.stats-service.xml",
+ src: "android.frameworks.stats-service.xml",
+}
+
cc_library_shared {
name: "libstatshidl",
srcs: [
@@ -38,7 +43,7 @@
local_include_dirs: [
"include/stats",
],
- vintf_fragments: [
+ vintf_fragment_modules: [
"android.frameworks.stats-service.xml",
],
}
diff --git a/services/stats/OWNERS b/services/stats/OWNERS
index a61babf..791b711 100644
--- a/services/stats/OWNERS
+++ b/services/stats/OWNERS
@@ -1,9 +1,7 @@
jeffreyhuang@google.com
joeo@google.com
-jtnguyen@google.com
muhammadq@google.com
ruchirr@google.com
singhtejinder@google.com
tsaichristine@google.com
yaochen@google.com
-yro@google.com
diff --git a/services/surfaceflinger/ActivePictureTracker.cpp b/services/surfaceflinger/ActivePictureTracker.cpp
new file mode 100644
index 0000000..4e6fa66
--- /dev/null
+++ b/services/surfaceflinger/ActivePictureTracker.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2024 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 "ActivePictureTracker.h"
+
+#include <algorithm>
+
+#include "Layer.h"
+#include "LayerFE.h"
+
+namespace android {
+
+using gui::ActivePicture;
+using gui::IActivePictureListener;
+
+void ActivePictureTracker::onLayerComposed(const Layer& layer, const LayerFE& layerFE,
+ const CompositionResult& result) {
+ if (result.wasPictureProfileCommitted) {
+ gui::ActivePicture picture;
+ picture.layerId = int32_t(layer.sequence);
+ picture.ownerUid = int32_t(layer.getOwnerUid());
+ // TODO(b/337330263): Why does LayerFE coming from SF have a null composition state?
+ if (layerFE.getCompositionState()) {
+ picture.pictureProfileId = layerFE.getCompositionState()->pictureProfileHandle.getId();
+ } else {
+ picture.pictureProfileId = result.pictureProfileHandle.getId();
+ }
+ mNewActivePictures.push_back(picture);
+ }
+}
+
+void ActivePictureTracker::updateAndNotifyListeners(const Listeners& listenersToAdd,
+ const Listeners& listenersToRemove) {
+ Listeners newListeners = updateListeners(listenersToAdd, listenersToRemove);
+ if (updateAndHasChanged()) {
+ for (auto listener : mListeners) {
+ listener->onActivePicturesChanged(getActivePictures());
+ }
+ } else {
+ for (auto listener : newListeners) {
+ listener->onActivePicturesChanged(getActivePictures());
+ }
+ }
+}
+
+ActivePictureTracker::Listeners ActivePictureTracker::updateListeners(
+ const Listeners& listenersToAdd, const Listeners& listenersToRemove) {
+ Listeners newListeners;
+ for (auto listener : listenersToRemove) {
+ std::erase_if(mListeners, [listener](const sp<IActivePictureListener>& otherListener) {
+ return IInterface::asBinder(listener) == IInterface::asBinder(otherListener);
+ });
+ }
+ for (auto listener : listenersToAdd) {
+ if (std::find_if(mListeners.begin(), mListeners.end(),
+ [listener](const sp<IActivePictureListener>& otherListener) {
+ return IInterface::asBinder(listener) ==
+ IInterface::asBinder(otherListener);
+ }) == mListeners.end()) {
+ newListeners.push_back(listener);
+ }
+ }
+ for (auto listener : newListeners) {
+ mListeners.push_back(listener);
+ }
+ return newListeners;
+}
+
+bool ActivePictureTracker::updateAndHasChanged() {
+ bool hasChanged = true;
+ if (mNewActivePictures.size() == mOldActivePictures.size()) {
+ auto compare = [](const ActivePicture& lhs, const ActivePicture& rhs) -> int {
+ if (lhs.layerId == rhs.layerId) {
+ return lhs.pictureProfileId < rhs.pictureProfileId;
+ }
+ return lhs.layerId < rhs.layerId;
+ };
+ std::sort(mNewActivePictures.begin(), mNewActivePictures.end(), compare);
+ if (std::equal(mNewActivePictures.begin(), mNewActivePictures.end(),
+ mOldActivePictures.begin())) {
+ hasChanged = false;
+ }
+ }
+ std::swap(mOldActivePictures, mNewActivePictures);
+ mNewActivePictures.resize(0);
+ return hasChanged;
+}
+
+const std::vector<ActivePicture>& ActivePictureTracker::getActivePictures() const {
+ return mOldActivePictures;
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/ActivePictureTracker.h b/services/surfaceflinger/ActivePictureTracker.h
new file mode 100644
index 0000000..cb319a5
--- /dev/null
+++ b/services/surfaceflinger/ActivePictureTracker.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2024 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 <vector>
+
+#include <android/gui/ActivePicture.h>
+#include <android/gui/IActivePictureListener.h>
+
+namespace android {
+
+class Layer;
+class LayerFE;
+struct CompositionResult;
+
+// Keeps track of active pictures - layers that are undergoing picture processing.
+class ActivePictureTracker {
+public:
+ typedef std::vector<sp<gui::IActivePictureListener>> Listeners;
+
+ // Called for each visible layer when SurfaceFlinger finishes composing.
+ void onLayerComposed(const Layer& layer, const LayerFE& layerFE,
+ const CompositionResult& result);
+
+ // Update internals and return whether the set of active pictures have changed.
+ void updateAndNotifyListeners(const Listeners& activePictureListenersToAdd,
+ const Listeners& activePictureListenersToRemove);
+
+ // The current set of active pictures.
+ const std::vector<gui::ActivePicture>& getActivePictures() const;
+
+private:
+ Listeners updateListeners(const Listeners& listenersToAdd, const Listeners& listenersToRemove);
+ bool updateAndHasChanged();
+
+ std::vector<gui::ActivePicture> mOldActivePictures;
+ std::vector<gui::ActivePicture> mNewActivePictures;
+ Listeners mListeners;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 7babd17..9aa1ffa 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -26,15 +26,15 @@
cc_defaults {
name: "surfaceflinger_defaults",
cflags: [
+ "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
"-Wall",
+ "-Wconversion",
"-Werror",
"-Wextra",
"-Wformat",
"-Wthread-safety",
- "-Wunused",
"-Wunreachable-code",
- "-Wconversion",
- "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
+ "-Wunused",
],
}
@@ -42,57 +42,57 @@
name: "libsurfaceflinger_defaults",
defaults: [
"android.hardware.graphics.composer3-ndk_shared",
- "android.hardware.power-ndk_shared",
"librenderengine_deps",
- "libtimestats_deps",
"libsurfaceflinger_common_deps",
- "surfaceflinger_defaults",
"libsurfaceflinger_proto_deps",
+ "libtimestats_deps",
+ "poweradvisor_deps",
+ "surfaceflinger_defaults",
],
cflags: [
- "-DLOG_TAG=\"SurfaceFlinger\"",
- "-DGL_GLEXT_PROTOTYPES",
"-DEGL_EGLEXT_PROTOTYPES",
+ "-DGL_GLEXT_PROTOTYPES",
+ "-DLOG_TAG=\"SurfaceFlinger\"",
],
shared_libs: [
+ "android.hardware.common-V2-ndk",
+ "android.hardware.common.fmq-V1-ndk",
"android.hardware.configstore-utils",
"android.hardware.configstore@1.0",
"android.hardware.configstore@1.1",
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.common@1.2",
- "android.hardware.common-V2-ndk",
- "android.hardware.common.fmq-V1-ndk",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.2",
"android.hardware.graphics.composer@2.3",
"android.hardware.graphics.composer@2.4",
+ "android.os.flags-aconfig-cc-host",
+ "libEGL",
+ "libGLESv1_CM",
+ "libGLESv2",
+ "libSurfaceFlingerProp",
+ "libaconfig_storage_read_api_cc",
"libbase",
"libbinder",
"libbinder_ndk",
"libcutils",
- "libEGL",
"libfmq",
- "libGLESv1_CM",
- "libGLESv2",
"libgui",
"libhidlbase",
"liblog",
"libnativewindow",
- "libpowermanager",
"libprocessgroup",
"libprotobuf-cpp-lite",
+ "libstatslog_surfaceflinger",
"libsync",
"libui",
"libutils",
- "libSurfaceFlingerProp",
- "libaconfig_storage_read_api_cc",
],
static_libs: [
"iinputflinger_aidl_lib_static",
"libaidlcommonsupport",
"libcompositionengine",
- "libframetimeline",
"libgui_aidl_static",
"libperfetto_client_experimental",
"librenderengine",
@@ -104,11 +104,11 @@
"libtonemap",
],
header_libs: [
+ "android.hardware.graphics.composer3-command-buffer",
"android.hardware.graphics.composer@2.1-command-buffer",
"android.hardware.graphics.composer@2.2-command-buffer",
"android.hardware.graphics.composer@2.3-command-buffer",
"android.hardware.graphics.composer@2.4-command-buffer",
- "android.hardware.graphics.composer3-command-buffer",
],
export_static_lib_headers: [
"libcompositionengine",
@@ -124,8 +124,8 @@
"android.hardware.graphics.composer@2.2",
"android.hardware.graphics.composer@2.3",
"android.hardware.graphics.composer@2.4",
- "libpowermanager",
"libhidlbase",
+ "libpowermanager",
],
// TODO (marissaw): this library is not used by surfaceflinger. This is here so
// the library compiled in a way that is accessible to system partition when running
@@ -147,6 +147,46 @@
},
}
+// libsurfaceflinger_backend_{headers|sources} are a step towards pulling out
+// the "backend" sources to clean up the dependency graph between
+// CompositionEngine and SurfaceFlinger. Completing the cleanup would require
+// moving the headers in particular so that the dependency can strictly be a
+// DAG. There would certainly be additional cleanups: VirtualDisplaySurface.cpp
+// and FrameBufferSurface.cpp likely belong in CompositionEngine for example.
+cc_library_headers {
+ name: "libsurfaceflinger_backend_headers",
+ export_include_dirs: ["."],
+ static_libs: ["libserviceutils"],
+ export_static_lib_headers: ["libserviceutils"],
+
+ shared_libs: [
+ "android.hardware.configstore-utils",
+ "android.hardware.configstore@1.0",
+ "android.hardware.configstore@1.1",
+ "libbinder_ndk",
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.configstore-utils",
+ "android.hardware.configstore@1.0",
+ "android.hardware.configstore@1.1",
+ "libbinder_ndk",
+ ],
+}
+
+filegroup {
+ name: "libsurfaceflinger_backend_sources",
+ srcs: [
+ "DisplayHardware/AidlComposerHal.cpp",
+ "DisplayHardware/ComposerHal.cpp",
+ "DisplayHardware/FramebufferSurface.cpp",
+ "DisplayHardware/HWC2.cpp",
+ "DisplayHardware/HWComposer.cpp",
+ "DisplayHardware/HidlComposerHal.cpp",
+ "DisplayHardware/VirtualDisplaySurface.cpp",
+ "PowerAdvisor/*.cpp",
+ ],
+}
+
cc_library_headers {
name: "libsurfaceflinger_headers",
export_include_dirs: ["."],
@@ -157,52 +197,43 @@
filegroup {
name: "libsurfaceflinger_sources",
srcs: [
+ ":libsurfaceflinger_backend_sources",
+ "ActivePictureTracker.cpp",
"BackgroundExecutor.cpp",
"Client.cpp",
"ClientCache.cpp",
"Display/DisplayModeController.cpp",
"Display/DisplaySnapshot.cpp",
"DisplayDevice.cpp",
- "DisplayHardware/AidlComposerHal.cpp",
- "DisplayHardware/ComposerHal.cpp",
- "DisplayHardware/FramebufferSurface.cpp",
- "DisplayHardware/HWC2.cpp",
- "DisplayHardware/HWComposer.cpp",
- "DisplayHardware/HidlComposerHal.cpp",
- "DisplayHardware/PowerAdvisor.cpp",
- "DisplayHardware/VirtualDisplaySurface.cpp",
- "DisplayRenderArea.cpp",
"Effects/Daltonizer.cpp",
- "FrontEnd/LayerCreationArgs.cpp",
- "FrontEnd/LayerHandle.cpp",
- "FrontEnd/LayerSnapshot.cpp",
- "FrontEnd/LayerSnapshotBuilder.cpp",
- "FrontEnd/LayerHierarchy.cpp",
- "FrontEnd/LayerLifecycleManager.cpp",
- "FrontEnd/RequestedLayerState.cpp",
- "FrontEnd/TransactionHandler.cpp",
"FpsReporter.cpp",
+ "FrameTimeline/FrameTimeline.cpp",
"FrameTracer/FrameTracer.cpp",
"FrameTracker.cpp",
+ "FrontEnd/LayerCreationArgs.cpp",
+ "FrontEnd/LayerHandle.cpp",
+ "FrontEnd/LayerHierarchy.cpp",
+ "FrontEnd/LayerLifecycleManager.cpp",
+ "FrontEnd/LayerSnapshot.cpp",
+ "FrontEnd/LayerSnapshotBuilder.cpp",
+ "FrontEnd/RequestedLayerState.cpp",
+ "FrontEnd/TransactionHandler.cpp",
"HdrLayerInfoReporter.cpp",
"HdrSdrRatioOverlay.cpp",
"Jank/JankTracker.cpp",
- "WindowInfosListenerInvoker.cpp",
"Layer.cpp",
"LayerFE.cpp",
"LayerProtoHelper.cpp",
- "LayerRenderArea.cpp",
"LayerVector.cpp",
"NativeWindowSurface.cpp",
"RefreshRateOverlay.cpp",
"RegionSamplingThread.cpp",
- "RenderArea.cpp",
"Scheduler/EventThread.cpp",
"Scheduler/FrameRateOverrideMappings.cpp",
- "Scheduler/OneShotTimer.cpp",
"Scheduler/LayerHistory.cpp",
"Scheduler/LayerInfo.cpp",
"Scheduler/MessageQueue.cpp",
+ "Scheduler/OneShotTimer.cpp",
"Scheduler/RefreshRateSelector.cpp",
"Scheduler/Scheduler.cpp",
"Scheduler/SmallAreaDetectionAllowMappings.cpp",
@@ -218,19 +249,20 @@
"Tracing/LayerDataSource.cpp",
"Tracing/LayerTracing.cpp",
"Tracing/TransactionDataSource.cpp",
- "Tracing/TransactionTracing.cpp",
"Tracing/TransactionProtoParser.cpp",
+ "Tracing/TransactionTracing.cpp",
"Tracing/tools/LayerTraceGenerator.cpp",
"TransactionCallbackInvoker.cpp",
"TunnelModeEnabledReporter.cpp",
+ "WindowInfosListenerInvoker.cpp",
],
}
cc_defaults {
name: "libsurfaceflinger_binary",
defaults: [
- "surfaceflinger_defaults",
"libsurfaceflinger_production_defaults",
+ "surfaceflinger_defaults",
],
cflags: [
"-DLOG_TAG=\"SurfaceFlinger\"",
@@ -250,7 +282,6 @@
],
static_libs: [
"android.frameworks.displayservice@1.0",
- "libc++fs",
"libdisplayservicehidl",
"libserviceutils",
],
@@ -297,9 +328,9 @@
"android.hardware.configstore@1.1",
"android.hardware.graphics.common@1.2",
"libhidlbase",
+ "liblog",
"libui",
"libutils",
- "liblog",
],
static_libs: [
"libSurfaceFlingerProperties",
@@ -313,3 +344,37 @@
"libSurfaceFlingerProperties",
],
}
+
+cc_library {
+ name: "libstatslog_surfaceflinger",
+ generated_sources: ["statslog_surfaceflinger.cpp"],
+ generated_headers: ["statslog_surfaceflinger.h"],
+ export_generated_headers: ["statslog_surfaceflinger.h"],
+ shared_libs: [
+ "android.os.statsbootstrap_aidl-cpp",
+ "libbinder",
+ "libstatsbootstrap",
+ "libutils",
+ ],
+}
+
+genrule {
+ name: "statslog_surfaceflinger.h",
+ tools: ["stats-log-api-gen"],
+ cmd: "$(location stats-log-api-gen) --header $(genDir)/statslog_surfaceflinger.h" +
+ " --module surfaceflinger --namespace android,surfaceflinger,stats --bootstrap",
+ out: [
+ "statslog_surfaceflinger.h",
+ ],
+}
+
+genrule {
+ name: "statslog_surfaceflinger.cpp",
+ tools: ["stats-log-api-gen"],
+ cmd: "$(location stats-log-api-gen) --cpp $(genDir)/statslog_surfaceflinger.cpp" +
+ " --module surfaceflinger --namespace android,surfaceflinger,stats" +
+ " --importHeader statslog_surfaceflinger.h --bootstrap",
+ out: [
+ "statslog_surfaceflinger.cpp",
+ ],
+}
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index abeb2a9..6088e25 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -53,7 +53,6 @@
const sp<IBinder>& parent, const gui::LayerMetadata& metadata,
gui::CreateSurfaceResult* outResult) {
// We rely on createLayer to check permissions.
- sp<IBinder> handle;
LayerCreationArgs args(mFlinger.get(), sp<Client>::fromExisting(this), name.c_str(),
static_cast<uint32_t>(flags), std::move(metadata));
args.parentHandle = parent;
@@ -101,7 +100,6 @@
binder::Status Client::mirrorSurface(const sp<IBinder>& mirrorFromHandle,
gui::CreateSurfaceResult* outResult) {
- sp<IBinder> handle;
LayerCreationArgs args(mFlinger.get(), sp<Client>::fromExisting(this), "MirrorRoot",
0 /* flags */, gui::LayerMetadata());
status_t status = mFlinger->mirrorLayer(args, mirrorFromHandle, *outResult);
@@ -109,12 +107,11 @@
}
binder::Status Client::mirrorDisplay(int64_t displayId, gui::CreateSurfaceResult* outResult) {
- sp<IBinder> handle;
LayerCreationArgs args(mFlinger.get(), sp<Client>::fromExisting(this),
"MirrorRoot-" + std::to_string(displayId), 0 /* flags */,
gui::LayerMetadata());
- std::optional<DisplayId> id = DisplayId::fromValue(static_cast<uint64_t>(displayId));
- status_t status = mFlinger->mirrorDisplay(*id, args, *outResult);
+ const DisplayId id = DisplayId::fromValue(static_cast<uint64_t>(displayId));
+ status_t status = mFlinger->mirrorDisplay(id, args, *outResult);
return binderStatusFromStatusT(status);
}
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index b4ac9ba..2d0f874 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -13,11 +13,11 @@
defaults: [
"aconfig_lib_cc_static_link.defaults",
"android.hardware.graphics.composer3-ndk_shared",
- "android.hardware.power-ndk_shared",
"librenderengine_deps",
"libtimestats_deps",
"surfaceflinger_defaults",
"libsurfaceflinger_proto_deps",
+ "poweradvisor_deps",
],
cflags: [
"-DLOG_TAG=\"CompositionEngine\"",
@@ -42,6 +42,7 @@
"libutils",
],
static_libs: [
+ "libguiflags",
"libmath",
"librenderengine",
"libtimestats",
@@ -49,9 +50,7 @@
"libaidlcommonsupport",
"libprocessgroup",
"libprocessgroup_util",
- "libcgrouprc",
"libjsoncpp",
- "libcgrouprc_format",
],
header_libs: [
"android.hardware.graphics.composer@2.1-command-buffer",
@@ -59,7 +58,7 @@
"android.hardware.graphics.composer@2.3-command-buffer",
"android.hardware.graphics.composer@2.4-command-buffer",
"android.hardware.graphics.composer3-command-buffer",
- "libsurfaceflinger_headers",
+ "libsurfaceflinger_backend_headers",
],
}
@@ -141,6 +140,8 @@
],
srcs: [
":libcompositionengine_sources",
+ ":libsurfaceflinger_backend_mock_sources",
+ ":libsurfaceflinger_backend_sources",
"tests/planner/CachedSetTest.cpp",
"tests/planner/FlattenerTest.cpp",
"tests/planner/LayerStateTest.cpp",
@@ -151,14 +152,14 @@
"tests/DisplayTest.cpp",
"tests/HwcAsyncWorkerTest.cpp",
"tests/HwcBufferCacheTest.cpp",
- "tests/MockHWC2.cpp",
- "tests/MockHWComposer.cpp",
- "tests/MockPowerAdvisor.cpp",
"tests/OutputLayerTest.cpp",
"tests/OutputTest.cpp",
"tests/ProjectionSpaceTest.cpp",
"tests/RenderSurfaceTest.cpp",
],
+ header_libs: [
+ "libsurfaceflinger_backend_mock_headers",
+ ],
static_libs: [
"libcompositionengine_mocks",
"libgui_mocks",
@@ -167,6 +168,7 @@
"libgtest",
],
shared_libs: [
+ "libbinder_ndk",
// For some reason, libvulkan isn't picked up from librenderengine
// Probably ASAN related?
"libvulkan",
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
index e32cc02..fd58191 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
@@ -53,7 +53,7 @@
createLayerFECompositionState() = 0;
virtual HWComposer& getHwComposer() const = 0;
- virtual void setHwComposer(std::unique_ptr<HWComposer>) = 0;
+ virtual void setHwComposer(HWComposer*) = 0;
virtual renderengine::RenderEngine& getRenderEngine() const = 0;
virtual void setRenderEngine(renderengine::RenderEngine*) = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
index 6e60839..252adaa 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
@@ -24,7 +24,7 @@
#include <ui/Size.h>
#include <ui/StaticDisplayInfo.h>
-#include "DisplayHardware/PowerAdvisor.h"
+#include "PowerAdvisor/PowerAdvisor.h"
namespace android::compositionengine {
@@ -46,9 +46,15 @@
// content.
bool isProtected = false;
+ // True if this display has picture processing hardware and pipelines.
+ bool hasPictureProcessing = false;
+
+ // The number of layer-specific picture-processing pipelines.
+ int32_t maxLayerPictureProfiles = 0;
+
// Optional pointer to the power advisor interface, if one is needed for
// this display.
- Hwc2::PowerAdvisor* powerAdvisor = nullptr;
+ adpf::PowerAdvisor* powerAdvisor = nullptr;
// Debugging. Human readable name for the display.
std::string name;
@@ -82,7 +88,17 @@
return *this;
}
- DisplayCreationArgsBuilder& setPowerAdvisor(Hwc2::PowerAdvisor* powerAdvisor) {
+ DisplayCreationArgsBuilder& setHasPictureProcessing(bool hasPictureProcessing) {
+ mArgs.hasPictureProcessing = hasPictureProcessing;
+ return *this;
+ }
+
+ DisplayCreationArgsBuilder& setMaxLayerPictureProfiles(int32_t maxLayerPictureProfiles) {
+ mArgs.maxLayerPictureProfiles = maxLayerPictureProfiles;
+ return *this;
+ }
+
+ DisplayCreationArgsBuilder& setPowerAdvisor(adpf::PowerAdvisor* powerAdvisor) {
mArgs.powerAdvisor = powerAdvisor;
return *this;
}
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
index 4e080b3..780758e 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
@@ -19,6 +19,7 @@
#include <optional>
#include <ostream>
#include <unordered_set>
+#include "aidl/android/hardware/graphics/composer3/Composition.h"
#include "ui/LayerStack.h"
// TODO(b/129481165): remove the #pragma below and fix conversion issues
@@ -121,6 +122,8 @@
// True if layers with 170M dataspace should be overridden to sRGB.
const bool treat170mAsSrgb;
+
+ std::shared_ptr<gui::DisplayLuts> luts;
};
// A superset of LayerSettings required by RenderEngine to compose a layer
@@ -131,6 +134,9 @@
// Currently latched frame number, 0 if invalid.
uint64_t frameNumber = 0;
+
+ // layer serial number, -1 if invalid.
+ int32_t sequence = -1;
};
// Describes the states of the release fence. Checking the states allows checks
@@ -148,9 +154,6 @@
virtual std::optional<LayerSettings> prepareClientComposition(
ClientCompositionTargetSettings&) const = 0;
- // Called after the layer is displayed to update the presentation fence
- virtual void onLayerDisplayed(ftl::SharedFuture<FenceResult>, ui::LayerStack layerStack) = 0;
-
// Initializes a promise for a buffer release fence and provides the future for that
// fence. This should only be called when a promise has not yet been created, or
// after the previous promise has already been fulfilled. Attempting to call this
@@ -164,6 +167,9 @@
// Checks if the buffer's release fence has been set
virtual LayerFE::ReleaseFencePromiseStatus getReleaseFencePromiseStatus() = 0;
+ // Indicates that the picture profile request was applied to this layer.
+ virtual void onPictureProfileCommitted() = 0;
+
// Gets some kind of identifier for the layer for debug purposes.
virtual const char* getDebugName() const = 0;
@@ -173,6 +179,28 @@
// Whether the layer should be rendered with rounded corners.
virtual bool hasRoundedCorners() const = 0;
virtual void setWasClientComposed(const sp<Fence>&) {}
+
+ // These fields are all copied from the last written HWC state.
+ // This state is only used for debugging purposes.
+ struct HwcLayerDebugState {
+ aidl::android::hardware::graphics::composer3::Composition lastCompositionType =
+ aidl::android::hardware::graphics::composer3::Composition::INVALID;
+ // Corresponds to passing an alpha of 0 to HWC2::Layer::setPlaneAlpha.
+ bool wasSkipped = false;
+
+ // Indicates whether the compositionengine::OutputLayer had properties overwritten.
+ // Not directly passed to HWC.
+ bool wasOverridden = false;
+
+ // Corresponds to the GraphicBuffer ID of the buffer passed to HWC2::Layer::setBuffer.
+ // This buffer corresponds to a CachedSet that the LayerFE was flattened to.
+ uint64_t overrideBufferId = 0;
+ };
+
+ // Used for debugging purposes, e.g. perfetto tracing, dumpsys.
+ virtual void setLastHwcState(const LayerFE::HwcLayerDebugState &hwcState) = 0;
+ virtual const HwcLayerDebugState &getLastHwcState() const = 0;
+
virtual const gui::LayerMetadata* getMetadata() const = 0;
virtual const gui::LayerMetadata* getRelativeMetadata() const = 0;
};
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
index 14a8fd6..fb8fed0 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
@@ -19,11 +19,13 @@
#include <cstdint>
#include <android/gui/CachingHint.h>
+#include <gui/DisplayLuts.h>
#include <gui/HdrMetadata.h>
#include <math/mat4.h>
#include <ui/BlurRegion.h>
#include <ui/FloatRect.h>
#include <ui/LayerStack.h>
+#include <ui/PictureProfileHandle.h>
#include <ui/Rect.h>
#include <ui/Region.h>
#include <ui/ShadowSettings.h>
@@ -218,7 +220,18 @@
float currentHdrSdrRatio = 1.f;
float desiredHdrSdrRatio = 1.f;
+ // A picture profile handle refers to a PictureProfile configured on the display, which is a
+ // set of parameters that configures the picture processing hardware that is used to enhance
+ // the quality of buffer contents.
+ PictureProfileHandle pictureProfileHandle{PictureProfileHandle::NONE};
+
+ // A layer's priority in terms of limited picture processing pipeline utilization.
+ int64_t pictureProfilePriority;
+
gui::CachingHint cachingHint = gui::CachingHint::Enabled;
+
+ std::shared_ptr<gui::DisplayLuts> luts;
+
virtual ~LayerFECompositionState();
// Debugging
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index 191d475..bda7856 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -16,6 +16,8 @@
#pragma once
+#include <ftl/future.h>
+#include <ftl/optional.h>
#include <cstdint>
#include <iterator>
#include <optional>
@@ -26,18 +28,18 @@
#include <vector>
#include <compositionengine/LayerFE.h>
-#include <ftl/future.h>
#include <renderengine/LayerSettings.h>
+#include <ui/DisplayIdentification.h>
#include <ui/Fence.h>
#include <ui/FenceTime.h>
#include <ui/GraphicTypes.h>
#include <ui/LayerStack.h>
+#include <ui/PictureProfileHandle.h>
#include <ui/Region.h>
#include <ui/Transform.h>
#include <utils/StrongPointer.h>
#include <utils/Vector.h>
-#include <ui/DisplayIdentification.h>
#include "DisplayHardware/HWComposer.h"
namespace android {
@@ -167,7 +169,7 @@
virtual bool isValid() const = 0;
// Returns the DisplayId the output represents, if it has one
- virtual std::optional<DisplayId> getDisplayId() const = 0;
+ virtual ftl::Optional<DisplayId> getDisplayId() const = 0;
// Enables (or disables) composition on this output
virtual void setCompositionEnabled(bool) = 0;
@@ -329,6 +331,11 @@
virtual bool isPowerHintSessionGpuReportingEnabled() = 0;
virtual void cacheClientCompositionRequests(uint32_t cacheSize) = 0;
virtual bool canPredictCompositionStrategy(const CompositionRefreshArgs&) = 0;
+ virtual const aidl::android::hardware::graphics::composer3::OverlayProperties*
+ getOverlaySupport() = 0;
+ virtual bool hasPictureProcessing() const = 0;
+ virtual int32_t getMaxLayerPictureProfiles() const = 0;
+ virtual void applyPictureProfile() = 0;
};
} // namespace compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
index dcfe21a..c0243b8 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
@@ -21,6 +21,7 @@
#include <string>
#include <vector>
+#include <ui/PictureProfileHandle.h>
#include <ui/Transform.h>
#include <utils/StrongPointer.h>
@@ -86,6 +87,16 @@
// longer cares about.
virtual void uncacheBuffers(const std::vector<uint64_t>& bufferIdsToUncache) = 0;
+ // Get the relative priority of the layer's picture profile with respect to the importance of
+ // the visual content to the user experience. Lower is higher priority.
+ virtual int64_t getPictureProfilePriority() const = 0;
+
+ // The picture profile handle for the layer.
+ virtual const PictureProfileHandle& getPictureProfileHandle() const = 0;
+
+ // Commit the picture profile to the composition state.
+ virtual void commitPictureProfileToCompositionState() = 0;
+
// Recalculates the state of the output layer from the output-independent
// layer. If includeGeometry is false, the geometry state can be skipped.
// internalDisplayRotationFlags must be set to the rotation flags for the
@@ -93,7 +104,10 @@
// transform, if needed.
virtual void updateCompositionState(
bool includeGeometry, bool forceClientComposition,
- ui::Transform::RotationFlags internalDisplayRotationFlags) = 0;
+ ui::Transform::RotationFlags internalDisplayRotationFlags,
+ const std::optional<std::vector<
+ std::optional<aidl::android::hardware::graphics::composer3::LutProperties>>>
+ properties) = 0;
// Writes the geometry state to the HWC, or does nothing if this layer does
// not use the HWC. If includeGeometry is false, the geometry state can be
@@ -104,7 +118,8 @@
// isPeekingThrough specifies whether this layer will be shown through a
// hole punch in a layer above it.
virtual void writeStateToHWC(bool includeGeometry, bool skipLayer, uint32_t z,
- bool zIsOverridden, bool isPeekingThrough) = 0;
+ bool zIsOverridden, bool isPeekingThrough,
+ bool isLutSupported) = 0;
// Updates the cursor position with the HWC
virtual void writeCursorPositionToHWC() const = 0;
@@ -129,8 +144,10 @@
virtual void applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) = 0;
// Applies a HWC device layer lut
- virtual void applyDeviceLayerLut(aidl::android::hardware::graphics::composer3::LutProperties,
- ndk::ScopedFileDescriptor) = 0;
+ virtual void applyDeviceLayerLut(
+ ::android::base::unique_fd,
+ std::vector<std::pair<
+ int, aidl::android::hardware::graphics::composer3::LutProperties>>) = 0;
// Returns true if the composition settings scale pixels
virtual bool needsFiltering() const = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
index 45208dd..2992b6d 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
@@ -31,7 +31,7 @@
override;
HWComposer& getHwComposer() const override;
- void setHwComposer(std::unique_ptr<HWComposer>) override;
+ void setHwComposer(HWComposer*) override;
renderengine::RenderEngine& getRenderEngine() const override;
void setRenderEngine(renderengine::RenderEngine*) override;
@@ -59,7 +59,7 @@
void setNeedsAnotherUpdateForTest(bool);
private:
- std::unique_ptr<HWComposer> mHwComposer;
+ HWComposer* mHwComposer;
renderengine::RenderEngine* mRenderEngine;
std::shared_ptr<TimeStats> mTimeStats;
bool mNeedsAnotherUpdate = false;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
index a39abb4..5519aaf 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
@@ -30,7 +30,7 @@
#include <ui/DisplayIdentification.h>
#include "DisplayHardware/HWComposer.h"
-#include "DisplayHardware/PowerAdvisor.h"
+#include "PowerAdvisor/PowerAdvisor.h"
namespace android::compositionengine {
@@ -45,7 +45,7 @@
virtual ~Display();
// compositionengine::Output overrides
- std::optional<DisplayId> getDisplayId() const override;
+ ftl::Optional<DisplayId> getDisplayId() const override;
bool isValid() const override;
void dump(std::string&) const override;
using compositionengine::impl::Output::setReleasedLayers;
@@ -100,9 +100,16 @@
void setHintSessionGpuStart(TimePoint startTime) override;
void setHintSessionGpuFence(std::unique_ptr<FenceTime>&& gpuFence) override;
void setHintSessionRequiresRenderEngine(bool requiresRenderEngine) override;
+ const aidl::android::hardware::graphics::composer3::OverlayProperties* getOverlaySupport()
+ override;
+ bool hasPictureProcessing() const override;
+ int32_t getMaxLayerPictureProfiles() const override;
+
DisplayId mId;
bool mIsDisconnected = false;
- Hwc2::PowerAdvisor* mPowerAdvisor = nullptr;
+ adpf::PowerAdvisor* mPowerAdvisor = nullptr;
+ bool mHasPictureProcessing = false;
+ int32_t mMaxLayerPictureProfiles = 0;
};
// This template factory function standardizes the implementation details of the
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index 9990a74..0ccdd22 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -16,6 +16,11 @@
#pragma once
+#include <ftl/optional.h>
+#include <memory>
+#include <utility>
+#include <vector>
+
#include <compositionengine/CompositionEngine.h>
#include <compositionengine/LayerFECompositionState.h>
#include <compositionengine/Output.h>
@@ -28,10 +33,6 @@
#include <renderengine/DisplaySettings.h>
#include <renderengine/LayerSettings.h>
-#include <memory>
-#include <utility>
-#include <vector>
-
namespace android::compositionengine::impl {
// The implementation class contains the common implementation, but does not
@@ -43,7 +44,7 @@
// compositionengine::Output overrides
bool isValid() const override;
- std::optional<DisplayId> getDisplayId() const override;
+ ftl::Optional<DisplayId> getDisplayId() const override;
void setCompositionEnabled(bool) override;
void setLayerCachingEnabled(bool) override;
void setLayerCachingTexturePoolEnabled(bool) override;
@@ -84,13 +85,14 @@
bool supportsOffloadPresent() const override { return false; }
void offloadPresentNextFrame() override;
- void uncacheBuffers(const std::vector<uint64_t>& bufferIdsToUncache) override;
void rebuildLayerStacks(const CompositionRefreshArgs&, LayerFESet&) override;
void collectVisibleLayers(const CompositionRefreshArgs&,
compositionengine::Output::CoverageState&) override;
void ensureOutputLayerIfVisible(sp<compositionengine::LayerFE>&,
compositionengine::Output::CoverageState&) override;
void setReleasedLayers(const compositionengine::CompositionRefreshArgs&) override;
+ void uncacheBuffers(const std::vector<uint64_t>& bufferIdsToUncache) override;
+ void commitPictureProfilesToCompositionState();
void updateCompositionState(const compositionengine::CompositionRefreshArgs&) override;
void planComposition() override;
@@ -151,6 +153,9 @@
void setHintSessionRequiresRenderEngine(bool requiresRenderEngine) override;
bool isPowerHintSessionEnabled() override;
bool isPowerHintSessionGpuReportingEnabled() override;
+ bool hasPictureProcessing() const override;
+ int32_t getMaxLayerPictureProfiles() const override;
+ void applyPictureProfile() override;
void dumpBase(std::string&) const;
// Implemented by the final implementation for the final state it uses.
@@ -164,6 +169,8 @@
bool mustRecompose() const;
const std::string& getNamePlusId() const { return mNamePlusId; }
+ const aidl::android::hardware::graphics::composer3::OverlayProperties* getOverlaySupport()
+ override;
private:
void dirtyEntireOutput();
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
index f8ffde1..c76b344 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
@@ -35,6 +35,7 @@
#include <compositionengine/CompositionRefreshArgs.h>
#include <compositionengine/ProjectionSpace.h>
#include <ui/LayerStack.h>
+#include <ui/PictureProfileHandle.h>
#include <ui/Rect.h>
#include <ui/Region.h>
#include <ui/Transform.h>
@@ -170,6 +171,8 @@
ICEPowerCallback* powerCallback = nullptr;
+ PictureProfileHandle pictureProfileHandle;
+
// Debugging
void dump(std::string& result) const;
};
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
index 354a441..dea3290 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
@@ -25,12 +25,15 @@
#include <compositionengine/LayerFE.h>
#include <compositionengine/OutputLayer.h>
#include <ui/FloatRect.h>
+#include <ui/PictureProfileHandle.h>
#include <ui/Rect.h>
#include <ui/DisplayIdentification.h>
#include <aidl/android/hardware/graphics/composer3/Composition.h>
+using aidl::android::hardware::graphics::composer3::LutProperties;
+
namespace android::compositionengine {
struct LayerFECompositionState;
@@ -46,11 +49,16 @@
void setHwcLayer(std::shared_ptr<HWC2::Layer>) override;
void uncacheBuffers(const std::vector<uint64_t>& bufferIdsToUncache) override;
+ int64_t getPictureProfilePriority() const override;
+ const PictureProfileHandle& getPictureProfileHandle() const override;
+ void commitPictureProfileToCompositionState() override;
void updateCompositionState(bool includeGeometry, bool forceClientComposition,
- ui::Transform::RotationFlags) override;
+ ui::Transform::RotationFlags,
+ const std::optional<std::vector<std::optional<LutProperties>>>
+ properties = std::nullopt) override;
void writeStateToHWC(bool includeGeometry, bool skipLayer, uint32_t z, bool zIsOverridden,
- bool isPeekingThrough) override;
+ bool isPeekingThrough, bool hasLutsProperties) override;
void writeCursorPositionToHWC() const override;
HWC2::Layer* getHwcLayer() const override;
@@ -60,8 +68,8 @@
aidl::android::hardware::graphics::composer3::Composition) override;
void prepareForDeviceLayerRequests() override;
void applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) override;
- void applyDeviceLayerLut(aidl::android::hardware::graphics::composer3::LutProperties,
- ndk::ScopedFileDescriptor) override;
+ void applyDeviceLayerLut(::android::base::unique_fd,
+ std::vector<std::pair<int, LutProperties>>) override;
bool needsFiltering() const override;
std::optional<LayerFE::LayerSettings> getOverrideCompositionSettings() const override;
@@ -92,10 +100,13 @@
void writeCompositionTypeToHWC(HWC2::Layer*,
aidl::android::hardware::graphics::composer3::Composition,
bool isPeekingThrough, bool skipLayer);
+ void writeLutToHWC(HWC2::Layer*, const LayerFECompositionState&);
void detectDisallowedCompositionTypeChange(
aidl::android::hardware::graphics::composer3::Composition from,
aidl::android::hardware::graphics::composer3::Composition to) const;
- bool isClientCompositionForced(bool isPeekingThrough) const;
+ bool isClientCompositionForced(bool isPeekingThrough, bool isCached) const;
+ void updateLuts(const LayerFECompositionState&,
+ const std::optional<std::vector<std::optional<LutProperties>>>& properties);
};
// This template factory function standardizes the implementation details of the
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
index 6c419da..c558739 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
@@ -18,9 +18,11 @@
#include <compositionengine/ProjectionSpace.h>
#include <compositionengine/impl/HwcBufferCache.h>
+#include <gui/DisplayLuts.h>
#include <renderengine/ExternalTexture.h>
#include <ui/FloatRect.h>
#include <ui/GraphicTypes.h>
+#include <ui/PictureProfileHandle.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -100,6 +102,9 @@
// order to save power.
Region outputSpaceBlockingRegionHint;
+ // The picture profile for this layer.
+ PictureProfileHandle pictureProfileHandle;
+
// Overrides the buffer, acquire fence, and display frame stored in LayerFECompositionState
struct {
std::shared_ptr<renderengine::ExternalTexture> buffer = nullptr;
@@ -151,6 +156,9 @@
// True when this layer was skipped as part of SF-side layer caching.
bool layerSkipped = false;
+
+ // lut information
+ std::shared_ptr<gui::DisplayLuts> luts;
};
// The HWC state is optional, and is only set up if there is any potential
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
index a1b7282..bb1a222 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
@@ -37,7 +37,7 @@
std::unique_ptr<compositionengine::LayerFECompositionState>());
MOCK_CONST_METHOD0(getHwComposer, HWComposer&());
- MOCK_METHOD1(setHwComposer, void(std::unique_ptr<HWComposer>));
+ MOCK_METHOD1(setHwComposer, void(HWComposer*));
MOCK_CONST_METHOD0(getRenderEngine, renderengine::RenderEngine&());
MOCK_METHOD1(setRenderEngine, void(renderengine::RenderEngine*));
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
index 05a5d38..d2a5a20 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
@@ -50,9 +50,6 @@
std::optional<compositionengine::LayerFE::LayerSettings>(
compositionengine::LayerFE::ClientCompositionTargetSettings&));
- MOCK_METHOD(void, onLayerDisplayed, (ftl::SharedFuture<FenceResult>, ui::LayerStack),
- (override));
-
MOCK_METHOD0(createReleaseFenceFuture, ftl::Future<FenceResult>());
MOCK_METHOD1(setReleaseFence, void(const FenceResult&));
MOCK_METHOD0(getReleaseFencePromiseStatus, LayerFE::ReleaseFencePromiseStatus());
@@ -61,6 +58,11 @@
MOCK_CONST_METHOD0(hasRoundedCorners, bool());
MOCK_CONST_METHOD0(getMetadata, gui::LayerMetadata*());
MOCK_CONST_METHOD0(getRelativeMetadata, gui::LayerMetadata*());
+ MOCK_METHOD0(onPictureProfileCommitted, void());
+ MOCK_METHOD(void, setLastHwcState,
+ (const HwcLayerDebugState&), (override));
+ MOCK_METHOD(const HwcLayerDebugState&, getLastHwcState,
+ (), (const, override));
};
} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index d5bf2b5..f2c265a 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -34,7 +34,7 @@
virtual ~Output();
MOCK_CONST_METHOD0(isValid, bool());
- MOCK_CONST_METHOD0(getDisplayId, std::optional<DisplayId>());
+ MOCK_CONST_METHOD0(getDisplayId, ftl::Optional<DisplayId>());
MOCK_METHOD1(setCompositionEnabled, void(bool));
MOCK_METHOD1(setLayerCachingEnabled, void(bool));
@@ -140,6 +140,11 @@
MOCK_METHOD(void, setHintSessionRequiresRenderEngine, (bool requiresRenderEngine));
MOCK_METHOD(bool, isPowerHintSessionEnabled, ());
MOCK_METHOD(bool, isPowerHintSessionGpuReportingEnabled, ());
+ MOCK_METHOD((const aidl::android::hardware::graphics::composer3::OverlayProperties*),
+ getOverlaySupport, ());
+ MOCK_METHOD(bool, hasPictureProcessing, (), (const));
+ MOCK_METHOD(int32_t, getMaxLayerPictureProfiles, (), (const));
+ MOCK_METHOD(void, applyPictureProfile, ());
};
} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
index 48c2f9c..be36db6 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
@@ -43,8 +43,11 @@
MOCK_CONST_METHOD0(getState, const impl::OutputLayerCompositionState&());
MOCK_METHOD0(editState, impl::OutputLayerCompositionState&());
- MOCK_METHOD3(updateCompositionState, void(bool, bool, ui::Transform::RotationFlags));
- MOCK_METHOD5(writeStateToHWC, void(bool, bool, uint32_t, bool, bool));
+ MOCK_METHOD(void, updateCompositionState,
+ (bool, bool, ui::Transform::RotationFlags,
+ (const std::optional<std::vector<std::optional<
+ aidl::android::hardware::graphics::composer3::LutProperties>>>)));
+ MOCK_METHOD(void, writeStateToHWC, (bool, bool, uint32_t, bool, bool, bool));
MOCK_CONST_METHOD0(writeCursorPositionToHWC, void());
MOCK_CONST_METHOD0(getHwcLayer, HWC2::Layer*());
@@ -57,9 +60,12 @@
MOCK_CONST_METHOD0(needsFiltering, bool());
MOCK_CONST_METHOD0(getOverrideCompositionSettings, std::optional<LayerFE::LayerSettings>());
MOCK_METHOD(void, applyDeviceLayerLut,
- (aidl::android::hardware::graphics::composer3::LutProperties,
- ndk::ScopedFileDescriptor));
-
+ (::android::base::unique_fd,
+ (std::vector<std::pair<
+ int, aidl::android::hardware::graphics::composer3::LutProperties>>)));
+ MOCK_METHOD(int64_t, getPictureProfilePriority, (), (const));
+ MOCK_METHOD(const PictureProfileHandle&, getPictureProfileHandle, (), (const));
+ MOCK_METHOD(void, commitPictureProfileToCompositionState, ());
MOCK_CONST_METHOD1(dump, void(std::string&));
};
diff --git a/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp b/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp
index d9018bc..dc84195 100644
--- a/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp
@@ -38,7 +38,8 @@
lhs.disableBlending == rhs.disableBlending && lhs.shadow == rhs.shadow &&
lhs.backgroundBlurRadius == rhs.backgroundBlurRadius &&
lhs.stretchEffect == rhs.stretchEffect &&
- lhs.edgeExtensionEffect == rhs.edgeExtensionEffect;
+ lhs.edgeExtensionEffect == rhs.edgeExtensionEffect &&
+ lhs.whitePointNits == rhs.whitePointNits;
}
inline bool equalIgnoringBuffer(const renderengine::Buffer& lhs, const renderengine::Buffer& rhs) {
diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
index 5c5d0cd..989f8e3 100644
--- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
@@ -58,11 +58,11 @@
}
HWComposer& CompositionEngine::getHwComposer() const {
- return *mHwComposer.get();
+ return *mHwComposer;
}
-void CompositionEngine::setHwComposer(std::unique_ptr<HWComposer> hwComposer) {
- mHwComposer = std::move(hwComposer);
+void CompositionEngine::setHwComposer(HWComposer* hwComposer) {
+ mHwComposer = hwComposer;
}
renderengine::RenderEngine& CompositionEngine::getRenderEngine() const {
@@ -198,25 +198,23 @@
// these buffers and fire a NO_FENCE to release it. This ensures that all
// promises for buffer releases are fulfilled at the end of composition.
void CompositionEngine::postComposition(CompositionRefreshArgs& args) {
- if (FlagManager::getInstance().ce_fence_promise()) {
- SFTRACE_CALL();
- ALOGV(__FUNCTION__);
+ SFTRACE_CALL();
+ ALOGV(__FUNCTION__);
- for (auto& layerFE : args.layers) {
- if (layerFE->getReleaseFencePromiseStatus() ==
- LayerFE::ReleaseFencePromiseStatus::INITIALIZED) {
- layerFE->setReleaseFence(Fence::NO_FENCE);
- }
+ for (auto& layerFE : args.layers) {
+ if (layerFE->getReleaseFencePromiseStatus() ==
+ LayerFE::ReleaseFencePromiseStatus::INITIALIZED) {
+ layerFE->setReleaseFence(Fence::NO_FENCE);
}
+ }
- // List of layersWithQueuedFrames does not necessarily overlap with
- // list of layers, so those layersWithQueuedFrames also need any
- // unfulfilled promises to be resolved for completeness.
- for (auto& layerFE : args.layersWithQueuedFrames) {
- if (layerFE->getReleaseFencePromiseStatus() ==
- LayerFE::ReleaseFencePromiseStatus::INITIALIZED) {
- layerFE->setReleaseFence(Fence::NO_FENCE);
- }
+ // List of layersWithQueuedFrames does not necessarily overlap with
+ // list of layers, so those layersWithQueuedFrames also need any
+ // unfulfilled promises to be resolved for completeness.
+ for (auto& layerFE : args.layersWithQueuedFrames) {
+ if (layerFE->getReleaseFencePromiseStatus() ==
+ LayerFE::ReleaseFencePromiseStatus::INITIALIZED) {
+ layerFE->setReleaseFence(Fence::NO_FENCE);
}
}
}
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index b0164b7..8364f4e 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -36,7 +36,7 @@
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion"
-#include "DisplayHardware/PowerAdvisor.h"
+#include "PowerAdvisor/PowerAdvisor.h"
using aidl::android::hardware::graphics::composer3::Capability;
using aidl::android::hardware::graphics::composer3::DisplayCapability;
@@ -54,6 +54,8 @@
void Display::setConfiguration(const compositionengine::DisplayCreationArgs& args) {
mId = args.id;
mPowerAdvisor = args.powerAdvisor;
+ mHasPictureProcessing = args.hasPictureProcessing;
+ mMaxLayerPictureProfiles = args.maxLayerPictureProfiles;
editState().isSecure = args.isSecure;
editState().isProtected = args.isProtected;
editState().displaySpace.setBounds(args.pixels);
@@ -80,7 +82,7 @@
return mId.isVirtual();
}
-std::optional<DisplayId> Display::getDisplayId() const {
+ftl::Optional<DisplayId> Display::getDisplayId() const {
return mId;
}
@@ -203,15 +205,16 @@
}
void Display::applyDisplayBrightness(bool applyImmediately) {
- if (const auto displayId = ftl::Optional(getDisplayId()).and_then(PhysicalDisplayId::tryCast);
- displayId && getState().displayBrightness) {
+ if (!getState().displayBrightness) {
+ return;
+ }
+ if (auto displayId = PhysicalDisplayId::tryCast(mId)) {
auto& hwc = getCompositionEngine().getHwComposer();
- const status_t result =
- hwc.setDisplayBrightness(*displayId, *getState().displayBrightness,
- getState().displayBrightnessNits,
- Hwc2::Composer::DisplayBrightnessOptions{
- .applyImmediately = applyImmediately})
- .get();
+ status_t result = hwc.setDisplayBrightness(*displayId, *getState().displayBrightness,
+ getState().displayBrightnessNits,
+ Hwc2::Composer::DisplayBrightnessOptions{
+ .applyImmediately = applyImmediately})
+ .get();
ALOGE_IF(result != NO_ERROR, "setDisplayBrightness failed for %s: %d, (%s)",
getName().c_str(), result, strerror(-result));
}
@@ -288,8 +291,8 @@
}
bool Display::getSkipColorTransform() const {
- const auto& hwc = getCompositionEngine().getHwComposer();
- if (const auto halDisplayId = HalDisplayId::tryCast(mId)) {
+ auto& hwc = getCompositionEngine().getHwComposer();
+ if (auto halDisplayId = HalDisplayId::tryCast(mId)) {
return hwc.hasDisplayCapability(*halDisplayId,
DisplayCapability::SKIP_CLIENT_COLOR_TRANSFORM);
}
@@ -370,8 +373,8 @@
if (auto lutsIt = layerLuts.find(hwcLayer); lutsIt != layerLuts.end()) {
if (auto mapperIt = mapper.find(hwcLayer); mapperIt != mapper.end()) {
- layer->applyDeviceLayerLut(lutsIt->second,
- ndk::ScopedFileDescriptor(mapperIt->second.release()));
+ layer->applyDeviceLayerLut(::android::base::unique_fd(mapperIt->second.release()),
+ lutsIt->second);
}
}
}
@@ -457,6 +460,19 @@
mPowerAdvisor->setRequiresRenderEngine(mId, requiresRenderEngine);
}
+const aidl::android::hardware::graphics::composer3::OverlayProperties*
+Display::getOverlaySupport() {
+ return &getCompositionEngine().getHwComposer().getOverlaySupport();
+}
+
+bool Display::hasPictureProcessing() const {
+ return mHasPictureProcessing;
+}
+
+int32_t Display::getMaxLayerPictureProfiles() const {
+ return mMaxLayerPictureProfiles;
+}
+
void Display::finishFrame(GpuCompositionResult&& result) {
// We only need to actually compose the display if:
// 1) It is being handled by hardware composer, which may need this to
@@ -471,8 +487,8 @@
}
bool Display::supportsOffloadPresent() const {
- if (const auto halDisplayId = HalDisplayId::tryCast(mId)) {
- const auto& hwc = getCompositionEngine().getHwComposer();
+ if (auto halDisplayId = HalDisplayId::tryCast(mId)) {
+ auto& hwc = getCompositionEngine().getHwComposer();
return hwc.hasDisplayCapability(*halDisplayId, DisplayCapability::MULTI_THREADED_PRESENT);
}
diff --git a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp
index 2d10866..348111d 100644
--- a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp
@@ -127,6 +127,9 @@
}
dumpVal(out, "colorTransform", colorTransform);
dumpVal(out, "caching hint", toString(cachingHint));
+ if (pictureProfileHandle) {
+ dumpVal(out, "pictureProfile", toString(pictureProfileHandle));
+ }
out.append("\n");
}
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 2d8f98f..de1d13a 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -32,9 +32,12 @@
#include <compositionengine/impl/planner/Planner.h>
#include <ftl/algorithm.h>
#include <ftl/future.h>
+#include <ftl/optional.h>
#include <scheduler/FrameTargeter.h>
#include <scheduler/Time.h>
+#include <com_android_graphics_libgui_flags.h>
+
#include <optional>
#include <thread>
@@ -111,7 +114,7 @@
mRenderSurface->isValid();
}
-std::optional<DisplayId> Output::getDisplayId() const {
+ftl::Optional<DisplayId> Output::getDisplayId() const {
return {};
}
@@ -433,7 +436,7 @@
ftl::Future<std::monostate> Output::present(
const compositionengine::CompositionRefreshArgs& refreshArgs) {
const auto stringifyExpectedPresentTime = [this, &refreshArgs]() -> std::string {
- return ftl::Optional(getDisplayId())
+ return getDisplayId()
.and_then(PhysicalDisplayId::tryCast)
.and_then([&refreshArgs](PhysicalDisplayId id) {
return refreshArgs.frameTargets.get(id);
@@ -500,15 +503,6 @@
updateHwcAsyncWorker();
}
-void Output::uncacheBuffers(std::vector<uint64_t> const& bufferIdsToUncache) {
- if (bufferIdsToUncache.empty()) {
- return;
- }
- for (auto outputLayer : getOutputLayersOrderedByZ()) {
- outputLayer->uncacheBuffers(bufferIdsToUncache);
- }
-}
-
void Output::rebuildLayerStacks(const compositionengine::CompositionRefreshArgs& refreshArgs,
LayerFESet& layerFESet) {
auto& outputState = editState();
@@ -776,11 +770,11 @@
// The layer is visible. Either reuse the existing outputLayer if we have
// one, or create a new one if we do not.
- auto result = ensureOutputLayer(prevOutputLayerIndex, layerFE);
+ auto outputLayer = ensureOutputLayer(prevOutputLayerIndex, layerFE);
// Store the layer coverage information into the layer state as some of it
// is useful later.
- auto& outputLayerState = result->editState();
+ auto& outputLayerState = outputLayer->editState();
outputLayerState.visibleRegion = visibleRegion;
outputLayerState.visibleNonTransparentRegion = visibleNonTransparentRegion;
outputLayerState.coveredRegion = coveredRegion;
@@ -798,6 +792,54 @@
}
}
+void Output::uncacheBuffers(std::vector<uint64_t> const& bufferIdsToUncache) {
+ if (bufferIdsToUncache.empty()) {
+ return;
+ }
+ for (auto outputLayer : getOutputLayersOrderedByZ()) {
+ outputLayer->uncacheBuffers(bufferIdsToUncache);
+ }
+}
+
+void Output::commitPictureProfilesToCompositionState() {
+ if (!com_android_graphics_libgui_flags_apply_picture_profiles()) {
+ return;
+ }
+ if (!hasPictureProcessing()) {
+ return;
+ }
+ auto compare = [](const ::android::compositionengine::OutputLayer* lhs,
+ const ::android::compositionengine::OutputLayer* rhs) {
+ return lhs->getPictureProfilePriority() < rhs->getPictureProfilePriority();
+ };
+ std::priority_queue<::android::compositionengine::OutputLayer*,
+ std::vector<::android::compositionengine::OutputLayer*>, decltype(compare)>
+ layersWithProfiles;
+ for (auto outputLayer : getOutputLayersOrderedByZ()) {
+ if (outputLayer->getPictureProfileHandle()) {
+ layersWithProfiles.push(outputLayer);
+ }
+ }
+
+ // TODO(b/337330263): Use the default display picture profile from SurfaceFlinger
+ editState().pictureProfileHandle = PictureProfileHandle::NONE;
+
+ // When layer-specific picture processing is supported, apply as many high priority profiles as
+ // possible to the layers, and ignore the low priority layers.
+ if (getMaxLayerPictureProfiles() > 0) {
+ for (int i = 0; i < getMaxLayerPictureProfiles() && !layersWithProfiles.empty();
+ layersWithProfiles.pop(), ++i) {
+ layersWithProfiles.top()->commitPictureProfileToCompositionState();
+ layersWithProfiles.top()->getLayerFE().onPictureProfileCommitted();
+ }
+ // No layer-specific picture processing, so apply the highest priority picture profile to
+ // the entire display.
+ } else if (!layersWithProfiles.empty()) {
+ editState().pictureProfileHandle = layersWithProfiles.top()->getPictureProfileHandle();
+ layersWithProfiles.top()->getLayerFE().onPictureProfileCommitted();
+ }
+}
+
void Output::setReleasedLayers(const compositionengine::CompositionRefreshArgs&) {
// The base class does nothing with this call.
}
@@ -813,16 +855,20 @@
mLayerRequestingBackgroundBlur = findLayerRequestingBackgroundComposition();
bool forceClientComposition = mLayerRequestingBackgroundBlur != nullptr;
+ auto* properties = getOverlaySupport();
+
for (auto* layer : getOutputLayersOrderedByZ()) {
layer->updateCompositionState(refreshArgs.updatingGeometryThisFrame,
refreshArgs.devOptForceClientComposition ||
forceClientComposition,
- refreshArgs.internalDisplayRotationFlags);
+ refreshArgs.internalDisplayRotationFlags,
+ properties ? properties->lutProperties : std::nullopt);
if (mLayerRequestingBackgroundBlur == layer) {
forceClientComposition = false;
}
}
+ commitPictureProfilesToCompositionState();
}
void Output::planComposition() {
@@ -844,17 +890,28 @@
return;
}
- if (auto frameTargetPtrOpt = ftl::Optional(getDisplayId())
+ if (auto frameTargetPtrOpt = getDisplayId()
.and_then(PhysicalDisplayId::tryCast)
.and_then([&refreshArgs](PhysicalDisplayId id) {
return refreshArgs.frameTargets.get(id);
})) {
editState().earliestPresentTime = frameTargetPtrOpt->get()->earliestPresentTime();
editState().expectedPresentTime = frameTargetPtrOpt->get()->expectedPresentTime().ns();
+ const auto debugPresentDelay = frameTargetPtrOpt->get()->debugPresentDelay();
+ if (debugPresentDelay) {
+ SFTRACE_FORMAT_INSTANT("DEBUG delaying presentation by %.2fms",
+ debugPresentDelay->ns() / 1e6f);
+ editState().expectedPresentTime += debugPresentDelay->ns();
+ }
}
editState().frameInterval = refreshArgs.frameInterval;
editState().powerCallback = refreshArgs.powerCallback;
+ applyPictureProfile();
+
+ auto* properties = getOverlaySupport();
+ bool hasLutsProperties = properties && properties->lutProperties.has_value();
+
compositionengine::OutputLayer* peekThroughLayer = nullptr;
sp<GraphicBuffer> previousOverride = nullptr;
bool includeGeometry = refreshArgs.updatingGeometryThisFrame;
@@ -886,7 +943,7 @@
includeGeometry = true;
constexpr bool isPeekingThrough = true;
peekThroughLayer->writeStateToHWC(includeGeometry, false, z++, overrideZ,
- isPeekingThrough);
+ isPeekingThrough, hasLutsProperties);
outputLayerHash ^= android::hashCombine(
reinterpret_cast<uint64_t>(&peekThroughLayer->getLayerFE()),
z, includeGeometry, overrideZ, isPeekingThrough,
@@ -898,7 +955,8 @@
}
constexpr bool isPeekingThrough = false;
- layer->writeStateToHWC(includeGeometry, skipLayer, z++, overrideZ, isPeekingThrough);
+ layer->writeStateToHWC(includeGeometry, skipLayer, z++, overrideZ, isPeekingThrough,
+ hasLutsProperties);
if (!skipLayer) {
outputLayerHash ^= android::hashCombine(
reinterpret_cast<uint64_t>(&layer->getLayerFE()),
@@ -1506,7 +1564,9 @@
.clearContent = !clientComposition,
.blurSetting = blurSetting,
.whitePointNits = layerState.whitePointNits,
- .treat170mAsSrgb = outputState.treat170mAsSrgb};
+ .treat170mAsSrgb = outputState.treat170mAsSrgb,
+ .luts = layer->getState().hwc ? layer->getState().hwc->luts
+ : nullptr};
if (auto clientCompositionSettings =
layerFE.prepareClientComposition(targetSettings)) {
clientCompositionLayers.push_back(std::move(*clientCompositionSettings));
@@ -1610,13 +1670,7 @@
releaseFence =
Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence);
}
- if (FlagManager::getInstance().ce_fence_promise()) {
- layer->getLayerFE().setReleaseFence(releaseFence);
- } else {
- layer->getLayerFE()
- .onLayerDisplayed(ftl::yield<FenceResult>(std::move(releaseFence)).share(),
- outputState.layerFilter.layerStack);
- }
+ layer->getLayerFE().setReleaseFence(releaseFence);
}
// We've got a list of layers needing fences, that are disjoint with
@@ -1624,12 +1678,7 @@
// supply them with the present fence.
for (auto& weakLayer : mReleasedLayers) {
if (const auto layer = weakLayer.promote()) {
- if (FlagManager::getInstance().ce_fence_promise()) {
- layer->setReleaseFence(frame.presentFence);
- } else {
- layer->onLayerDisplayed(ftl::yield<FenceResult>(frame.presentFence).share(),
- outputState.layerFilter.layerStack);
- }
+ layer->setReleaseFence(frame.presentFence);
}
}
@@ -1689,6 +1738,10 @@
editState().treat170mAsSrgb = enable;
}
+const aidl::android::hardware::graphics::composer3::OverlayProperties* Output::getOverlaySupport() {
+ return nullptr;
+}
+
bool Output::canPredictCompositionStrategy(const CompositionRefreshArgs& refreshArgs) {
uint64_t lastOutputLayerHash = getState().lastOutputLayerHash;
uint64_t outputLayerHash = getState().outputLayerHash;
@@ -1767,5 +1820,34 @@
return getState().displayBrightnessNits / getState().sdrWhitePointNits;
}
+bool Output::hasPictureProcessing() const {
+ return false;
+}
+
+int32_t Output::getMaxLayerPictureProfiles() const {
+ return 0;
+}
+
+void Output::applyPictureProfile() {
+ if (!com_android_graphics_libgui_flags_apply_picture_profiles()) {
+ return;
+ }
+
+ // TODO(b/337330263): Move this into the Display class and add a Display unit test.
+ if (!getState().pictureProfileHandle) {
+ return;
+ }
+ if (!getDisplayId()) {
+ return;
+ }
+ if (auto displayId = PhysicalDisplayId::tryCast(*getDisplayId())) {
+ auto& hwc = getCompositionEngine().getHwComposer();
+ const status_t error =
+ hwc.setDisplayPictureProfileHandle(*displayId, getState().pictureProfileHandle);
+ ALOGE_IF(error, "setDisplayPictureProfileHandle failed for %s: %d, (%s)", getName().c_str(),
+ error, strerror(-error));
+ }
+}
+
} // namespace impl
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 2d46dc0..b1bbcac 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
#include <DisplayHardware/Hal.h>
#include <android-base/stringprintf.h>
#include <compositionengine/DisplayColorProfile.h>
@@ -22,11 +23,13 @@
#include <compositionengine/impl/OutputCompositionState.h>
#include <compositionengine/impl/OutputLayer.h>
#include <compositionengine/impl/OutputLayerCompositionState.h>
-#include <cstdint>
-#include "system/graphics-base-v1.0.h"
-#include "ui/FloatRect.h"
-
+#include <ui/FloatRect.h>
#include <ui/HdrRenderTypeUtils.h>
+#include <cstdint>
+#include <limits>
+#include "system/graphics-base-v1.0.h"
+
+#include <com_android_graphics_libgui_flags.h>
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic push
@@ -38,7 +41,7 @@
#pragma clang diagnostic pop // ignored "-Wconversion"
using aidl::android::hardware::graphics::composer3::Composition;
-using aidl::android::hardware::graphics::composer3::LutProperties;
+using aidl::android::hardware::graphics::composer3::Luts;
namespace android::compositionengine {
@@ -285,9 +288,55 @@
return transform.getOrientation();
}
+void OutputLayer::updateLuts(
+ const LayerFECompositionState& layerFEState,
+ const std::optional<std::vector<std::optional<LutProperties>>>& properties) {
+ auto& luts = layerFEState.luts;
+ if (!luts) {
+ return;
+ }
+
+ auto& state = editState();
+
+ if (!properties) {
+ // GPU composition if no Hwc Luts
+ state.forceClientComposition = true;
+ return;
+ }
+
+ std::vector<LutProperties> hwcLutProperties;
+ for (auto& p : *properties) {
+ if (p) {
+ hwcLutProperties.emplace_back(*p);
+ }
+ }
+
+ for (const auto& inputLut : luts->lutProperties) {
+ bool foundInHwcLuts = false;
+ for (const auto& hwcLut : hwcLutProperties) {
+ if (static_cast<int32_t>(hwcLut.dimension) ==
+ static_cast<int32_t>(inputLut.dimension) &&
+ hwcLut.size == inputLut.size &&
+ std::find(hwcLut.samplingKeys.begin(), hwcLut.samplingKeys.end(),
+ static_cast<LutProperties::SamplingKey>(inputLut.samplingKey)) !=
+ hwcLut.samplingKeys.end()) {
+ foundInHwcLuts = true;
+ break;
+ }
+ }
+ // if any lut properties of luts can not be found in hwcLutProperties,
+ // GPU composition instead
+ if (!foundInHwcLuts) {
+ state.forceClientComposition = true;
+ return;
+ }
+ }
+}
+
void OutputLayer::updateCompositionState(
bool includeGeometry, bool forceClientComposition,
- ui::Transform::RotationFlags internalDisplayRotationFlags) {
+ ui::Transform::RotationFlags internalDisplayRotationFlags,
+ const std::optional<std::vector<std::optional<LutProperties>>> properties) {
const auto* layerFEState = getLayerFE().getCompositionState();
if (!layerFEState) {
return;
@@ -320,8 +369,11 @@
layerFEState->buffer->getPixelFormat()))
: std::nullopt;
- auto hdrRenderType =
- getHdrRenderType(outputState.dataspace, pixelFormat, layerFEState->desiredHdrSdrRatio);
+ // prefer querying this from gralloc instead to catch 2094-10 metadata
+ const bool hasHdrMetadata = layerFEState->hdrMetadata.validTypes != 0;
+
+ auto hdrRenderType = getHdrRenderType(outputState.dataspace, pixelFormat,
+ layerFEState->desiredHdrSdrRatio, hasHdrMetadata);
// Determine the output dependent dataspace for this layer. If it is
// colorspace agnostic, it just uses the dataspace chosen for the output to
@@ -344,30 +396,51 @@
}
// re-get HdrRenderType after the dataspace gets changed.
- hdrRenderType =
- getHdrRenderType(state.dataspace, pixelFormat, layerFEState->desiredHdrSdrRatio);
+ hdrRenderType = getHdrRenderType(state.dataspace, pixelFormat, layerFEState->desiredHdrSdrRatio,
+ hasHdrMetadata);
// For hdr content, treat the white point as the display brightness - HDR content should not be
// boosted or dimmed.
// If the layer explicitly requests to disable dimming, then don't dim either.
- if (hdrRenderType == HdrRenderType::GENERIC_HDR ||
- getOutput().getState().displayBrightnessNits == getOutput().getState().sdrWhitePointNits ||
- getOutput().getState().displayBrightnessNits == 0.f || !layerFEState->dimmingEnabled) {
+ if (getOutput().getState().displayBrightnessNits == getOutput().getState().sdrWhitePointNits ||
+ getOutput().getState().displayBrightnessNits <= 0.f || !layerFEState->dimmingEnabled) {
state.dimmingRatio = 1.f;
state.whitePointNits = getOutput().getState().displayBrightnessNits;
+ } else if (hdrRenderType == HdrRenderType::GENERIC_HDR) {
+ float deviceHeadroom = getOutput().getState().displayBrightnessNits /
+ getOutput().getState().sdrWhitePointNits;
+ float idealizedMaxHeadroom = deviceHeadroom;
+
+ if (FlagManager::getInstance().begone_bright_hlg()) {
+ idealizedMaxHeadroom =
+ std::min(idealizedMaxHeadroom, getIdealizedMaxHeadroom(state.dataspace));
+ }
+
+ state.dimmingRatio = std::min(idealizedMaxHeadroom / deviceHeadroom, 1.0f);
+ state.whitePointNits = getOutput().getState().displayBrightnessNits * state.dimmingRatio;
} else {
+ const bool isLayerFp16 = pixelFormat && *pixelFormat == ui::PixelFormat::RGBA_FP16;
float layerBrightnessNits = getOutput().getState().sdrWhitePointNits;
// RANGE_EXTENDED can "self-promote" to HDR, but is still rendered for a particular
// range that we may need to re-adjust to the current display conditions
+ // Do NOT do this when we may render fp16 to an fp16 client target, to avoid applying
+ // and additional gain to the layer. This is because the fp16 client target should
+ // already be adapted to remap 1.0 to the SDR white point in the panel's luminance
+ // space.
if (hdrRenderType == HdrRenderType::DISPLAY_HDR) {
- layerBrightnessNits *= layerFEState->currentHdrSdrRatio;
+ if (!FlagManager::getInstance().fp16_client_target() || !isLayerFp16) {
+ layerBrightnessNits *= layerFEState->currentHdrSdrRatio;
+ }
}
+
state.dimmingRatio =
std::clamp(layerBrightnessNits / getOutput().getState().displayBrightnessNits, 0.f,
1.f);
state.whitePointNits = layerBrightnessNits;
}
+ updateLuts(*layerFEState, properties);
+
// These are evaluated every frame as they can potentially change at any
// time.
if (layerFEState->forceClientComposition || !profile.isDataspaceSupported(state.dataspace) ||
@@ -376,8 +449,19 @@
}
}
+void OutputLayer::commitPictureProfileToCompositionState() {
+ if (!com_android_graphics_libgui_flags_apply_picture_profiles()) {
+ return;
+ }
+ const auto* layerState = getLayerFE().getCompositionState();
+ if (layerState) {
+ editState().pictureProfileHandle = layerState->pictureProfileHandle;
+ }
+}
+
void OutputLayer::writeStateToHWC(bool includeGeometry, bool skipLayer, uint32_t z,
- bool zIsOverridden, bool isPeekingThrough) {
+ bool zIsOverridden, bool isPeekingThrough,
+ bool hasLutsProperties) {
const auto& state = getState();
// Skip doing this if there is no HWC interface
if (!state.hwc) {
@@ -419,6 +503,9 @@
writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType, isPeekingThrough,
skipLayer);
+ if (hasLutsProperties) {
+ writeLutToHWC(hwcLayer.get(), *outputIndependentState);
+ }
if (requestedCompositionType == Composition::SOLID_COLOR) {
writeSolidColorStateToHWC(hwcLayer.get(), *outputIndependentState);
@@ -426,6 +513,15 @@
editState().hwc->stateOverridden = isOverridden;
editState().hwc->layerSkipped = skipLayer;
+
+
+ // Save the final HWC state for debugging purposes, e.g. perfetto tracing, dumpsys.
+ getLayerFE().setLastHwcState({.lastCompositionType = editState().hwc->hwcCompositionType,
+ .wasSkipped = skipLayer,
+ .wasOverridden = isOverridden,
+ .overrideBufferId = editState().overrideInfo.buffer
+ ? editState().overrideInfo.buffer.get()->getId()
+ : 0});
}
void OutputLayer::writeOutputDependentGeometryStateToHWC(HWC2::Layer* hwcLayer,
@@ -513,6 +609,41 @@
}
}
+void OutputLayer::writeLutToHWC(HWC2::Layer* hwcLayer,
+ const LayerFECompositionState& outputIndependentState) {
+ Luts luts;
+ // if outputIndependentState.luts is nullptr, it means we want to clear the LUTs
+ // and we pass an empty Luts object to the HWC.
+ if (outputIndependentState.luts) {
+ auto& lutFileDescriptor = outputIndependentState.luts->getLutFileDescriptor();
+ auto lutOffsets = outputIndependentState.luts->offsets;
+ auto& lutProperties = outputIndependentState.luts->lutProperties;
+
+ std::vector<LutProperties> aidlProperties;
+ aidlProperties.reserve(lutProperties.size());
+ for (size_t i = 0; i < lutOffsets.size(); i++) {
+ aidlProperties.emplace_back(
+ LutProperties{.dimension = static_cast<LutProperties::Dimension>(
+ lutProperties[i].dimension),
+ .size = lutProperties[i].size,
+ .samplingKeys = {static_cast<LutProperties::SamplingKey>(
+ lutProperties[i].samplingKey)}});
+ }
+
+ luts.pfd.set(dup(lutFileDescriptor.get()));
+ luts.offsets = lutOffsets;
+ luts.lutProperties = std::move(aidlProperties);
+ }
+
+ switch (auto error = hwcLayer->setLuts(luts)) {
+ case hal::Error::NONE:
+ break;
+ default:
+ ALOGE("[%s] Failed to set Luts: %s (%d)", getLayerFE().getDebugName(),
+ to_string(error).c_str(), static_cast<int32_t>(error));
+ }
+}
+
void OutputLayer::writeOutputDependentPerFrameStateToHWC(HWC2::Layer* hwcLayer) {
const auto& outputDependentState = getState();
@@ -561,6 +692,21 @@
ALOGE("[%s] Failed to set brightness %f: %s (%d)", getLayerFE().getDebugName(),
dimmingRatio, to_string(error).c_str(), static_cast<int32_t>(error));
}
+
+ if (com_android_graphics_libgui_flags_apply_picture_profiles() &&
+ outputDependentState.pictureProfileHandle) {
+ if (auto error =
+ hwcLayer->setPictureProfileHandle(outputDependentState.pictureProfileHandle);
+ error != hal::Error::NONE) {
+ ALOGE("[%s] Failed to set picture profile handle: %s (%d)", getLayerFE().getDebugName(),
+ toString(outputDependentState.pictureProfileHandle).c_str(),
+ static_cast<int32_t>(error));
+ }
+ // Reset the picture profile state, as it needs to be re-committed on each present cycle
+ // when Output decides that the limited picture-processing hardware should be used by this
+ // layer.
+ editState().pictureProfileHandle = PictureProfileHandle::NONE;
+ }
}
void OutputLayer::writeOutputIndependentPerFrameStateToHWC(
@@ -666,6 +812,16 @@
}
}
+int64_t OutputLayer::getPictureProfilePriority() const {
+ const auto* layerState = getLayerFE().getCompositionState();
+ return layerState ? layerState->pictureProfilePriority : 0;
+}
+
+const PictureProfileHandle& OutputLayer::getPictureProfileHandle() const {
+ const auto* layerState = getLayerFE().getCompositionState();
+ return layerState ? layerState->pictureProfileHandle : PictureProfileHandle::NONE;
+}
+
void OutputLayer::writeBufferStateToHWC(HWC2::Layer* hwcLayer,
const LayerFECompositionState& outputIndependentState,
bool skipLayer) {
@@ -720,7 +876,8 @@
bool isPeekingThrough, bool skipLayer) {
auto& outputDependentState = editState();
- if (isClientCompositionForced(isPeekingThrough)) {
+ bool isCached = !skipLayer && outputDependentState.overrideInfo.buffer;
+ if (isClientCompositionForced(isPeekingThrough, isCached)) {
// If we are forcing client composition, we need to tell the HWC
requestedCompositionType = Composition::CLIENT;
}
@@ -748,14 +905,14 @@
return;
}
- const auto* layerFEState = getLayerFE().getCompositionState();
- if (!layerFEState) {
+ const auto* layerState = getLayerFE().getCompositionState();
+ if (!layerState) {
return;
}
const auto& outputState = getOutput().getState();
- Rect frame = layerFEState->cursorFrame;
+ Rect frame = layerState->cursorFrame;
frame.intersect(outputState.layerStackSpace.getContent(), &frame);
Rect position = outputState.transform.transform(frame);
@@ -810,9 +967,12 @@
}
}
-bool OutputLayer::isClientCompositionForced(bool isPeekingThrough) const {
+bool OutputLayer::isClientCompositionForced(bool isPeekingThrough, bool isCached) const {
+ // If this layer was flattened into a CachedSet then it is not necessary for
+ // the GPU to compose it.
+ bool requiresClientDrawnRoundedCorners = !isCached && getLayerFE().hasRoundedCorners();
return getState().forceClientComposition ||
- (!isPeekingThrough && getLayerFE().hasRoundedCorners());
+ (!isPeekingThrough && requiresClientDrawnRoundedCorners);
}
void OutputLayer::applyDeviceCompositionTypeChange(Composition compositionType) {
@@ -828,6 +988,13 @@
}
hwcState.hwcCompositionType = compositionType;
+
+ getLayerFE().setLastHwcState({.lastCompositionType = hwcState.hwcCompositionType,
+ .wasSkipped = hwcState.layerSkipped,
+ .wasOverridden = hwcState.stateOverridden,
+ .overrideBufferId = state.overrideInfo.buffer
+ ? state.overrideInfo.buffer.get()->getId()
+ : 0});
}
void OutputLayer::prepareForDeviceLayerRequests() {
@@ -849,10 +1016,29 @@
}
}
-void OutputLayer::applyDeviceLayerLut(LutProperties /*lutProperties*/,
- ndk::ScopedFileDescriptor /*lutPfd*/) {
- // TODO(b/329472856): decode the shared memory of the pfd, and store the lut data into
- // OutputLayerCompositionState#hwc struct
+void OutputLayer::applyDeviceLayerLut(
+ ::android::base::unique_fd lutFd,
+ std::vector<std::pair<int, LutProperties>> lutOffsetsAndProperties) {
+ auto& state = editState();
+ LOG_FATAL_IF(!state.hwc);
+ auto& hwcState = *state.hwc;
+ std::vector<int32_t> offsets;
+ std::vector<int32_t> dimensions;
+ std::vector<int32_t> sizes;
+ std::vector<int32_t> samplingKeys;
+ for (const auto& [offset, properties] : lutOffsetsAndProperties) {
+ // The Lut(s) that comes back through CommandResultPayload should be
+ // only one sampling key.
+ if (properties.samplingKeys.size() == 1) {
+ offsets.emplace_back(offset);
+ dimensions.emplace_back(static_cast<int32_t>(properties.dimension));
+ sizes.emplace_back(static_cast<int32_t>(properties.size));
+ samplingKeys.emplace_back(static_cast<int32_t>(properties.samplingKeys[0]));
+ }
+ }
+ hwcState.luts = std::make_shared<gui::DisplayLuts>(std::move(lutFd), std::move(offsets),
+ std::move(dimensions), std::move(sizes),
+ std::move(samplingKeys));
}
bool OutputLayer::needsFiltering() const {
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp
index da1f7e4..deef747 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp
@@ -72,6 +72,9 @@
dumpVal(out, "dataspace", toString(dataspace), dataspace);
dumpVal(out, "whitePointNits", whitePointNits);
dumpVal(out, "dimmingRatio", dimmingRatio);
+ if (pictureProfileHandle) {
+ dumpVal(out, "pictureProfile", toString(pictureProfileHandle));
+ }
dumpVal(out, "override buffer", overrideInfo.buffer.get());
dumpVal(out, "override acquire fence", overrideInfo.acquireFence.get());
dumpVal(out, "override display frame", overrideInfo.displayFrame);
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
index 783209c..b290823 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
@@ -325,6 +325,7 @@
priorBlurLayer == (*incomingLayerIter)->getOutputLayer();
OutputLayer::CompositionState& state =
(*incomingLayerIter)->getOutputLayer()->editState();
+
state.overrideInfo = {
.buffer = mNewCachedSet->getBuffer(),
.acquireFence = mNewCachedSet->getDrawFence(),
@@ -378,6 +379,7 @@
};
++incomingLayerIter;
}
+ priorBlurLayer = currentLayerIter->getBlurLayer();
} else if (currentLayerIter->getLayerCount() > 1) {
// Break the current layer into its constituent layers
++mInvalidatedCachedSetAges[currentLayerIter->getAge()];
@@ -400,8 +402,8 @@
currentLayerIter->updateAge(now);
merged.emplace_back(*currentLayerIter);
++incomingLayerIter;
+ priorBlurLayer = currentLayerIter->getBlurLayer();
}
- priorBlurLayer = currentLayerIter->getBlurLayer();
++currentLayerIter;
}
diff --git a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
index 639164d..ad65c44 100644
--- a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
@@ -26,11 +26,8 @@
#include <gtest/gtest.h>
#include <renderengine/mock/RenderEngine.h>
-#include "MockHWComposer.h"
#include "TimeStats/TimeStats.h"
-#include "gmock/gmock.h"
-
-#include <variant>
+#include "mock/DisplayHardware/MockHWComposer.h"
using namespace com::android::graphics::surfaceflinger;
@@ -64,7 +61,7 @@
TEST_F(CompositionEngineTest, canSetHWComposer) {
android::mock::HWComposer* hwc = new StrictMock<android::mock::HWComposer>();
- mEngine.setHwComposer(std::unique_ptr<android::HWComposer>(hwc));
+ mEngine.setHwComposer(static_cast<android::HWComposer*>(hwc));
EXPECT_EQ(hwc, &mEngine.getHwComposer());
}
@@ -494,9 +491,6 @@
};
TEST_F(CompositionEnginePostCompositionTest, postCompositionReleasesAllFences) {
- SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, true);
- ASSERT_TRUE(FlagManager::getInstance().ce_fence_promise());
-
EXPECT_CALL(*mLayer1FE, getReleaseFencePromiseStatus)
.WillOnce(Return(LayerFE::ReleaseFencePromiseStatus::FULFILLED));
EXPECT_CALL(*mLayer2FE, getReleaseFencePromiseStatus)
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 9c0e62c..c1e59d0 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -36,10 +36,10 @@
#include <ui/Rect.h>
#include <ui/StaticDisplayInfo.h>
-#include "MockHWC2.h"
-#include "MockHWComposer.h"
-#include "MockPowerAdvisor.h"
#include "ftl/future.h"
+#include "mock/DisplayHardware/MockHWC2.h"
+#include "mock/DisplayHardware/MockHWComposer.h"
+#include "mock/PowerAdvisor/MockPowerAdvisor.h"
#include <aidl/android/hardware/graphics/composer3/Composition.h>
@@ -192,7 +192,7 @@
}
StrictMock<android::mock::HWComposer> mHwComposer;
- StrictMock<Hwc2::mock::PowerAdvisor> mPowerAdvisor;
+ StrictMock<adpf::mock::PowerAdvisor> mPowerAdvisor;
StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
StrictMock<mock::CompositionEngine> mCompositionEngine;
sp<mock::NativeWindow> mNativeWindow = sp<StrictMock<mock::NativeWindow>>::make();
@@ -1035,7 +1035,7 @@
}
NiceMock<android::mock::HWComposer> mHwComposer;
- NiceMock<Hwc2::mock::PowerAdvisor> mPowerAdvisor;
+ NiceMock<adpf::mock::PowerAdvisor> mPowerAdvisor;
NiceMock<mock::CompositionEngine> mCompositionEngine;
sp<mock::NativeWindow> mNativeWindow = sp<NiceMock<mock::NativeWindow>>::make();
sp<mock::DisplaySurface> mDisplaySurface = sp<NiceMock<mock::DisplaySurface>>::make();
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.cpp b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.cpp
deleted file mode 100644
index 0baa79d..0000000
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2019 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 "MockHWC2.h"
-
-namespace android::HWC2 {
-
-// This will go away once HWC2::Layer is moved into the "backend" library
-Layer::~Layer() = default;
-
-namespace mock {
-
-// The Google Mock documentation recommends explicit non-header instantiations
-// for better compile time performance.
-Layer::Layer() = default;
-Layer::~Layer() = default;
-
-} // namespace mock
-} // namespace android::HWC2
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
deleted file mode 100644
index eb6e677..0000000
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2019 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 <gmock/gmock.h>
-#include <ui/Fence.h>
-#include <ui/FloatRect.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/Rect.h>
-#include <ui/Region.h>
-#include <ui/Transform.h>
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-#pragma clang diagnostic ignored "-Wextra"
-
-#include <ui/GraphicTypes.h>
-#include "DisplayHardware/HWC2.h"
-
-#include <aidl/android/hardware/graphics/composer3/Composition.h>
-#include <aidl/android/hardware/graphics/composer3/Lut.h>
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
-
-namespace android {
-namespace HWC2 {
-namespace mock {
-
-namespace hal = android::hardware::graphics::composer::hal;
-
-using Error = hal::Error;
-
-class Layer : public HWC2::Layer {
-public:
- Layer();
- ~Layer() override;
-
- MOCK_CONST_METHOD0(getId, hal::HWLayerId());
-
- MOCK_METHOD2(setCursorPosition, Error(int32_t, int32_t));
- MOCK_METHOD3(setBuffer,
- Error(uint32_t, const android::sp<android::GraphicBuffer>&,
- const android::sp<android::Fence>&));
- MOCK_METHOD2(setBufferSlotsToClear, Error(const std::vector<uint32_t>&, uint32_t));
- MOCK_METHOD1(setSurfaceDamage, Error(const android::Region&));
- MOCK_METHOD1(setBlendMode, Error(hal::BlendMode));
- MOCK_METHOD1(setColor, Error(aidl::android::hardware::graphics::composer3::Color));
- MOCK_METHOD1(setCompositionType,
- Error(aidl::android::hardware::graphics::composer3::Composition));
- MOCK_METHOD1(setDataspace, Error(android::ui::Dataspace));
- MOCK_METHOD2(setPerFrameMetadata, Error(const int32_t, const android::HdrMetadata&));
- MOCK_METHOD1(setDisplayFrame, Error(const android::Rect&));
- MOCK_METHOD1(setPlaneAlpha, Error(float));
- MOCK_METHOD1(setSidebandStream, Error(const native_handle_t*));
- MOCK_METHOD1(setSourceCrop, Error(const android::FloatRect&));
- MOCK_METHOD1(setTransform, Error(hal::Transform));
- MOCK_METHOD1(setVisibleRegion, Error(const android::Region&));
- MOCK_METHOD1(setZOrder, Error(uint32_t));
-
- MOCK_METHOD1(setColorTransform, Error(const android::mat4&));
- MOCK_METHOD3(setLayerGenericMetadata,
- Error(const std::string&, bool, const std::vector<uint8_t>&));
- MOCK_METHOD1(setBrightness, Error(float));
- MOCK_METHOD1(setBlockingRegion, Error(const android::Region&));
- MOCK_METHOD(Error, setLuts, (std::vector<aidl::android::hardware::graphics::composer3::Lut>&));
-};
-
-} // namespace mock
-} // namespace HWC2
-} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
deleted file mode 100644
index 5c55ce7..0000000
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright 2018 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 <compositionengine/Output.h>
-#include <gmock/gmock.h>
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-#pragma clang diagnostic ignored "-Wextra"
-
-#include "DisplayHardware/HWComposer.h"
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
-
-namespace android {
-namespace mock {
-
-namespace hal = android::hardware::graphics::composer::hal;
-
-class HWComposer : public android::HWComposer {
-public:
- HWComposer();
- ~HWComposer() override;
-
- MOCK_METHOD1(setCallback, void(HWC2::ComposerCallback&));
- MOCK_CONST_METHOD3(getDisplayIdentificationData,
- bool(hal::HWDisplayId, uint8_t*, DisplayIdentificationData*));
- MOCK_CONST_METHOD1(hasCapability,
- bool(aidl::android::hardware::graphics::composer3::Capability));
- MOCK_CONST_METHOD2(hasDisplayCapability,
- bool(HalDisplayId,
- aidl::android::hardware::graphics::composer3::DisplayCapability));
-
- MOCK_CONST_METHOD0(getMaxVirtualDisplayCount, size_t());
- MOCK_CONST_METHOD0(getMaxVirtualDisplayDimension, size_t());
- MOCK_METHOD3(allocateVirtualDisplay, bool(HalVirtualDisplayId, ui::Size, ui::PixelFormat*));
- MOCK_METHOD3(allocatePhysicalDisplay,
- void(hal::HWDisplayId, PhysicalDisplayId, std::optional<ui::Size>));
-
- MOCK_METHOD1(createLayer, std::shared_ptr<HWC2::Layer>(HalDisplayId));
- MOCK_METHOD(status_t, getDeviceCompositionChanges,
- (HalDisplayId, bool, std::optional<std::chrono::steady_clock::time_point>, nsecs_t,
- Fps, std::optional<android::HWComposer::DeviceRequestedChanges>*));
- MOCK_METHOD(status_t, setClientTarget,
- (HalDisplayId, uint32_t, const sp<Fence>&, const sp<GraphicBuffer>&, ui::Dataspace,
- float),
- (override));
- MOCK_METHOD2(presentAndGetReleaseFences,
- status_t(HalDisplayId, std::optional<std::chrono::steady_clock::time_point>));
- MOCK_METHOD(status_t, executeCommands, (HalDisplayId));
- MOCK_METHOD2(setPowerMode, status_t(PhysicalDisplayId, hal::PowerMode));
- MOCK_METHOD2(setActiveConfig, status_t(HalDisplayId, size_t));
- MOCK_METHOD2(setColorTransform, status_t(HalDisplayId, const mat4&));
- MOCK_METHOD1(disconnectDisplay, void(HalDisplayId));
- MOCK_CONST_METHOD1(hasDeviceComposition, bool(const std::optional<DisplayId>&));
- MOCK_CONST_METHOD1(getPresentFence, sp<Fence>(HalDisplayId));
- MOCK_METHOD(nsecs_t, getPresentTimestamp, (PhysicalDisplayId), (const, override));
- MOCK_CONST_METHOD2(getLayerReleaseFence, sp<Fence>(HalDisplayId, HWC2::Layer*));
- MOCK_METHOD3(setOutputBuffer,
- status_t(HalVirtualDisplayId, const sp<Fence>&, const sp<GraphicBuffer>&));
- MOCK_METHOD1(clearReleaseFences, void(HalDisplayId));
- MOCK_METHOD2(getHdrCapabilities, status_t(HalDisplayId, HdrCapabilities*));
- MOCK_CONST_METHOD1(getSupportedPerFrameMetadata, int32_t(HalDisplayId));
- MOCK_CONST_METHOD2(getRenderIntents,
- std::vector<ui::RenderIntent>(HalDisplayId, ui::ColorMode));
- MOCK_METHOD2(getDataspaceSaturationMatrix, mat4(HalDisplayId, ui::Dataspace));
- MOCK_METHOD4(getDisplayedContentSamplingAttributes,
- status_t(HalDisplayId, ui::PixelFormat*, ui::Dataspace*, uint8_t*));
- MOCK_METHOD4(setDisplayContentSamplingEnabled, status_t(HalDisplayId, bool, uint8_t, uint64_t));
- MOCK_METHOD4(getDisplayedContentSample,
- status_t(HalDisplayId, uint64_t, uint64_t, DisplayedFrameStats*));
- MOCK_METHOD(ftl::Future<status_t>, setDisplayBrightness,
- (PhysicalDisplayId, float, float, const Hwc2::Composer::DisplayBrightnessOptions&),
- (override));
- MOCK_METHOD2(getDisplayBrightnessSupport, status_t(PhysicalDisplayId, bool*));
-
- MOCK_METHOD2(onHotplug,
- std::optional<DisplayIdentificationInfo>(hal::HWDisplayId, hal::Connection));
- MOCK_CONST_METHOD0(updatesDeviceProductInfoOnHotplugReconnect, bool());
- MOCK_METHOD(std::optional<PhysicalDisplayId>, onVsync, (hal::HWDisplayId, int64_t));
- MOCK_METHOD2(setVsyncEnabled, void(PhysicalDisplayId, hal::Vsync));
- MOCK_CONST_METHOD1(isConnected, bool(PhysicalDisplayId));
- MOCK_CONST_METHOD2(getModes,
- std::vector<HWComposer::HWCDisplayMode>(PhysicalDisplayId, int32_t));
- MOCK_CONST_METHOD1(getActiveMode, ftl::Expected<hal::HWConfigId, status_t>(PhysicalDisplayId));
- MOCK_CONST_METHOD1(getColorModes, std::vector<ui::ColorMode>(PhysicalDisplayId));
- MOCK_METHOD3(setActiveColorMode, status_t(PhysicalDisplayId, ui::ColorMode, ui::RenderIntent));
- MOCK_CONST_METHOD0(isUsingVrComposer, bool());
- MOCK_CONST_METHOD1(getDisplayConnectionType, ui::DisplayConnectionType(PhysicalDisplayId));
- MOCK_CONST_METHOD1(isVsyncPeriodSwitchSupported, bool(PhysicalDisplayId));
- MOCK_CONST_METHOD1(getDisplayVsyncPeriod, ftl::Expected<nsecs_t, status_t>(PhysicalDisplayId));
- MOCK_METHOD4(setActiveModeWithConstraints,
- status_t(PhysicalDisplayId, hal::HWConfigId,
- const hal::VsyncPeriodChangeConstraints&,
- hal::VsyncPeriodChangeTimeline*));
- MOCK_METHOD2(setBootDisplayMode, status_t(PhysicalDisplayId, hal::HWConfigId));
- MOCK_METHOD1(clearBootDisplayMode, status_t(PhysicalDisplayId));
- MOCK_METHOD1(getPreferredBootDisplayMode, std::optional<hal::HWConfigId>(PhysicalDisplayId));
- MOCK_METHOD0(getBootDisplayModeSupport, bool());
- MOCK_CONST_METHOD0(
- getHdrConversionCapabilities,
- std::vector<aidl::android::hardware::graphics::common::HdrConversionCapability>());
- MOCK_METHOD2(setHdrConversionStrategy,
- status_t(aidl::android::hardware::graphics::common::HdrConversionStrategy,
- aidl::android::hardware::graphics::common::Hdr*));
- MOCK_METHOD2(setAutoLowLatencyMode, status_t(PhysicalDisplayId, bool));
- MOCK_METHOD(status_t, getSupportedContentTypes,
- (PhysicalDisplayId, std::vector<hal::ContentType>*), (const, override));
- MOCK_METHOD2(setContentType, status_t(PhysicalDisplayId, hal::ContentType));
- MOCK_CONST_METHOD0(getSupportedLayerGenericMetadata,
- const std::unordered_map<std::string, bool>&());
-
- MOCK_CONST_METHOD1(dump, void(std::string&));
- MOCK_CONST_METHOD1(dumpOverlayProperties, void(std::string&));
- MOCK_CONST_METHOD0(getComposer, android::Hwc2::Composer*());
-
- MOCK_METHOD(hal::HWDisplayId, getPrimaryHwcDisplayId, (), (const, override));
- MOCK_METHOD(PhysicalDisplayId, getPrimaryDisplayId, (), (const, override));
- MOCK_METHOD(bool, isHeadless, (), (const, override));
-
- MOCK_METHOD(std::optional<PhysicalDisplayId>, toPhysicalDisplayId, (hal::HWDisplayId),
- (const, override));
- MOCK_METHOD(std::optional<hal::HWDisplayId>, fromPhysicalDisplayId, (PhysicalDisplayId),
- (const, override));
- MOCK_METHOD2(getDisplayDecorationSupport,
- status_t(PhysicalDisplayId,
- std::optional<aidl::android::hardware::graphics::common::
- DisplayDecorationSupport>* support));
- MOCK_METHOD2(setIdleTimerEnabled, status_t(PhysicalDisplayId, std::chrono::milliseconds));
- MOCK_METHOD(bool, hasDisplayIdleTimerCapability, (PhysicalDisplayId), (const, override));
- MOCK_METHOD(Hwc2::AidlTransform, getPhysicalDisplayOrientation, (PhysicalDisplayId),
- (const, override));
- MOCK_METHOD(bool, getValidateSkipped, (HalDisplayId), (const, override));
- MOCK_METHOD(const aidl::android::hardware::graphics::composer3::OverlayProperties&,
- getOverlaySupport, (), (const, override));
- MOCK_METHOD(status_t, setRefreshRateChangedCallbackDebugEnabled, (PhysicalDisplayId, bool));
- MOCK_METHOD(status_t, notifyExpectedPresent, (PhysicalDisplayId, TimePoint, Fps));
- MOCK_METHOD((HWC2::Display::LutFileDescriptorMapper&), getLutFileDescriptorMapper, (), ());
-};
-
-} // namespace mock
-} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.cpp b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.cpp
deleted file mode 100644
index 85b9403..0000000
--- a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2019 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 "MockPowerAdvisor.h"
-
-namespace android {
-namespace Hwc2 {
-
-// This will go away once PowerAdvisor is moved into the "backend" library
-PowerAdvisor::~PowerAdvisor() = default;
-
-namespace mock {
-
-// The Google Mock documentation recommends explicit non-header instantiations
-// for better compile time performance.
-PowerAdvisor::PowerAdvisor() = default;
-PowerAdvisor::~PowerAdvisor() = default;
-
-} // namespace mock
-} // namespace Hwc2
-} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
deleted file mode 100644
index ed2ffa9..0000000
--- a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2019 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 <gmock/gmock.h>
-
-#include "DisplayHardware/PowerAdvisor.h"
-
-namespace android {
-namespace Hwc2 {
-namespace mock {
-
-class PowerAdvisor : public android::Hwc2::PowerAdvisor {
-public:
- PowerAdvisor();
- ~PowerAdvisor() override;
-
- MOCK_METHOD(void, init, (), (override));
- MOCK_METHOD(void, onBootFinished, (), (override));
- MOCK_METHOD(void, setExpensiveRenderingExpected, (DisplayId displayId, bool expected),
- (override));
- MOCK_METHOD(bool, isUsingExpensiveRendering, (), (override));
- MOCK_METHOD(void, notifyCpuLoadUp, (), (override));
- MOCK_METHOD(void, notifyDisplayUpdateImminentAndCpuReset, (), (override));
- MOCK_METHOD(bool, usePowerHintSession, (), (override));
- MOCK_METHOD(bool, supportsPowerHintSession, (), (override));
- MOCK_METHOD(bool, supportsGpuReporting, (), (override));
- MOCK_METHOD(void, updateTargetWorkDuration, (Duration targetDuration), (override));
- MOCK_METHOD(void, reportActualWorkDuration, (), (override));
- MOCK_METHOD(void, enablePowerHintSession, (bool enabled), (override));
- MOCK_METHOD(bool, startPowerHintSession, (std::vector<int32_t> && threadIds), (override));
- MOCK_METHOD(void, setGpuStartTime, (DisplayId displayId, TimePoint startTime), (override));
- MOCK_METHOD(void, setGpuFenceTime,
- (DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime), (override));
- MOCK_METHOD(void, setHwcValidateTiming,
- (DisplayId displayId, TimePoint validateStartTime, TimePoint validateEndTime),
- (override));
- MOCK_METHOD(void, setHwcPresentTiming,
- (DisplayId displayId, TimePoint presentStartTime, TimePoint presentEndTime),
- (override));
- MOCK_METHOD(void, setSkippedValidate, (DisplayId displayId, bool skipped), (override));
- MOCK_METHOD(void, setRequiresRenderEngine, (DisplayId displayId, bool requiresRenderEngine),
- (override));
- MOCK_METHOD(void, setExpectedPresentTime, (TimePoint expectedPresentTime), (override));
- MOCK_METHOD(void, setSfPresentTiming, (TimePoint presentFenceTime, TimePoint presentEndTime),
- (override));
- MOCK_METHOD(void, setHwcPresentDelayedTime,
- (DisplayId displayId, TimePoint earliestFrameStartTime));
- MOCK_METHOD(void, setFrameDelay, (Duration frameDelayDuration), (override));
- MOCK_METHOD(void, setCommitStart, (TimePoint commitStartTime), (override));
- MOCK_METHOD(void, setCompositeEnd, (TimePoint compositeEndTime), (override));
- MOCK_METHOD(void, setDisplays, (std::vector<DisplayId> & displayIds), (override));
- MOCK_METHOD(void, setTotalFrameTargetWorkDuration, (Duration targetDuration), (override));
-};
-
-} // namespace mock
-} // namespace Hwc2
-} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index b21533a..ca262ee 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <com_android_graphics_libgui_flags.h>
#include <compositionengine/impl/HwcBufferCache.h>
#include <compositionengine/impl/OutputLayer.h>
#include <compositionengine/impl/OutputLayerCompositionState.h>
@@ -23,14 +24,14 @@
#include <compositionengine/mock/Output.h>
#include <gtest/gtest.h>
#include <log/log.h>
-
#include <renderengine/impl/ExternalTexture.h>
#include <renderengine/mock/RenderEngine.h>
+#include <ui/FloatRect.h>
#include <ui/PixelFormat.h>
-#include "MockHWC2.h"
-#include "MockHWComposer.h"
+
#include "RegionMatcher.h"
-#include "ui/FloatRect.h"
+#include "mock/DisplayHardware/MockHWC2.h"
+#include "mock/DisplayHardware/MockHWComposer.h"
#include <aidl/android/hardware/graphics/composer3/Composition.h>
@@ -540,6 +541,9 @@
MOCK_CONST_METHOD1(calculateOutputSourceCrop, FloatRect(uint32_t));
MOCK_CONST_METHOD0(calculateOutputDisplayFrame, Rect());
MOCK_CONST_METHOD1(calculateOutputRelativeBufferTransform, uint32_t(uint32_t));
+ MOCK_METHOD(void, updateLuts,
+ (const LayerFECompositionState&,
+ const std::optional<std::vector<std::optional<LutProperties>>>&));
// compositionengine::OutputLayer overrides
const compositionengine::Output& getOutput() const override { return mOutput; }
@@ -984,21 +988,24 @@
EXPECT_CALL(mLayerFE, getCompositionState()).WillOnce(Return(nullptr));
mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, doesNothingIfNoHWCState) {
mOutputLayer.editState().hwc.reset();
mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, doesNothingIfNoHWCLayer) {
mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc(nullptr);
mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, canSetAllState) {
@@ -1009,7 +1016,8 @@
EXPECT_CALL(mLayerFE, hasRoundedCorners()).WillOnce(Return(false));
mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerTest, displayInstallOrientationBufferTransformSetTo90) {
@@ -1040,7 +1048,8 @@
expectSetColorCall();
mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSideband) {
@@ -1051,7 +1060,8 @@
expectSetCompositionTypeCall(Composition::SIDEBAND);
mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForCursor) {
@@ -1062,7 +1072,8 @@
expectSetCompositionTypeCall(Composition::CURSOR);
mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForDevice) {
@@ -1073,7 +1084,8 @@
expectSetCompositionTypeCall(Composition::DEVICE);
mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsNotSetIfUnchanged) {
@@ -1086,7 +1098,8 @@
expectNoSetCompositionTypeCall();
mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfColorTransformNotSupported) {
@@ -1097,7 +1110,8 @@
expectSetCompositionTypeCall(Composition::CLIENT);
mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfClientCompositionForced) {
@@ -1110,7 +1124,8 @@
expectSetCompositionTypeCall(Composition::CLIENT);
mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, allStateIncludesMetadataIfPresent) {
@@ -1124,7 +1139,8 @@
expectSetCompositionTypeCall(Composition::DEVICE);
mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, perFrameStateDoesNotIncludeMetadataIfPresent) {
@@ -1136,7 +1152,8 @@
expectSetCompositionTypeCall(Composition::DEVICE);
mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, overriddenSkipLayerDoesNotSendBuffer) {
@@ -1151,7 +1168,8 @@
expectSetCompositionTypeCall(Composition::DEVICE);
mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ true, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, overriddenSkipLayerForSolidColorDoesNotSendBuffer) {
@@ -1166,7 +1184,8 @@
expectSetCompositionTypeCall(Composition::DEVICE);
mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ true, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, includesOverrideInfoIfPresent) {
@@ -1181,7 +1200,8 @@
expectSetCompositionTypeCall(Composition::DEVICE);
mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, includesOverrideInfoForSolidColorIfPresent) {
@@ -1196,7 +1216,8 @@
expectSetCompositionTypeCall(Composition::DEVICE);
mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, previousOverriddenLayerSendsSurfaceDamage) {
@@ -1210,7 +1231,8 @@
expectSetCompositionTypeCall(Composition::DEVICE);
mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, previousSkipLayerSendsUpdatedDeviceCompositionInfo) {
@@ -1226,7 +1248,8 @@
expectSetCompositionTypeCall(Composition::DEVICE);
mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, previousSkipLayerSendsUpdatedClientCompositionInfo) {
@@ -1243,7 +1266,8 @@
expectSetCompositionTypeCall(Composition::CLIENT);
mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, peekThroughChangesBlendMode) {
@@ -1257,7 +1281,8 @@
expectPerFrameCommonCalls();
mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, isPeekingThroughSetsOverride) {
@@ -1265,7 +1290,8 @@
expectPerFrameCommonCalls();
mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ true);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ true,
+ /*hasLutsProperties*/ false);
EXPECT_TRUE(mOutputLayer.getState().hwc->stateOverridden);
}
@@ -1275,7 +1301,7 @@
mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
/*zIsOverridden*/ true, /*isPeekingThrough*/
- false);
+ false, /*hasLutsProperties*/ false);
EXPECT_TRUE(mOutputLayer.getState().hwc->stateOverridden);
}
@@ -1287,7 +1313,7 @@
mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
/*zIsOverridden*/ false, /*isPeekingThrough*/
- false);
+ false, /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, roundedCornersPeekingThroughAllowsDeviceComposition) {
@@ -1300,7 +1326,7 @@
mLayerFEState.compositionType = Composition::DEVICE;
mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
/*zIsOverridden*/ false, /*isPeekingThrough*/
- true);
+ true, /*hasLutsProperties*/ false);
EXPECT_EQ(Composition::DEVICE, mOutputLayer.getState().hwc->hwcCompositionType);
}
@@ -1317,7 +1343,7 @@
mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
/*zIsOverridden*/ false, /*isPeekingThrough*/
- false);
+ false, /*hasLutsProperties*/ false);
}
TEST_F(OutputLayerWriteStateToHWCTest, setCompositionTypeRefreshRateIndicator) {
@@ -1329,7 +1355,77 @@
expectSetCompositionTypeCall(Composition::REFRESH_RATE_INDICATOR);
mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
+}
+
+TEST_F(OutputLayerWriteStateToHWCTest, setsPictureProfileWhenCommitted) {
+ if (!com_android_graphics_libgui_flags_apply_picture_profiles()) {
+ GTEST_SKIP() << "Feature flag disabled, skipping";
+ }
+ mLayerFEState.compositionType = Composition::DEVICE;
+ mLayerFEState.pictureProfileHandle = PictureProfileHandle(1);
+
+ expectGeometryCommonCalls();
+ expectPerFrameCommonCalls();
+ expectSetHdrMetadataAndBufferCalls();
+ expectSetCompositionTypeCall(Composition::DEVICE);
+
+ EXPECT_CALL(*mHwcLayer, setPictureProfileHandle(PictureProfileHandle(1)));
+
+ mOutputLayer.commitPictureProfileToCompositionState();
+ mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
+}
+
+TEST_F(OutputLayerWriteStateToHWCTest, doesNotSetPictureProfileWhenNotCommitted) {
+ if (!com_android_graphics_libgui_flags_apply_picture_profiles()) {
+ GTEST_SKIP() << "Feature flag disabled, skipping";
+ }
+ mLayerFEState.compositionType = Composition::DEVICE;
+ mLayerFEState.pictureProfileHandle = PictureProfileHandle(1);
+
+ expectGeometryCommonCalls();
+ expectPerFrameCommonCalls();
+ expectSetHdrMetadataAndBufferCalls();
+ expectSetCompositionTypeCall(Composition::DEVICE);
+
+ EXPECT_CALL(*mHwcLayer, setPictureProfileHandle(_)).Times(0);
+
+ mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
+}
+
+TEST_F(OutputLayerWriteStateToHWCTest, doesNotSetPictureProfileWhenNotCommittedLater) {
+ if (!com_android_graphics_libgui_flags_apply_picture_profiles()) {
+ GTEST_SKIP() << "Feature flag disabled, skipping";
+ }
+ mLayerFEState.compositionType = Composition::DEVICE;
+ mLayerFEState.pictureProfileHandle = PictureProfileHandle(1);
+
+ expectGeometryCommonCalls();
+ expectPerFrameCommonCalls();
+ expectSetHdrMetadataAndBufferCalls();
+ expectSetCompositionTypeCall(Composition::DEVICE);
+
+ EXPECT_CALL(*mHwcLayer, setPictureProfileHandle(PictureProfileHandle(1)));
+
+ mOutputLayer.commitPictureProfileToCompositionState();
+ mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
+
+ expectGeometryCommonCalls();
+ expectPerFrameCommonCalls();
+ expectSetHdrMetadataAndBufferCalls(kExpectedHwcSlot, nullptr, kFence);
+
+ EXPECT_CALL(*mHwcLayer, setPictureProfileHandle(PictureProfileHandle(1))).Times(0);
+ // No committing of picture profile before writing the state
+ mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
}
/*
@@ -1375,21 +1471,24 @@
mLayerFEState.buffer = kBuffer1;
EXPECT_CALL(mHwcLayer, setBuffer(/*slot*/ 0, kBuffer1, kFence));
mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
Mock::VerifyAndClearExpectations(&mHwcLayer);
// Buffer2 is stored in slot 1
mLayerFEState.buffer = kBuffer2;
EXPECT_CALL(mHwcLayer, setBuffer(/*slot*/ 1, kBuffer2, kFence));
mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
Mock::VerifyAndClearExpectations(&mHwcLayer);
// Buffer3 is stored in slot 2
mLayerFEState.buffer = kBuffer3;
EXPECT_CALL(mHwcLayer, setBuffer(/*slot*/ 2, kBuffer3, kFence));
mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
Mock::VerifyAndClearExpectations(&mHwcLayer);
// Buffer2 becomes the active buffer again (with a nullptr) and reuses slot 1
@@ -1397,7 +1496,8 @@
sp<GraphicBuffer> nullBuffer = nullptr;
EXPECT_CALL(mHwcLayer, setBuffer(/*slot*/ 1, nullBuffer, kFence));
mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
Mock::VerifyAndClearExpectations(&mHwcLayer);
// Buffer slots are cleared
@@ -1415,7 +1515,8 @@
mLayerFEState.buffer = kBuffer1;
EXPECT_CALL(mHwcLayer, setBuffer(/*slot*/ 1, kBuffer1, kFence));
mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false);
Mock::VerifyAndClearExpectations(&mHwcLayer);
}
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index c34168d..09ad9fa 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -15,6 +15,7 @@
*/
#include <android-base/stringprintf.h>
+#include <com_android_graphics_libgui_flags.h>
#include <com_android_graphics_surfaceflinger_flags.h>
#include <compositionengine/LayerFECompositionState.h>
#include <compositionengine/impl/Output.h>
@@ -34,15 +35,17 @@
#include <ui/Rect.h>
#include <ui/Region.h>
-#include <cmath>
#include <cstdint>
#include <variant>
+#include <com_android_graphics_surfaceflinger_flags.h>
+
#include <common/FlagManager.h>
#include <common/test/FlagUtils.h>
#include "CallOrderStateMachineHelper.h"
-#include "MockHWC2.h"
#include "RegionMatcher.h"
+#include "mock/DisplayHardware/MockHWC2.h"
+#include "mock/DisplayHardware/MockHWComposer.h"
namespace android::compositionengine {
namespace {
@@ -143,6 +146,24 @@
public:
using impl::Output::injectOutputLayerForTest;
virtual void injectOutputLayerForTest(std::unique_ptr<compositionengine::OutputLayer>) = 0;
+
+ virtual ftl::Optional<DisplayId> getDisplayId() const override { return mId; }
+
+ virtual bool hasPictureProcessing() const override { return mHasPictureProcessing; }
+ virtual int32_t getMaxLayerPictureProfiles() const override {
+ return mMaxLayerPictureProfiles;
+ }
+
+ void setDisplayIdForTest(DisplayId value) { mId = value; }
+
+ void setHasPictureProcessingForTest(bool value) { mHasPictureProcessing = value; }
+
+ void setMaxLayerPictureProfilesForTest(int32_t value) { mMaxLayerPictureProfiles = value; }
+
+ private:
+ ftl::Optional<DisplayId> mId;
+ bool mHasPictureProcessing;
+ int32_t mMaxLayerPictureProfiles;
};
static std::shared_ptr<Output> createOutput(
@@ -158,6 +179,7 @@
mOutput->editState().displaySpace.setBounds(
ui::Size(kDefaultDisplaySize.getWidth(), kDefaultDisplaySize.getHeight()));
EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
+ EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer));
}
void injectOutputLayer(InjectedLayer& layer) {
@@ -170,6 +192,7 @@
static const Rect kDefaultDisplaySize;
+ StrictMock<::android::mock::HWComposer> mHwComposer;
StrictMock<mock::CompositionEngine> mCompositionEngine;
StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
@@ -786,20 +809,26 @@
InjectedLayer layer3;
uint32_t z = 0;
- EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_180));
+ EXPECT_CALL(*layer1.outputLayer,
+ updateCompositionState(false, false, ui::Transform::ROT_180, _));
EXPECT_CALL(*layer1.outputLayer,
writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false));
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false));
EXPECT_CALL(*layer1.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
- EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_180));
+ EXPECT_CALL(*layer2.outputLayer,
+ updateCompositionState(false, false, ui::Transform::ROT_180, _));
EXPECT_CALL(*layer2.outputLayer,
writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false));
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false));
EXPECT_CALL(*layer2.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
- EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_180));
+ EXPECT_CALL(*layer3.outputLayer,
+ updateCompositionState(false, false, ui::Transform::ROT_180, _));
EXPECT_CALL(*layer3.outputLayer,
writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false));
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false));
EXPECT_CALL(*layer3.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
injectOutputLayer(layer1);
@@ -823,20 +852,23 @@
InjectedLayer layer3;
uint32_t z = 0;
- EXPECT_CALL(*layer1.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0));
+ EXPECT_CALL(*layer1.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0, _));
EXPECT_CALL(*layer1.outputLayer,
writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, z++,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false));
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false));
EXPECT_CALL(*layer1.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
- EXPECT_CALL(*layer2.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0));
+ EXPECT_CALL(*layer2.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0, _));
EXPECT_CALL(*layer2.outputLayer,
writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, z++,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false));
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false));
EXPECT_CALL(*layer2.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
- EXPECT_CALL(*layer3.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0));
+ EXPECT_CALL(*layer3.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0, _));
EXPECT_CALL(*layer3.outputLayer,
writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, z++,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false));
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false));
EXPECT_CALL(*layer3.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
injectOutputLayer(layer1);
@@ -859,20 +891,23 @@
InjectedLayer layer3;
uint32_t z = 0;
- EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0));
+ EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0, _));
EXPECT_CALL(*layer1.outputLayer,
writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false));
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false));
EXPECT_CALL(*layer1.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
- EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0));
+ EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0, _));
EXPECT_CALL(*layer2.outputLayer,
writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false));
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false));
EXPECT_CALL(*layer2.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
- EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0));
+ EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0, _));
EXPECT_CALL(*layer3.outputLayer,
writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false));
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false));
EXPECT_CALL(*layer3.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
injectOutputLayer(layer1);
@@ -897,16 +932,17 @@
InjectedLayer layer3;
InSequence seq;
- EXPECT_CALL(*layer0.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0));
- EXPECT_CALL(*layer1.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0));
+ EXPECT_CALL(*layer0.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0, _));
+ EXPECT_CALL(*layer1.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0, _));
EXPECT_CALL(*layer1.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
- EXPECT_CALL(*layer2.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0));
- EXPECT_CALL(*layer3.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0));
+ EXPECT_CALL(*layer2.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0, _));
+ EXPECT_CALL(*layer3.outputLayer, updateCompositionState(true, false, ui::Transform::ROT_0, _));
uint32_t z = 0;
EXPECT_CALL(*layer0.outputLayer,
writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, z++,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false));
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false));
EXPECT_CALL(*layer0.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
// After calling planComposition (which clears overrideInfo), this test sets
@@ -916,15 +952,17 @@
EXPECT_CALL(*layer3.outputLayer,
writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, z++,
/*zIsOverridden*/ true, /*isPeekingThrough*/
- true));
+ true, /*hasLutsProperties*/ false));
EXPECT_CALL(*layer3.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
EXPECT_CALL(*layer1.outputLayer,
writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, z++,
- /*zIsOverridden*/ true, /*isPeekingThrough*/ false));
+ /*zIsOverridden*/ true, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false));
EXPECT_CALL(*layer1.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
EXPECT_CALL(*layer2.outputLayer,
writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ true, z++,
- /*zIsOverridden*/ true, /*isPeekingThrough*/ false));
+ /*zIsOverridden*/ true, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false));
EXPECT_CALL(*layer2.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
injectOutputLayer(layer0);
@@ -3263,57 +3301,9 @@
mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
}
-TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) {
- SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, false);
- ASSERT_FALSE(FlagManager::getInstance().ce_fence_promise());
- // Simulate getting release fences from each layer, and ensure they are passed to the
- // front-end layer interface for each layer correctly.
-
- mOutput.mState.isEnabled = true;
-
- // Create three unique fence instances
- sp<Fence> layer1Fence = sp<Fence>::make();
- sp<Fence> layer2Fence = sp<Fence>::make();
- sp<Fence> layer3Fence = sp<Fence>::make();
-
- Output::FrameFences frameFences;
- frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence);
- frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence);
- frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence);
-
- EXPECT_CALL(mOutput, presentFrame()).WillOnce(Return(frameFences));
- EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
-
- // Compare the pointers values of each fence to make sure the correct ones
- // are passed. This happens to work with the current implementation, but
- // would not survive certain calls like Fence::merge() which would return a
- // new instance.
- EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed(_, _))
- .WillOnce([&layer1Fence](ftl::SharedFuture<FenceResult> futureFenceResult,
- ui::LayerStack) {
- EXPECT_EQ(FenceResult(layer1Fence), futureFenceResult.get());
- });
- EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed(_, _))
- .WillOnce([&layer2Fence](ftl::SharedFuture<FenceResult> futureFenceResult,
- ui::LayerStack) {
- EXPECT_EQ(FenceResult(layer2Fence), futureFenceResult.get());
- });
- EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed(_, _))
- .WillOnce([&layer3Fence](ftl::SharedFuture<FenceResult> futureFenceResult,
- ui::LayerStack) {
- EXPECT_EQ(FenceResult(layer3Fence), futureFenceResult.get());
- });
-
- constexpr bool kFlushEvenWhenDisabled = false;
- mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
-}
-
TEST_F(OutputPostFramebufferTest, releaseFencesAreSetInLayerFE) {
- SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, true);
- ASSERT_TRUE(FlagManager::getInstance().ce_fence_promise());
// Simulate getting release fences from each layer, and ensure they are passed to the
// front-end layer interface for each layer correctly.
-
mOutput.mState.isEnabled = true;
// Create three unique fence instances
@@ -3350,37 +3340,7 @@
mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
}
-TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) {
- SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, false);
- ASSERT_FALSE(FlagManager::getInstance().ce_fence_promise());
-
- mOutput.mState.isEnabled = true;
- mOutput.mState.usesClientComposition = true;
-
- Output::FrameFences frameFences;
- frameFences.clientTargetAcquireFence = sp<Fence>::make();
- frameFences.layerFences.emplace(&mLayer1.hwc2Layer, sp<Fence>::make());
- frameFences.layerFences.emplace(&mLayer2.hwc2Layer, sp<Fence>::make());
- frameFences.layerFences.emplace(&mLayer3.hwc2Layer, sp<Fence>::make());
-
- EXPECT_CALL(mOutput, presentFrame()).WillOnce(Return(frameFences));
- EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
-
- // Fence::merge is called, and since none of the fences are actually valid,
- // Fence::NO_FENCE is returned and passed to each onLayerDisplayed() call.
- // This is the best we can do without creating a real kernel fence object.
- EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed).WillOnce(Return());
- EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed).WillOnce(Return());
- EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed).WillOnce(Return());
-
- constexpr bool kFlushEvenWhenDisabled = false;
- mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
-}
-
TEST_F(OutputPostFramebufferTest, setReleaseFencesIncludeClientTargetAcquireFence) {
- SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, true);
- ASSERT_TRUE(FlagManager::getInstance().ce_fence_promise());
-
mOutput.mState.isEnabled = true;
mOutput.mState.usesClientComposition = true;
@@ -3403,62 +3363,7 @@
mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
}
-TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) {
- SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, false);
- ASSERT_FALSE(FlagManager::getInstance().ce_fence_promise());
-
- mOutput.mState.isEnabled = true;
- mOutput.mState.usesClientComposition = true;
-
- // This should happen even if there are no (current) output layers.
- EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
-
- // Load up the released layers with some mock instances
- sp<StrictMock<mock::LayerFE>> releasedLayer1 = sp<StrictMock<mock::LayerFE>>::make();
- sp<StrictMock<mock::LayerFE>> releasedLayer2 = sp<StrictMock<mock::LayerFE>>::make();
- sp<StrictMock<mock::LayerFE>> releasedLayer3 = sp<StrictMock<mock::LayerFE>>::make();
- Output::ReleasedLayers layers;
- layers.push_back(releasedLayer1);
- layers.push_back(releasedLayer2);
- layers.push_back(releasedLayer3);
- mOutput.setReleasedLayers(std::move(layers));
-
- // Set up a fake present fence
- sp<Fence> presentFence = sp<Fence>::make();
- Output::FrameFences frameFences;
- frameFences.presentFence = presentFence;
-
- EXPECT_CALL(mOutput, presentFrame()).WillOnce(Return(frameFences));
- EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
-
- // Each released layer should be given the presentFence.
- EXPECT_CALL(*releasedLayer1, onLayerDisplayed(_, _))
- .WillOnce([&presentFence](ftl::SharedFuture<FenceResult> futureFenceResult,
- ui::LayerStack) {
- EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get());
- });
- EXPECT_CALL(*releasedLayer2, onLayerDisplayed(_, _))
- .WillOnce([&presentFence](ftl::SharedFuture<FenceResult> futureFenceResult,
- ui::LayerStack) {
- EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get());
- });
- EXPECT_CALL(*releasedLayer3, onLayerDisplayed(_, _))
- .WillOnce([&presentFence](ftl::SharedFuture<FenceResult> futureFenceResult,
- ui::LayerStack) {
- EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get());
- });
-
- constexpr bool kFlushEvenWhenDisabled = false;
- mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
-
- // After the call the list of released layers should have been cleared.
- EXPECT_TRUE(mOutput.getReleasedLayersForTest().empty());
-}
-
TEST_F(OutputPostFramebufferTest, setReleasedLayersSentPresentFence) {
- SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, true);
- ASSERT_TRUE(FlagManager::getInstance().ce_fence_promise());
-
mOutput.mState.isEnabled = true;
mOutput.mState.usesClientComposition = true;
@@ -5066,15 +4971,17 @@
uint32_t z = 0;
// Layer requesting blur, or below, should request client composition, unless opaque.
- EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_0));
+ EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_0, _));
EXPECT_CALL(*layer1.outputLayer,
writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false));
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false));
EXPECT_CALL(*layer1.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
- EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_0));
+ EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_0, _));
EXPECT_CALL(*layer2.outputLayer,
writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false));
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false));
EXPECT_CALL(*layer2.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
layer2.layerFEState.backgroundBlurRadius = 10;
@@ -5100,20 +5007,23 @@
uint32_t z = 0;
// Layer requesting blur, or below, should request client composition.
- EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0));
+ EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0, _));
EXPECT_CALL(*layer1.outputLayer,
writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false));
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false));
EXPECT_CALL(*layer1.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
- EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0));
+ EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0, _));
EXPECT_CALL(*layer2.outputLayer,
writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false));
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false));
EXPECT_CALL(*layer2.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
- EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_0));
+ EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_0, _));
EXPECT_CALL(*layer3.outputLayer,
writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false));
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false));
EXPECT_CALL(*layer3.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
layer2.layerFEState.backgroundBlurRadius = 10;
@@ -5140,20 +5050,23 @@
uint32_t z = 0;
// Layer requesting blur, or below, should request client composition.
- EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0));
+ EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0, _));
EXPECT_CALL(*layer1.outputLayer,
writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false));
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false));
EXPECT_CALL(*layer1.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
- EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0));
+ EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0, _));
EXPECT_CALL(*layer2.outputLayer,
writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false));
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false));
EXPECT_CALL(*layer2.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
- EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_0));
+ EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_0, _));
EXPECT_CALL(*layer3.outputLayer,
writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, z++,
- /*zIsOverridden*/ false, /*isPeekingThrough*/ false));
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false,
+ /*hasLutsProperties*/ false));
EXPECT_CALL(*layer3.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
BlurRegion region;
@@ -5174,6 +5087,133 @@
mOutput->writeCompositionState(args);
}
+TEST_F(OutputUpdateAndWriteCompositionStateTest, assignsDisplayProfileBasedOnLayerPriority) {
+ if (!com_android_graphics_libgui_flags_apply_picture_profiles()) {
+ GTEST_SKIP() << "Feature flag disabled, skipping";
+ }
+
+ mOutput->setDisplayIdForTest(PhysicalDisplayId::fromPort(1));
+ // Has only one display-global picture processing pipeline
+ mOutput->setHasPictureProcessingForTest(true);
+ mOutput->setMaxLayerPictureProfilesForTest(0);
+
+ InjectedLayer layer1;
+ injectOutputLayer(layer1);
+ PictureProfileHandle profileForLayer1(1);
+ EXPECT_CALL(*layer1.outputLayer, getPictureProfilePriority()).WillRepeatedly(Return(1));
+ EXPECT_CALL(*layer1.outputLayer, getPictureProfileHandle())
+ .WillRepeatedly(ReturnRef(profileForLayer1));
+
+ InjectedLayer layer2;
+ injectOutputLayer(layer2);
+ PictureProfileHandle profileForLayer2(2);
+ EXPECT_CALL(*layer2.outputLayer, getPictureProfilePriority()).WillRepeatedly(Return(3));
+ EXPECT_CALL(*layer2.outputLayer, getPictureProfileHandle())
+ .WillRepeatedly(ReturnRef(profileForLayer2));
+
+ InjectedLayer layer3;
+ injectOutputLayer(layer3);
+ PictureProfileHandle profileForLayer3(3);
+ EXPECT_CALL(*layer3.outputLayer, getPictureProfilePriority()).WillRepeatedly(Return(2));
+ EXPECT_CALL(*layer3.outputLayer, getPictureProfileHandle())
+ .WillRepeatedly(ReturnRef(profileForLayer3));
+
+ // Because StrictMock
+ EXPECT_CALL(*layer1.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
+ EXPECT_CALL(*layer1.outputLayer, updateCompositionState(_, _, _, _));
+ EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(_, _, _, _, _, _));
+ EXPECT_CALL(*layer2.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
+ EXPECT_CALL(*layer2.outputLayer, updateCompositionState(_, _, _, _));
+ EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(_, _, _, _, _, _));
+ EXPECT_CALL(*layer3.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
+ EXPECT_CALL(*layer3.outputLayer, updateCompositionState(_, _, _, _));
+ EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(_, _, _, _, _, _));
+
+ // No layer picture profiles should be committed
+ EXPECT_CALL(*layer1.outputLayer, commitPictureProfileToCompositionState).Times(0);
+ EXPECT_CALL(*layer2.outputLayer, commitPictureProfileToCompositionState).Times(0);
+ EXPECT_CALL(*layer3.outputLayer, commitPictureProfileToCompositionState).Times(0);
+
+ // Sets display picture profile to the highest priority layer's profile
+ EXPECT_CALL(mHwComposer, setDisplayPictureProfileHandle(_, Eq(profileForLayer2)));
+
+ // Marks only the highest priority layer as committed
+ EXPECT_CALL(*layer1.layerFE, onPictureProfileCommitted).Times(0);
+ EXPECT_CALL(*layer2.layerFE, onPictureProfileCommitted);
+ EXPECT_CALL(*layer3.layerFE, onPictureProfileCommitted).Times(0);
+
+ mOutput->editState().isEnabled = true;
+ CompositionRefreshArgs args;
+ args.updatingGeometryThisFrame = false;
+ args.devOptForceClientComposition = false;
+ mOutput->updateCompositionState(args);
+ mOutput->planComposition();
+ mOutput->writeCompositionState(args);
+}
+
+TEST_F(OutputUpdateAndWriteCompositionStateTest, assignsLayerProfileBasedOnLayerPriority) {
+ if (!com_android_graphics_libgui_flags_apply_picture_profiles()) {
+ GTEST_SKIP() << "Feature flag disabled, skipping";
+ }
+ mOutput->setDisplayIdForTest(PhysicalDisplayId::fromPort(1));
+ // Has 2 layer-specific picture processing pipelines
+ mOutput->setHasPictureProcessingForTest(true);
+ mOutput->setMaxLayerPictureProfilesForTest(2);
+
+ InjectedLayer layer1;
+ injectOutputLayer(layer1);
+ PictureProfileHandle profileForLayer1(1);
+ EXPECT_CALL(*layer1.outputLayer, getPictureProfilePriority()).WillRepeatedly(Return(1));
+ EXPECT_CALL(*layer1.outputLayer, getPictureProfileHandle())
+ .WillRepeatedly(ReturnRef(profileForLayer1));
+
+ InjectedLayer layer2;
+ injectOutputLayer(layer2);
+ PictureProfileHandle profileForLayer2(2);
+ EXPECT_CALL(*layer2.outputLayer, getPictureProfilePriority()).WillRepeatedly(Return(3));
+ EXPECT_CALL(*layer2.outputLayer, getPictureProfileHandle())
+ .WillRepeatedly(ReturnRef(profileForLayer2));
+
+ InjectedLayer layer3;
+ injectOutputLayer(layer3);
+ PictureProfileHandle profileForLayer3(3);
+ EXPECT_CALL(*layer3.outputLayer, getPictureProfilePriority()).WillRepeatedly(Return(2));
+ EXPECT_CALL(*layer3.outputLayer, getPictureProfileHandle())
+ .WillRepeatedly(ReturnRef(profileForLayer3));
+
+ // Because StrictMock
+ EXPECT_CALL(*layer1.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
+ EXPECT_CALL(*layer1.outputLayer, updateCompositionState(_, _, _, _));
+ EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(_, _, _, _, _, _));
+ EXPECT_CALL(*layer2.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
+ EXPECT_CALL(*layer2.outputLayer, updateCompositionState(_, _, _, _));
+ EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(_, _, _, _, _, _));
+ EXPECT_CALL(*layer3.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
+ EXPECT_CALL(*layer3.outputLayer, updateCompositionState(_, _, _, _));
+ EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(_, _, _, _, _, _));
+
+ // The two highest priority layers should have their picture profiles committed
+ EXPECT_CALL(*layer1.outputLayer, commitPictureProfileToCompositionState).Times(0);
+ EXPECT_CALL(*layer2.outputLayer, commitPictureProfileToCompositionState);
+ EXPECT_CALL(*layer3.outputLayer, commitPictureProfileToCompositionState);
+
+ // Marks only the highest priority layers as committed
+ EXPECT_CALL(*layer1.layerFE, onPictureProfileCommitted).Times(0);
+ EXPECT_CALL(*layer2.layerFE, onPictureProfileCommitted);
+ EXPECT_CALL(*layer3.layerFE, onPictureProfileCommitted);
+
+ // No display picture profile is sent
+ EXPECT_CALL(mHwComposer, setDisplayPictureProfileHandle).Times(0);
+
+ mOutput->editState().isEnabled = true;
+ CompositionRefreshArgs args;
+ args.updatingGeometryThisFrame = false;
+ args.devOptForceClientComposition = false;
+ mOutput->updateCompositionState(args);
+ mOutput->planComposition();
+ mOutput->writeCompositionState(args);
+}
+
TEST_F(GenerateClientCompositionRequestsTest, handlesLandscapeModeSplitScreenRequests) {
// In split-screen landscape mode, the screen is rotated 90 degrees, with
// one layer on the left covering the left side of the output, and one layer
diff --git a/services/surfaceflinger/Display/DisplayModeController.cpp b/services/surfaceflinger/Display/DisplayModeController.cpp
index f8b6c6e..a086aee 100644
--- a/services/surfaceflinger/Display/DisplayModeController.cpp
+++ b/services/surfaceflinger/Display/DisplayModeController.cpp
@@ -28,6 +28,7 @@
#include <ftl/concat.h>
#include <ftl/expected.h>
#include <log/log.h>
+#include <utils/Errors.h>
namespace android::display {
@@ -177,12 +178,13 @@
}
}
-bool DisplayModeController::initiateModeChange(PhysicalDisplayId displayId,
- DisplayModeRequest&& desiredMode,
- const hal::VsyncPeriodChangeConstraints& constraints,
- hal::VsyncPeriodChangeTimeline& outTimeline) {
+auto DisplayModeController::initiateModeChange(
+ PhysicalDisplayId displayId, DisplayModeRequest&& desiredMode,
+ const hal::VsyncPeriodChangeConstraints& constraints,
+ hal::VsyncPeriodChangeTimeline& outTimeline) -> ModeChangeResult {
std::lock_guard lock(mDisplayLock);
- const auto& displayPtr = FTL_EXPECT(mDisplays.get(displayId).ok_or(false)).get();
+ const auto& displayPtr =
+ FTL_EXPECT(mDisplays.get(displayId).ok_or(ModeChangeResult::Aborted)).get();
// TODO: b/255635711 - Flow the DisplayModeRequest through the desired/pending/active states.
// For now, `desiredMode` and `desiredModeOpt` are one and the same, but the latter is not
@@ -201,13 +203,17 @@
const auto& mode = *displayPtr->pendingModeOpt->mode.modePtr;
- if (mComposerPtr->setActiveModeWithConstraints(displayId, mode.getHwcId(), constraints,
- &outTimeline) != OK) {
- return false;
+ const auto error = mComposerPtr->setActiveModeWithConstraints(displayId, mode.getHwcId(),
+ constraints, &outTimeline);
+ switch (error) {
+ case FAILED_TRANSACTION:
+ return ModeChangeResult::Rejected;
+ case OK:
+ SFTRACE_INT(displayPtr->pendingModeFpsTrace.c_str(), mode.getVsyncRate().getIntValue());
+ return ModeChangeResult::Changed;
+ default:
+ return ModeChangeResult::Aborted;
}
-
- SFTRACE_INT(displayPtr->pendingModeFpsTrace.c_str(), mode.getVsyncRate().getIntValue());
- return true;
}
void DisplayModeController::finalizeModeChange(PhysicalDisplayId displayId, DisplayModeId modeId,
diff --git a/services/surfaceflinger/Display/DisplayModeController.h b/services/surfaceflinger/Display/DisplayModeController.h
index 9ec603d..af3e909 100644
--- a/services/surfaceflinger/Display/DisplayModeController.h
+++ b/services/surfaceflinger/Display/DisplayModeController.h
@@ -70,6 +70,7 @@
RefreshRateSelectorPtr selectorPtrFor(PhysicalDisplayId) const EXCLUDES(mDisplayLock);
enum class DesiredModeAction { None, InitiateDisplayModeSwitch, InitiateRenderRateSwitch };
+ enum class ModeChangeResult { Changed, Rejected, Aborted };
DesiredModeAction setDesiredMode(PhysicalDisplayId, DisplayModeRequest&&)
EXCLUDES(mDisplayLock);
@@ -86,9 +87,9 @@
scheduler::FrameRateMode getActiveMode(PhysicalDisplayId) const EXCLUDES(mDisplayLock);
- bool initiateModeChange(PhysicalDisplayId, DisplayModeRequest&&,
- const hal::VsyncPeriodChangeConstraints&,
- hal::VsyncPeriodChangeTimeline& outTimeline)
+ ModeChangeResult initiateModeChange(PhysicalDisplayId, DisplayModeRequest&&,
+ const hal::VsyncPeriodChangeConstraints&,
+ hal::VsyncPeriodChangeTimeline& outTimeline)
REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);
void finalizeModeChange(PhysicalDisplayId, DisplayModeId, Fps vsyncRate, Fps renderFps)
diff --git a/services/surfaceflinger/Display/DisplayModeRequest.h b/services/surfaceflinger/Display/DisplayModeRequest.h
index ec3ec52..2e9dc1e 100644
--- a/services/surfaceflinger/Display/DisplayModeRequest.h
+++ b/services/surfaceflinger/Display/DisplayModeRequest.h
@@ -26,7 +26,8 @@
struct DisplayModeRequest {
scheduler::FrameRateMode mode;
- // Whether to emit DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE.
+ // Whether to emit DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE for a change in refresh rate
+ // or render rate. Ignored for resolution changes, which always emit the event.
bool emitEvent = false;
// Whether to force the request to be applied, even if the mode is unchanged.
diff --git a/services/surfaceflinger/Display/DisplaySnapshot.cpp b/services/surfaceflinger/Display/DisplaySnapshot.cpp
index 0c7a58e..3960740 100644
--- a/services/surfaceflinger/Display/DisplaySnapshot.cpp
+++ b/services/surfaceflinger/Display/DisplaySnapshot.cpp
@@ -26,11 +26,12 @@
namespace android::display {
-DisplaySnapshot::DisplaySnapshot(PhysicalDisplayId displayId,
+DisplaySnapshot::DisplaySnapshot(PhysicalDisplayId displayId, uint8_t port,
ui::DisplayConnectionType connectionType,
DisplayModes&& displayModes, ui::ColorModes&& colorModes,
std::optional<DeviceProductInfo>&& deviceProductInfo)
: mDisplayId(displayId),
+ mPort(port),
mConnectionType(connectionType),
mDisplayModes(std::move(displayModes)),
mColorModes(std::move(colorModes)),
@@ -62,6 +63,8 @@
void DisplaySnapshot::dump(utils::Dumper& dumper) const {
using namespace std::string_view_literals;
+ dumper.dump("port"sv, mPort);
+
dumper.dump("connectionType"sv, ftl::enum_string(mConnectionType));
dumper.dump("colorModes"sv);
diff --git a/services/surfaceflinger/Display/DisplaySnapshot.h b/services/surfaceflinger/Display/DisplaySnapshot.h
index 23471f5..0030aad 100644
--- a/services/surfaceflinger/Display/DisplaySnapshot.h
+++ b/services/surfaceflinger/Display/DisplaySnapshot.h
@@ -16,6 +16,7 @@
#pragma once
+#include <cstdint>
#include <optional>
#include <ui/ColorMode.h>
@@ -30,13 +31,14 @@
// Immutable state of a physical display, captured on hotplug.
class DisplaySnapshot {
public:
- DisplaySnapshot(PhysicalDisplayId, ui::DisplayConnectionType, DisplayModes&&, ui::ColorModes&&,
- std::optional<DeviceProductInfo>&&);
+ DisplaySnapshot(PhysicalDisplayId, uint8_t, ui::DisplayConnectionType, DisplayModes&&,
+ ui::ColorModes&&, std::optional<DeviceProductInfo>&&);
DisplaySnapshot(const DisplaySnapshot&) = delete;
DisplaySnapshot(DisplaySnapshot&&) = default;
PhysicalDisplayId displayId() const { return mDisplayId; }
+ uint8_t port() const { return mPort; }
ui::DisplayConnectionType connectionType() const { return mConnectionType; }
std::optional<DisplayModeId> translateModeId(hal::HWConfigId) const;
@@ -51,6 +53,7 @@
private:
const PhysicalDisplayId mDisplayId;
+ const uint8_t mPort;
const ui::DisplayConnectionType mConnectionType;
// Effectively const except in move constructor.
diff --git a/services/surfaceflinger/Display/VirtualDisplaySnapshot.h b/services/surfaceflinger/Display/VirtualDisplaySnapshot.h
new file mode 100644
index 0000000..c68020c
--- /dev/null
+++ b/services/surfaceflinger/Display/VirtualDisplaySnapshot.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2024 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 <optional>
+#include <string>
+
+#include <ui/DisplayId.h>
+
+#include "Utils/Dumper.h"
+
+namespace android::display {
+
+// Immutable state of a virtual display, captured on creation.
+class VirtualDisplaySnapshot {
+public:
+ VirtualDisplaySnapshot(GpuVirtualDisplayId gpuId, std::string uniqueId)
+ : mIsGpu(true), mUniqueId(std::move(uniqueId)), mVirtualId(gpuId) {}
+ VirtualDisplaySnapshot(HalVirtualDisplayId halId, std::string uniqueId)
+ : mIsGpu(false), mUniqueId(std::move(uniqueId)), mVirtualId(halId) {}
+
+ VirtualDisplayId displayId() const { return mVirtualId; }
+ bool isGpu() const { return mIsGpu; }
+
+ void dump(utils::Dumper& dumper) const {
+ using namespace std::string_view_literals;
+
+ dumper.dump("isGpu"sv, mIsGpu ? "true"sv : "false"sv);
+ dumper.dump("uniqueId"sv, mUniqueId);
+ }
+
+private:
+ const bool mIsGpu;
+ const std::string mUniqueId;
+ const VirtualDisplayId mVirtualId;
+};
+
+} // namespace android::display
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 402a3d2..e8b09b0 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -201,6 +201,10 @@
return mPowerMode != hal::PowerMode::OFF;
}
+bool DisplayDevice::isRefreshable() const {
+ return mPowerMode == hal::PowerMode::DOZE || mPowerMode == hal::PowerMode::ON;
+}
+
ui::Dataspace DisplayDevice::getCompositionDataSpace() const {
return mCompositionDisplay->getState().dataspace;
}
@@ -219,9 +223,7 @@
mFlags = flags;
}
-void DisplayDevice::setDisplaySize(int width, int height) {
- LOG_FATAL_IF(!isVirtual(), "Changing the display size is supported only for virtual displays.");
- const auto size = ui::Size(width, height);
+void DisplayDevice::setDisplaySize(ui::Size size) {
mCompositionDisplay->setDisplaySize(size);
if (mRefreshRateOverlay) {
mRefreshRateOverlay->setViewport(size);
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 3e3f558..b5a543a 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -42,7 +42,6 @@
#include "DisplayHardware/DisplayMode.h"
#include "DisplayHardware/Hal.h"
-#include "DisplayHardware/PowerAdvisor.h"
#include "FrontEnd/DisplayInfo.h"
#include "Scheduler/RefreshRateSelector.h"
#include "ThreadContext.h"
@@ -99,7 +98,7 @@
ui::Size getSize() const { return {getWidth(), getHeight()}; }
void setLayerFilter(ui::LayerFilter);
- void setDisplaySize(int width, int height);
+ void setDisplaySize(ui::Size);
void setProjection(ui::Rotation orientation, Rect viewport, Rect frame);
void stageBrightness(float brightness) REQUIRES(kMainThreadContext);
void persistBrightness(bool needsComposite) REQUIRES(kMainThreadContext);
@@ -173,6 +172,7 @@
hardware::graphics::composer::hal::PowerMode getPowerMode() const;
void setPowerMode(hardware::graphics::composer::hal::PowerMode);
bool isPoweredOn() const;
+ bool isRefreshable() const;
void tracePowerMode();
// Enables layer caching on this DisplayDevice
@@ -260,6 +260,7 @@
struct Physical {
PhysicalDisplayId id;
hardware::graphics::composer::hal::HWDisplayId hwcDisplayId;
+ uint8_t port;
DisplayModePtr activeMode;
bool operator==(const Physical& other) const {
@@ -285,6 +286,8 @@
bool isProtected = false;
// Refer to DisplayDevice::mRequestedRefreshRate, for virtual display only
Fps requestedRefreshRate;
+ int32_t maxLayerPictureProfiles = 0;
+ bool hasPictureProcessing = false;
private:
static std::atomic<int32_t> sNextSequenceId;
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
index 77bd804..bb6bebe 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -26,30 +26,28 @@
#include <android/binder_manager.h>
#include <common/FlagManager.h>
#include <common/trace.h>
+#include <fmt/core.h>
#include <log/log.h>
#include <aidl/android/hardware/graphics/composer3/BnComposerCallback.h>
#include <algorithm>
#include <cinttypes>
+#include <string>
+#include <string_view>
#include "HWC2.h"
namespace android {
-using hardware::hidl_handle;
-using hardware::hidl_vec;
-using hardware::Return;
-
using aidl::android::hardware::graphics::composer3::BnComposerCallback;
using aidl::android::hardware::graphics::composer3::Capability;
using aidl::android::hardware::graphics::composer3::ClientTargetPropertyWithBrightness;
-using aidl::android::hardware::graphics::composer3::Lut;
+using aidl::android::hardware::graphics::composer3::CommandResultPayload;
+using aidl::android::hardware::graphics::composer3::Luts;
using aidl::android::hardware::graphics::composer3::PowerMode;
using aidl::android::hardware::graphics::composer3::VirtualDisplay;
-using aidl::android::hardware::graphics::composer3::CommandResultPayload;
-
using AidlColorMode = aidl::android::hardware::graphics::composer3::ColorMode;
using AidlContentType = aidl::android::hardware::graphics::composer3::ContentType;
using AidlDisplayIdentification =
@@ -234,25 +232,32 @@
HWC2::ComposerCallback& mCallback;
};
-std::string AidlComposer::instance(const std::string& serviceName) {
- return std::string(AidlIComposer::descriptor) + "/" + serviceName;
+std::string AidlComposer::ensureFullyQualifiedName(std::string_view serviceName) {
+ if (!serviceName.starts_with(AidlIComposer::descriptor)) {
+ return fmt::format("{}/{}", AidlIComposer::descriptor, serviceName);
+ } else {
+ return std::string{serviceName};
+ }
}
-bool AidlComposer::isDeclared(const std::string& serviceName) {
- return AServiceManager_isDeclared(instance(serviceName).c_str());
+bool AidlComposer::namesAnAidlComposerService(std::string_view serviceName) {
+ if (!serviceName.starts_with(AidlIComposer::descriptor)) {
+ return AServiceManager_isDeclared(ensureFullyQualifiedName(serviceName).c_str());
+ }
+ return true;
}
AidlComposer::AidlComposer(const std::string& serviceName) {
// This only waits if the service is actually declared
- mAidlComposer = AidlIComposer::fromBinder(
- ndk::SpAIBinder(AServiceManager_waitForService(instance(serviceName).c_str())));
+ mAidlComposer = AidlIComposer::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService(ensureFullyQualifiedName(serviceName).c_str())));
if (!mAidlComposer) {
LOG_ALWAYS_FATAL("Failed to get AIDL composer service");
return;
}
if (!mAidlComposer->createClient(&mAidlComposerClient).isOk()) {
- LOG_ALWAYS_FATAL("Can't create AidlComposerClient, fallback to HIDL");
+ LOG_ALWAYS_FATAL("Can't create AidlComposerClient");
return;
}
@@ -352,7 +357,9 @@
mAidlComposerCallback = ndk::SharedRefBase::make<AidlIComposerCallbackWrapper>(callback);
ndk::SpAIBinder binder = mAidlComposerCallback->asBinder();
- AIBinder_setMinSchedulerPolicy(binder.get(), SCHED_FIFO, 2);
+ if (!FlagManager::getInstance().disable_sched_fifo_composer_callback()) {
+ AIBinder_setMinSchedulerPolicy(binder.get(), SCHED_FIFO, 2);
+ }
const auto status = mAidlComposerClient->registerCallback(mAidlComposerCallback);
if (!status.isOk()) {
@@ -525,11 +532,15 @@
Error AidlComposer::getDisplayAttribute(Display display, Config config,
IComposerClient::Attribute attribute, int32_t* outValue) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
const auto status =
mAidlComposerClient->getDisplayAttribute(translate<int64_t>(display),
translate<int32_t>(config),
static_cast<AidlDisplayAttribute>(attribute),
outValue);
+#pragma clang diagnostic pop
+
if (!status.isOk()) {
ALOGE("getDisplayAttribute failed %s", status.getDescription().c_str());
return static_cast<Error>(status.getServiceSpecificError());
@@ -539,8 +550,13 @@
Error AidlComposer::getDisplayConfigs(Display display, std::vector<Config>* outConfigs) {
std::vector<int32_t> configs;
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
const auto status =
mAidlComposerClient->getDisplayConfigs(translate<int64_t>(display), &configs);
+#pragma clang diagnostic pop
+
if (!status.isOk()) {
ALOGE("getDisplayConfigs failed %s", status.getDescription().c_str());
return static_cast<Error>(status.getServiceSpecificError());
@@ -682,6 +698,36 @@
return error;
}
+Error AidlComposer::getLayerPresentFences(Display display, std::vector<Layer>* outLayers,
+ std::vector<int>* outFences,
+ std::vector<int64_t>* outLatenciesNanos) {
+ Error error = Error::NONE;
+ std::vector<PresentFence::LayerPresentFence> fences;
+ {
+ mMutex.lock_shared();
+ if (auto reader = getReader(display)) {
+ fences = reader->get().takeLayerPresentFences(translate<int64_t>(display));
+ } else {
+ error = Error::BAD_DISPLAY;
+ }
+ mMutex.unlock_shared();
+ }
+
+ outLayers->reserve(fences.size());
+ outFences->reserve(fences.size());
+ outLatenciesNanos->reserve(fences.size());
+
+ for (auto& fence : fences) {
+ outLayers->emplace_back(translate<Layer>(fence.layer));
+ // take ownership
+ const int fenceOwner = fence.bufferFence.get();
+ *fence.bufferFence.getR() = -1;
+ outFences->emplace_back(fenceOwner);
+ outLatenciesNanos->emplace_back(fence.bufferLatencyNanos);
+ }
+ return error;
+}
+
Error AidlComposer::presentDisplay(Display display, int* outPresentFence) {
const auto displayId = translate<int64_t>(display);
SFTRACE_FORMAT("HwcPresentDisplay %" PRId64, displayId);
@@ -1385,7 +1431,7 @@
return V2_4::Error::NONE;
}
-V2_4::Error AidlComposer::setActiveConfigWithConstraints(
+Error AidlComposer::setActiveConfigWithConstraints(
Display display, Config config,
const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
VsyncPeriodChangeTimeline* outTimeline) {
@@ -1399,10 +1445,10 @@
&timeline);
if (!status.isOk()) {
ALOGE("setActiveConfigWithConstraints failed %s", status.getDescription().c_str());
- return static_cast<V2_4::Error>(status.getServiceSpecificError());
+ return static_cast<Error>(status.getServiceSpecificError());
}
*outTimeline = translate<VsyncPeriodChangeTimeline>(timeline);
- return V2_4::Error::NONE;
+ return Error::NONE;
}
V2_4::Error AidlComposer::setAutoLowLatencyMode(Display display, bool on) {
@@ -1565,7 +1611,7 @@
return error;
}
-Error AidlComposer::setLayerLuts(Display display, Layer layer, std::vector<Lut>& luts) {
+Error AidlComposer::setLayerLuts(Display display, Layer layer, Luts& luts) {
Error error = Error::NONE;
mMutex.lock_shared();
if (auto writer = getWriter(display)) {
@@ -1639,6 +1685,64 @@
return Error::NONE;
}
+Error AidlComposer::getMaxLayerPictureProfiles(Display display, int32_t* outMaxProfiles) {
+ const auto status = mAidlComposerClient->getMaxLayerPictureProfiles(translate<int64_t>(display),
+ outMaxProfiles);
+ if (!status.isOk()) {
+ ALOGE("getMaxLayerPictureProfiles failed %s", status.getDescription().c_str());
+ return static_cast<Error>(status.getServiceSpecificError());
+ }
+ return Error::NONE;
+}
+
+Error AidlComposer::setDisplayPictureProfileId(Display display, PictureProfileId id) {
+ Error error = Error::NONE;
+ mMutex.lock_shared();
+ if (auto writer = getWriter(display)) {
+ writer->get().setDisplayPictureProfileId(translate<int64_t>(display), id);
+ } else {
+ error = Error::BAD_DISPLAY;
+ }
+ mMutex.unlock_shared();
+ return error;
+}
+
+Error AidlComposer::setLayerPictureProfileId(Display display, Layer layer, PictureProfileId id) {
+ Error error = Error::NONE;
+ mMutex.lock_shared();
+ if (auto writer = getWriter(display)) {
+ writer->get().setLayerPictureProfileId(translate<int64_t>(display),
+ translate<int64_t>(layer), id);
+ } else {
+ error = Error::BAD_DISPLAY;
+ }
+ mMutex.unlock_shared();
+ return error;
+}
+
+Error AidlComposer::getLuts(Display display, const std::vector<sp<GraphicBuffer>>& buffers,
+ std::vector<aidl::android::hardware::graphics::composer3::Luts>* luts) {
+ std::vector<aidl::android::hardware::graphics::composer3::Buffer> aidlBuffers;
+ aidlBuffers.reserve(buffers.size());
+
+ for (auto& buffer : buffers) {
+ if (buffer.get()) {
+ aidl::android::hardware::graphics::composer3::Buffer aidlBuffer;
+ aidlBuffer.handle.emplace(::android::dupToAidl(buffer->getNativeBuffer()->handle));
+ aidlBuffers.emplace_back(std::move(aidlBuffer));
+ }
+ }
+
+ const auto status =
+ mAidlComposerClient->getLuts(translate<int64_t>(display), aidlBuffers, luts);
+ if (!status.isOk()) {
+ ALOGE("getLuts failed %s", status.getDescription().c_str());
+ return static_cast<Error>(status.getServiceSpecificError());
+ }
+
+ return Error::NONE;
+}
+
ftl::Optional<std::reference_wrapper<ComposerClientWriter>> AidlComposer::getWriter(Display display)
REQUIRES_SHARED(mMutex) {
return mWriters.get(display);
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
index cdb67e4..5fcc8b0 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
@@ -24,14 +24,9 @@
#include <functional>
#include <optional>
#include <string>
-#include <utility>
+#include <string_view>
#include <vector>
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-#pragma clang diagnostic ignored "-Wextra"
-
#include <android/hardware/graphics/composer/2.4/IComposer.h>
#include <android/hardware/graphics/composer/2.4/IComposerClient.h>
@@ -43,9 +38,6 @@
#include <aidl/android/hardware/graphics/composer3/Composition.h>
#include <aidl/android/hardware/graphics/composer3/DisplayCapability.h>
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
-
namespace android::Hwc2 {
using aidl::android::hardware::graphics::common::DisplayDecorationSupport;
@@ -53,6 +45,7 @@
using aidl::android::hardware::graphics::common::HdrConversionStrategy;
using aidl::android::hardware::graphics::composer3::ComposerClientReader;
using aidl::android::hardware::graphics::composer3::ComposerClientWriter;
+using aidl::android::hardware::graphics::composer3::Luts;
using aidl::android::hardware::graphics::composer3::OverlayProperties;
class AidlIComposerCallbackWrapper;
@@ -60,7 +53,8 @@
// Composer is a wrapper to IComposer, a proxy to server-side composer.
class AidlComposer final : public Hwc2::Composer {
public:
- static bool isDeclared(const std::string& serviceName);
+ // Returns true if serviceName appears to be something that is meant to be used by AidlComposer.
+ static bool namesAnAidlComposerService(std::string_view serviceName);
explicit AidlComposer(const std::string& serviceName);
~AidlComposer() override;
@@ -113,6 +107,10 @@
Error getReleaseFences(Display display, std::vector<Layer>* outLayers,
std::vector<int>* outReleaseFences) override;
+ Error getLayerPresentFences(Display display, std::vector<Layer>* outLayers,
+ std::vector<int>* outFences,
+ std::vector<int64_t>* outLatenciesNanos) override;
+
Error presentDisplay(Display display, int* outPresentFence) override;
Error setActiveConfig(Display display, Config config) override;
@@ -205,7 +203,7 @@
V2_4::Error getDisplayConnectionType(Display display,
IComposerClient::DisplayConnectionType* outType) override;
V2_4::Error getDisplayVsyncPeriod(Display display, VsyncPeriodNanos* outVsyncPeriod) override;
- V2_4::Error setActiveConfigWithConstraints(
+ Error setActiveConfigWithConstraints(
Display display, Config config,
const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
VsyncPeriodChangeTimeline* outTimeline) override;
@@ -248,9 +246,12 @@
Display display, std::vector<Layer>* outLayers,
std::vector<aidl::android::hardware::graphics::composer3::DisplayLuts::LayerLut>*
outLuts) override;
- Error setLayerLuts(
- Display display, Layer layer,
- std::vector<aidl::android::hardware::graphics::composer3::Lut>& luts) override;
+ Error setLayerLuts(Display display, Layer layer, Luts& luts) override;
+ Error getMaxLayerPictureProfiles(Display, int32_t* outMaxProfiles) override;
+ Error setDisplayPictureProfileId(Display, PictureProfileId id) override;
+ Error setLayerPictureProfileId(Display, Layer, PictureProfileId id) override;
+ Error getLuts(Display, const std::vector<sp<GraphicBuffer>>&,
+ std::vector<aidl::android::hardware::graphics::composer3::Luts>*) override;
private:
// Many public functions above simply write a command into the command
@@ -258,8 +259,8 @@
// this function to execute the command queue.
Error execute(Display) REQUIRES_SHARED(mMutex);
- // returns the default instance name for the given service
- static std::string instance(const std::string& serviceName);
+ // Ensures serviceName is fully qualified.
+ static std::string ensureFullyQualifiedName(std::string_view serviceName);
ftl::Optional<std::reference_wrapper<ComposerClientWriter>> getWriter(Display)
REQUIRES_SHARED(mMutex);
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index d69a923..1e4132c 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -26,7 +26,7 @@
Composer::~Composer() = default;
std::unique_ptr<Composer> Composer::create(const std::string& serviceName) {
- if (AidlComposer::isDeclared(serviceName)) {
+ if (AidlComposer::namesAnAidlComposerService(serviceName)) {
return std::make_unique<AidlComposer>(serviceName);
}
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 0905663..018ee6e 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -29,11 +29,15 @@
#include <math/mat4.h>
#include <ui/DisplayedFrameStats.h>
#include <ui/GraphicBuffer.h>
+#include <ui/PictureProfileHandle.h>
#include <utils/StrongPointer.h>
+#include "DisplayHardware/Hal.h"
+
#include <aidl/android/hardware/graphics/common/DisplayDecorationSupport.h>
#include <aidl/android/hardware/graphics/common/HdrConversionCapability.h>
#include <aidl/android/hardware/graphics/common/HdrConversionStrategy.h>
+#include <aidl/android/hardware/graphics/common/Transform.h>
#include <aidl/android/hardware/graphics/composer3/Capability.h>
#include <aidl/android/hardware/graphics/composer3/ClientTargetPropertyWithBrightness.h>
#include <aidl/android/hardware/graphics/composer3/Color.h>
@@ -42,10 +46,9 @@
#include <aidl/android/hardware/graphics/composer3/DisplayConfiguration.h>
#include <aidl/android/hardware/graphics/composer3/DisplayLuts.h>
#include <aidl/android/hardware/graphics/composer3/IComposerCallback.h>
-#include <aidl/android/hardware/graphics/composer3/Lut.h>
+#include <aidl/android/hardware/graphics/composer3/Luts.h>
#include <aidl/android/hardware/graphics/composer3/OverlayProperties.h>
-#include <aidl/android/hardware/graphics/common/Transform.h>
#include <optional>
// TODO(b/129481165): remove the #pragma below and fix conversion issues
@@ -73,9 +76,9 @@
using types::V1_2::Dataspace;
using types::V1_2::PixelFormat;
+using hardware::graphics::composer::hal::Error;
using V2_1::Config;
using V2_1::Display;
-using V2_1::Error;
using V2_1::Layer;
using V2_4::CommandReaderBase;
using V2_4::CommandWriterBase;
@@ -154,6 +157,10 @@
virtual Error getReleaseFences(Display display, std::vector<Layer>* outLayers,
std::vector<int>* outReleaseFences) = 0;
+ virtual Error getLayerPresentFences(Display display, std::vector<Layer>* outLayers,
+ std::vector<int>* outFences,
+ std::vector<int64_t>* outLatenciesNanos) = 0;
+
virtual Error presentDisplay(Display display, int* outPresentFence) = 0;
virtual Error setActiveConfig(Display display, Config config) = 0;
@@ -261,7 +268,7 @@
Display display, IComposerClient::DisplayConnectionType* outType) = 0;
virtual V2_4::Error getDisplayVsyncPeriod(Display display,
VsyncPeriodNanos* outVsyncPeriod) = 0;
- virtual V2_4::Error setActiveConfigWithConstraints(
+ virtual Error setActiveConfigWithConstraints(
Display display, Config config,
const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
VsyncPeriodChangeTimeline* outTimeline) = 0;
@@ -307,7 +314,12 @@
int32_t frameIntervalNs) = 0;
virtual Error getRequestedLuts(Display display, std::vector<Layer>* outLayers,
std::vector<V3_0::DisplayLuts::LayerLut>* outLuts) = 0;
- virtual Error setLayerLuts(Display display, Layer layer, std::vector<V3_0::Lut>& luts) = 0;
+ virtual Error setLayerLuts(Display display, Layer layer, V3_0::Luts& luts) = 0;
+ virtual Error getMaxLayerPictureProfiles(Display display, int32_t* outMaxProfiles) = 0;
+ virtual Error setDisplayPictureProfileId(Display display, PictureProfileId id) = 0;
+ virtual Error setLayerPictureProfileId(Display display, Layer layer, PictureProfileId id) = 0;
+ virtual Error getLuts(Display display, const std::vector<sp<GraphicBuffer>>&,
+ std::vector<V3_0::Luts>*) = 0;
};
} // namespace Hwc2
diff --git a/services/surfaceflinger/DisplayHardware/DisplayMode.h b/services/surfaceflinger/DisplayHardware/DisplayMode.h
index 224f50e..e90b5b7 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayMode.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayMode.h
@@ -31,10 +31,11 @@
#include <common/FlagManager.h>
#include <scheduler/Fps.h>
-#include "DisplayHardware/Hal.h"
+#include "Hal.h"
namespace android {
+using aidl::android::hardware::graphics::composer3::OutputType;
namespace hal = android::hardware::graphics::composer::hal;
class DisplayMode;
@@ -114,6 +115,11 @@
return *this;
}
+ Builder& setHdrOutputType(OutputType type) {
+ mDisplayMode->mHdrOutputType = type;
+ return *this;
+ }
+
private:
float getDefaultDensity() {
// Default density is based on TVs: 1080p displays get XHIGH density, lower-
@@ -166,6 +172,8 @@
// without visual interruptions such as a black screen.
int32_t getGroup() const { return mGroup; }
+ OutputType getHdrOutputType() const { return mHdrOutputType; }
+
private:
explicit DisplayMode(hal::HWConfigId id) : mHwcId(id) {}
@@ -179,21 +187,25 @@
Dpi mDpi;
int32_t mGroup = -1;
std::optional<hal::VrrConfig> mVrrConfig;
+ OutputType mHdrOutputType;
};
inline bool equalsExceptDisplayModeId(const DisplayMode& lhs, const DisplayMode& rhs) {
return lhs.getHwcId() == rhs.getHwcId() && lhs.getResolution() == rhs.getResolution() &&
lhs.getVsyncRate().getPeriodNsecs() == rhs.getVsyncRate().getPeriodNsecs() &&
- lhs.getDpi() == rhs.getDpi() && lhs.getGroup() == rhs.getGroup();
+ lhs.getDpi() == rhs.getDpi() && lhs.getGroup() == rhs.getGroup() &&
+ lhs.getVrrConfig() == rhs.getVrrConfig() &&
+ lhs.getHdrOutputType() == rhs.getHdrOutputType();
}
inline std::string to_string(const DisplayMode& mode) {
return base::StringPrintf("{id=%d, hwcId=%d, resolution=%dx%d, vsyncRate=%s, "
- "dpi=%.2fx%.2f, group=%d, vrrConfig=%s}",
+ "dpi=%.2fx%.2f, group=%d, vrrConfig=%s, supportedHdrTypes=%s}",
ftl::to_underlying(mode.getId()), mode.getHwcId(), mode.getWidth(),
mode.getHeight(), to_string(mode.getVsyncRate()).c_str(),
mode.getDpi().x, mode.getDpi().y, mode.getGroup(),
- to_string(mode.getVrrConfig()).c_str());
+ to_string(mode.getVrrConfig()).c_str(),
+ toString(mode.getHdrOutputType()).c_str());
}
template <typename... DisplayModePtrs>
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 1df2ab1..01f382f 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -31,6 +31,9 @@
#include <ui/Fence.h>
#include <ui/FloatRect.h>
#include <ui/GraphicBuffer.h>
+#include <ui/PictureProfileHandle.h>
+
+#include "DisplayHardware/Hal.h"
#include <algorithm>
#include <cinttypes>
@@ -42,7 +45,8 @@
using AidlCapability = aidl::android::hardware::graphics::composer3::Capability;
using aidl::android::hardware::graphics::composer3::DisplayCapability;
using aidl::android::hardware::graphics::composer3::DisplayLuts;
-using aidl::android::hardware::graphics::composer3::Lut;
+using aidl::android::hardware::graphics::composer3::LutProperties;
+using aidl::android::hardware::graphics::composer3::Luts;
using aidl::android::hardware::graphics::composer3::OverlayProperties;
namespace android {
@@ -52,6 +56,7 @@
using android::GraphicBuffer;
using android::HdrCapabilities;
using android::HdrMetadata;
+using android::PictureProfileHandle;
using android::Rect;
using android::Region;
using android::sp;
@@ -624,10 +629,26 @@
auto layer = getLayerById(layerIds[i]);
if (layer) {
auto& layerLut = tmpLuts[i];
- outLuts->emplace_or_replace(layer.get(), layerLut.lut.lutProperties);
- lutFileDescriptorMapper.emplace_or_replace(layer.get(),
- ndk::ScopedFileDescriptor(
- layerLut.lut.pfd.release()));
+ if (layerLut.luts.pfd.get() >= 0 && layerLut.luts.offsets.has_value()) {
+ const auto& offsets = layerLut.luts.offsets.value();
+ std::vector<std::pair<int32_t, LutProperties>> lutOffsetsAndProperties;
+ lutOffsetsAndProperties.reserve(offsets.size());
+ std::transform(offsets.begin(), offsets.end(), layerLut.luts.lutProperties.begin(),
+ std::back_inserter(lutOffsetsAndProperties),
+ [](int32_t i, LutProperties j) { return std::make_pair(i, j); });
+ outLuts->emplace_or_replace(layer.get(), lutOffsetsAndProperties);
+ lutFileDescriptorMapper.emplace_or_replace(layer.get(),
+ ::android::base::unique_fd(
+ layerLut.luts.pfd.release()));
+ } else {
+ ALOGE("getRequestedLuts: invalid luts on layer %" PRIu64 " found"
+ " on display %" PRIu64 ". pfd.get()=%d, offsets.has_value()=%d",
+ layerIds[i], mId, layerLut.luts.pfd.get(), layerLut.luts.offsets.has_value());
+ }
+ } else {
+ ALOGE("getRequestedLuts: invalid layer %" PRIu64 " found"
+ " on display %" PRIu64,
+ layerIds[i], mId);
}
}
@@ -646,6 +667,22 @@
return static_cast<Error>(error);
}
+Error Display::getMaxLayerPictureProfiles(int32_t* outMaxProfiles) {
+ const auto error = mComposer.getMaxLayerPictureProfiles(mId, outMaxProfiles);
+ return static_cast<Error>(error);
+}
+
+Error Display::setPictureProfileHandle(const PictureProfileHandle& handle) {
+ const auto error = mComposer.setDisplayPictureProfileId(mId, handle.getId());
+ return static_cast<Error>(error);
+}
+
+Error Display::getLuts(const std::vector<sp<GraphicBuffer>>& buffers,
+ std::vector<aidl::android::hardware::graphics::composer3::Luts>* outLuts) {
+ const auto error = mComposer.getLuts(mId, buffers, outLuts);
+ return static_cast<Error>(error);
+}
+
// For use by Device
void Display::setConnected(bool connected) {
@@ -1069,7 +1106,7 @@
return static_cast<Error>(intError);
}
-Error Layer::setLuts(std::vector<Lut>& luts) {
+Error Layer::setLuts(aidl::android::hardware::graphics::composer3::Luts& luts) {
if (CC_UNLIKELY(!mDisplay)) {
return Error::BAD_DISPLAY;
}
@@ -1077,6 +1114,15 @@
return static_cast<Error>(intError);
}
+Error Layer::setPictureProfileHandle(const PictureProfileHandle& handle) {
+ if (CC_UNLIKELY(!mDisplay)) {
+ return Error::BAD_DISPLAY;
+ }
+ const auto intError =
+ mComposer.setLayerPictureProfileId(mDisplay->getId(), mId, handle.getId());
+ return static_cast<Error>(intError);
+}
+
} // namespace impl
} // namespace HWC2
} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 61f92f4..7c1f8e3 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -24,6 +24,7 @@
#include <gui/HdrMetadata.h>
#include <math/mat4.h>
#include <ui/HdrCapabilities.h>
+#include <ui/PictureProfileHandle.h>
#include <ui/Region.h>
#include <ui/StaticDisplayInfo.h>
#include <utils/Log.h>
@@ -46,7 +47,7 @@
#include <aidl/android/hardware/graphics/composer3/Color.h>
#include <aidl/android/hardware/graphics/composer3/Composition.h>
#include <aidl/android/hardware/graphics/composer3/DisplayCapability.h>
-#include <aidl/android/hardware/graphics/composer3/Lut.h>
+#include <aidl/android/hardware/graphics/composer3/Luts.h>
#include <aidl/android/hardware/graphics/composer3/OverlayProperties.h>
#include <aidl/android/hardware/graphics/composer3/RefreshRateChangedDebugData.h>
@@ -109,11 +110,12 @@
virtual std::optional<ui::Size> getPhysicalSizeInMm() const = 0;
static const int kLutFileDescriptorMapperSize = 20;
+ using LutOffsetAndProperties = std::vector<
+ std::pair<int32_t, aidl::android::hardware::graphics::composer3::LutProperties>>;
using LayerLuts =
- ftl::SmallMap<HWC2::Layer*, aidl::android::hardware::graphics::composer3::LutProperties,
- kLutFileDescriptorMapperSize>;
+ ftl::SmallMap<HWC2::Layer*, LutOffsetAndProperties, kLutFileDescriptorMapperSize>;
using LutFileDescriptorMapper =
- ftl::SmallMap<HWC2::Layer*, ndk::ScopedFileDescriptor, kLutFileDescriptorMapperSize>;
+ ftl::SmallMap<HWC2::Layer*, ::android::base::unique_fd, kLutFileDescriptorMapperSize>;
[[nodiscard]] virtual hal::Error acceptChanges() = 0;
[[nodiscard]] virtual base::expected<std::shared_ptr<HWC2::Layer>, hal::Error>
@@ -198,6 +200,12 @@
[[nodiscard]] virtual hal::Error setIdleTimerEnabled(std::chrono::milliseconds timeout) = 0;
[[nodiscard]] virtual hal::Error getPhysicalDisplayOrientation(
Hwc2::AidlTransform* outTransform) const = 0;
+ [[nodiscard]] virtual hal::Error getMaxLayerPictureProfiles(int32_t* maxProfiles) = 0;
+ [[nodiscard]] virtual hal::Error setPictureProfileHandle(
+ const PictureProfileHandle& handle) = 0;
+ [[nodiscard]] virtual hal::Error getLuts(
+ const std::vector<android::sp<android::GraphicBuffer>>&,
+ std::vector<aidl::android::hardware::graphics::composer3::Luts>*) = 0;
};
namespace impl {
@@ -281,6 +289,10 @@
std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
support) override;
hal::Error setIdleTimerEnabled(std::chrono::milliseconds timeout) override;
+ hal::Error getMaxLayerPictureProfiles(int32_t* maxProfiles) override;
+ hal::Error setPictureProfileHandle(const android::PictureProfileHandle& handle) override;
+ hal::Error getLuts(const std::vector<android::sp<android::GraphicBuffer>>&,
+ std::vector<aidl::android::hardware::graphics::composer3::Luts>*) override;
// Other Display methods
hal::HWDisplayId getId() const override { return mId; }
@@ -375,7 +387,9 @@
[[nodiscard]] virtual hal::Error setBrightness(float brightness) = 0;
[[nodiscard]] virtual hal::Error setBlockingRegion(const android::Region& region) = 0;
[[nodiscard]] virtual hal::Error setLuts(
- std::vector<aidl::android::hardware::graphics::composer3::Lut>& luts) = 0;
+ aidl::android::hardware::graphics::composer3::Luts& luts) = 0;
+ [[nodiscard]] virtual hal::Error setPictureProfileHandle(
+ const PictureProfileHandle& handle) = 0;
};
namespace impl {
@@ -426,8 +440,8 @@
// AIDL HAL
hal::Error setBrightness(float brightness) override;
hal::Error setBlockingRegion(const android::Region& region) override;
- hal::Error setLuts(
- std::vector<aidl::android::hardware::graphics::composer3::Lut>& luts) override;
+ hal::Error setLuts(aidl::android::hardware::graphics::composer3::Luts&) override;
+ hal::Error setPictureProfileHandle(const PictureProfileHandle& handle) override;
private:
// These are references to data owned by HWComposer, which will outlive
@@ -449,6 +463,7 @@
android::HdrMetadata mHdrMetadata;
android::mat4 mColorMatrix;
uint32_t mBufferSlot;
+ android::PictureProfileHandle profile;
};
} // namespace impl
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index e37c0ba..545ed19 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -27,6 +27,7 @@
#include "HWComposer.h"
+#include <aidl/android/hardware/graphics/composer3/IComposerClient.h>
#include <android-base/properties.h>
#include <common/trace.h>
#include <compositionengine/Output.h>
@@ -137,13 +138,13 @@
}
std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hal::HWDisplayId hwcDisplayId,
- hal::Connection connection) {
- switch (connection) {
- case hal::Connection::CONNECTED:
+ HotplugEvent event) {
+ switch (event) {
+ case HotplugEvent::Connected:
return onHotplugConnect(hwcDisplayId);
- case hal::Connection::DISCONNECTED:
+ case HotplugEvent::Disconnected:
return onHotplugDisconnect(hwcDisplayId);
- case hal::Connection::INVALID:
+ case HotplugEvent::LinkUnstable:
return {};
}
}
@@ -224,7 +225,11 @@
}
void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId, PhysicalDisplayId displayId,
- std::optional<ui::Size> physicalSize) {
+ uint8_t port, std::optional<ui::Size> physicalSize) {
+ LOG_ALWAYS_FATAL_IF(!mActivePorts.try_emplace(port).second,
+ "Cannot attach display %" PRIu64 " to an already active port %" PRIu8 ".",
+ hwcDisplayId, port);
+
mPhysicalDisplayIdMap[hwcDisplayId] = displayId;
if (!mPrimaryHwcDisplayId) {
@@ -238,6 +243,7 @@
newDisplay->setConnected(true);
newDisplay->setPhysicalSizeInMm(physicalSize);
displayData.hwcDisplay = std::move(newDisplay);
+ displayData.port = port;
}
int32_t HWComposer::getAttribute(hal::HWDisplayId hwcDisplayId, hal::HWConfigId configId,
@@ -335,7 +341,8 @@
.height = config.height,
.vsyncPeriod = config.vsyncPeriod,
.configGroup = config.configGroup,
- .vrrConfig = config.vrrConfig};
+ .vrrConfig = config.vrrConfig,
+ .hdrOutputType = config.hdrOutputType};
const DisplayConfiguration::Dpi estimatedDPI =
getEstimatedDotsPerInchFromSize(hwcDisplayId, hwcMode);
@@ -379,7 +386,7 @@
const int32_t dpiX = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_X);
const int32_t dpiY = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_Y);
const DisplayConfiguration::Dpi hwcDpi =
- DisplayConfiguration::Dpi{dpiX == -1 ? dpiY : dpiX / 1000.f,
+ DisplayConfiguration::Dpi{dpiX == -1 ? dpiX : dpiX / 1000.f,
dpiY == -1 ? dpiY : dpiY / 1000.f};
const DisplayConfiguration::Dpi estimatedDPI =
getEstimatedDotsPerInchFromSize(hwcDisplayId, hwcMode);
@@ -733,7 +740,11 @@
auto error = mDisplayData[displayId].hwcDisplay->setActiveConfigWithConstraints(hwcModeId,
constraints,
outTimeline);
- RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
+ if (error == hal::Error::CONFIG_FAILED) {
+ RETURN_IF_HWC_ERROR_FOR("setActiveConfigWithConstraints", error, displayId,
+ FAILED_TRANSACTION);
+ }
+ RETURN_IF_HWC_ERROR_FOR("setActiveConfigWithConstraints", error, displayId, UNKNOWN_ERROR);
return NO_ERROR;
}
@@ -752,6 +763,9 @@
const auto hwcDisplayId = displayData.hwcDisplay->getId();
mPhysicalDisplayIdMap.erase(hwcDisplayId);
+ if (const auto port = displayData.port) {
+ mActivePorts.erase(port.value());
+ }
mDisplayData.erase(displayId);
// Reset the primary display ID if we're disconnecting it.
@@ -1022,11 +1036,39 @@
return NO_ERROR;
}
+int32_t HWComposer::getMaxLayerPictureProfiles(PhysicalDisplayId displayId) {
+ int32_t maxProfiles = 0;
+ RETURN_IF_INVALID_DISPLAY(displayId, 0);
+ const auto error = mDisplayData[displayId].hwcDisplay->getMaxLayerPictureProfiles(&maxProfiles);
+ RETURN_IF_HWC_ERROR(error, displayId, 0);
+ return maxProfiles;
+}
+
+status_t HWComposer::setDisplayPictureProfileHandle(PhysicalDisplayId displayId,
+ const PictureProfileHandle& handle) {
+ RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
+ const auto error = mDisplayData[displayId].hwcDisplay->setPictureProfileHandle(handle);
+ if (error != hal::Error::UNSUPPORTED) {
+ RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
+ }
+ return NO_ERROR;
+}
+
+status_t HWComposer::getLuts(
+ PhysicalDisplayId displayId, const std::vector<sp<GraphicBuffer>>& buffers,
+ std::vector<aidl::android::hardware::graphics::composer3::Luts>* luts) {
+ RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
+ auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
+ auto error = hwcDisplay->getLuts(buffers, luts);
+ RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
+ return NO_ERROR;
+}
+
const std::unordered_map<std::string, bool>& HWComposer::getSupportedLayerGenericMetadata() const {
return mSupportedLayerGenericMetadata;
}
-ftl::SmallMap<HWC2::Layer*, ndk::ScopedFileDescriptor, 20>&
+ftl::SmallMap<HWC2::Layer*, ::android::base::unique_fd, 20>&
HWComposer::getLutFileDescriptorMapper() {
return mLutFileDescriptorMapper;
}
@@ -1089,8 +1131,15 @@
return {};
}
-bool HWComposer::shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId,
+bool HWComposer::shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId, uint8_t port,
bool hasDisplayIdentificationData) const {
+ if (mActivePorts.contains(port)) {
+ ALOGE("Ignoring connection of display %" PRIu64 ". Port %" PRIu8
+ " is already in active use.",
+ hwcDisplayId, port);
+ return true;
+ }
+
if (mHasMultiDisplaySupport && !hasDisplayIdentificationData) {
ALOGE("Ignoring connection of display %" PRIu64 " without identification data",
hwcDisplayId);
@@ -1136,7 +1185,7 @@
mHasMultiDisplaySupport ? "generalized" : "legacy");
}
- if (shouldIgnoreHotplugConnect(hwcDisplayId, hasDisplayIdentificationData)) {
+ if (shouldIgnoreHotplugConnect(hwcDisplayId, port, hasDisplayIdentificationData)) {
return {};
}
@@ -1156,6 +1205,7 @@
return DisplayIdentificationInfo{.id = PhysicalDisplayId::fromPort(port),
.name = isPrimary ? "Primary display"
: "Secondary display",
+ .port = port,
.deviceProductInfo = std::nullopt};
}();
@@ -1167,7 +1217,7 @@
if (info->preferredDetailedTimingDescriptor) {
size = info->preferredDetailedTimingDescriptor->physicalSizeInMm;
}
- allocatePhysicalDisplay(hwcDisplayId, info->id, size);
+ allocatePhysicalDisplay(hwcDisplayId, info->id, info->port, size);
}
return info;
}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 7b04d67..2c0aa3d 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -28,7 +28,9 @@
#include <ftl/expected.h>
#include <ftl/future.h>
#include <ui/DisplayIdentification.h>
+#include <ui/DisplayMap.h>
#include <ui/FenceTime.h>
+#include <ui/PictureProfileHandle.h>
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic push
@@ -54,6 +56,8 @@
#include <aidl/android/hardware/graphics/composer3/DisplayCapability.h>
#include <aidl/android/hardware/graphics/composer3/DisplayLuts.h>
#include <aidl/android/hardware/graphics/composer3/LutProperties.h>
+#include <aidl/android/hardware/graphics/composer3/Luts.h>
+#include <aidl/android/hardware/graphics/composer3/OutputType.h>
#include <aidl/android/hardware/graphics/composer3/OverlayProperties.h>
namespace android {
@@ -65,6 +69,7 @@
class TestableSurfaceFlinger;
struct HWComposerTest;
struct CompositionInfo;
+class PictureProfileHandle;
namespace Hwc2 {
class Composer;
@@ -110,12 +115,14 @@
float dpiY = -1.f;
int32_t configGroup = -1;
std::optional<hal::VrrConfig> vrrConfig;
+ OutputType hdrOutputType;
friend std::ostream& operator<<(std::ostream& os, const HWCDisplayMode& mode) {
return os << "id=" << mode.hwcId << " res=" << mode.width << "x" << mode.height
<< " vsyncPeriod=" << mode.vsyncPeriod << " dpi=" << mode.dpiX << "x"
<< mode.dpiY << " group=" << mode.configGroup
- << " vrrConfig=" << to_string(mode.vrrConfig).c_str();
+ << " vrrConfig=" << to_string(mode.vrrConfig).c_str()
+ << " hdrOutputType=" << toString(mode.hdrOutputType);
}
};
@@ -138,7 +145,7 @@
// supported by the HWC can be queried in advance, but allocation may fail for other reasons.
virtual bool allocateVirtualDisplay(HalVirtualDisplayId, ui::Size, ui::PixelFormat*) = 0;
- virtual void allocatePhysicalDisplay(hal::HWDisplayId, PhysicalDisplayId,
+ virtual void allocatePhysicalDisplay(hal::HWDisplayId, PhysicalDisplayId, uint8_t port,
std::optional<ui::Size> physicalSize) = 0;
// Attempts to create a new layer on this display
@@ -225,11 +232,12 @@
// Events handling ---------------------------------------------------------
- // Returns stable display ID (and display name on connection of new or previously disconnected
- // display), or std::nullopt if hotplug event was ignored.
+ enum class HotplugEvent { Connected, Disconnected, LinkUnstable };
+
+ // Returns the stable display ID of the display for which the hotplug event was received, or
+ // std::nullopt if hotplug event was ignored.
// This function is called from SurfaceFlinger.
- virtual std::optional<DisplayIdentificationInfo> onHotplug(hal::HWDisplayId,
- hal::Connection) = 0;
+ virtual std::optional<DisplayIdentificationInfo> onHotplug(hal::HWDisplayId, HotplugEvent) = 0;
// If true we'll update the DeviceProductInfo on subsequent hotplug connected events.
// TODO(b/157555476): Remove when the framework has proper support for headless mode
@@ -296,7 +304,7 @@
virtual std::optional<PhysicalDisplayId> toPhysicalDisplayId(hal::HWDisplayId) const = 0;
virtual std::optional<hal::HWDisplayId> fromPhysicalDisplayId(PhysicalDisplayId) const = 0;
- // Composer 3.0
+ // AIDL Composer
virtual status_t setBootDisplayMode(PhysicalDisplayId, hal::HWConfigId) = 0;
virtual status_t clearBootDisplayMode(PhysicalDisplayId) = 0;
virtual std::optional<hal::HWConfigId> getPreferredBootDisplayMode(PhysicalDisplayId) = 0;
@@ -315,8 +323,12 @@
virtual status_t setRefreshRateChangedCallbackDebugEnabled(PhysicalDisplayId, bool enabled) = 0;
virtual status_t notifyExpectedPresent(PhysicalDisplayId, TimePoint expectedPresentTime,
Fps frameInterval) = 0;
- // mapper
virtual HWC2::Display::LutFileDescriptorMapper& getLutFileDescriptorMapper() = 0;
+ virtual int32_t getMaxLayerPictureProfiles(PhysicalDisplayId) = 0;
+ virtual status_t setDisplayPictureProfileHandle(PhysicalDisplayId,
+ const PictureProfileHandle& handle) = 0;
+ virtual status_t getLuts(PhysicalDisplayId, const std::vector<sp<GraphicBuffer>>&,
+ std::vector<aidl::android::hardware::graphics::composer3::Luts>*) = 0;
};
static inline bool operator==(const android::HWComposer::DeviceRequestedChanges& lhs,
@@ -351,7 +363,7 @@
bool allocateVirtualDisplay(HalVirtualDisplayId, ui::Size, ui::PixelFormat*) override;
// Called from SurfaceFlinger, when the state for a new physical display needs to be recreated.
- void allocatePhysicalDisplay(hal::HWDisplayId, PhysicalDisplayId,
+ void allocatePhysicalDisplay(hal::HWDisplayId, PhysicalDisplayId, uint8_t port,
std::optional<ui::Size> physicalSize) override;
// Attempts to create a new layer on this display
@@ -425,9 +437,7 @@
// Events handling ---------------------------------------------------------
- // Returns PhysicalDisplayId (and display name on connection of new or previously disconnected
- // display), or std::nullopt if hotplug event was ignored.
- std::optional<DisplayIdentificationInfo> onHotplug(hal::HWDisplayId, hal::Connection) override;
+ std::optional<DisplayIdentificationInfo> onHotplug(hal::HWDisplayId, HotplugEvent) override;
bool updatesDeviceProductInfoOnHotplugReconnect() const override;
@@ -480,9 +490,12 @@
status_t setRefreshRateChangedCallbackDebugEnabled(PhysicalDisplayId, bool enabled) override;
status_t notifyExpectedPresent(PhysicalDisplayId, TimePoint expectedPresentTime,
Fps frameInterval) override;
-
- // get a mapper
HWC2::Display::LutFileDescriptorMapper& getLutFileDescriptorMapper() override;
+ int32_t getMaxLayerPictureProfiles(PhysicalDisplayId) override;
+ status_t setDisplayPictureProfileHandle(PhysicalDisplayId,
+ const android::PictureProfileHandle& profile) override;
+ status_t getLuts(PhysicalDisplayId, const std::vector<sp<GraphicBuffer>>&,
+ std::vector<aidl::android::hardware::graphics::composer3::Luts>*) override;
// for debugging ----------------------------------------------------------
void dump(std::string& out) const override;
@@ -513,6 +526,7 @@
struct DisplayData {
std::unique_ptr<HWC2::Display> hwcDisplay;
+ std::optional<uint8_t> port; // Set on hotplug for physical displays
sp<Fence> lastPresentFence = Fence::NO_FENCE; // signals when the last set op retires
nsecs_t lastPresentTimestamp = 0;
@@ -530,7 +544,8 @@
std::optional<DisplayIdentificationInfo> onHotplugConnect(hal::HWDisplayId);
std::optional<DisplayIdentificationInfo> onHotplugDisconnect(hal::HWDisplayId);
- bool shouldIgnoreHotplugConnect(hal::HWDisplayId, bool hasDisplayIdentificationData) const;
+ bool shouldIgnoreHotplugConnect(hal::HWDisplayId, uint8_t port,
+ bool hasDisplayIdentificationData) const;
aidl::android::hardware::graphics::composer3::DisplayConfiguration::Dpi
getEstimatedDotsPerInchFromSize(uint64_t hwcDisplayId, const HWCDisplayMode& hwcMode) const;
@@ -552,6 +567,7 @@
void loadHdrConversionCapabilities();
std::unordered_map<HalDisplayId, DisplayData> mDisplayData;
+ ui::PhysicalDisplaySet<uint8_t> mActivePorts;
std::unique_ptr<android::Hwc2::Composer> mComposer;
std::unordered_set<aidl::android::hardware::graphics::composer3::Capability> mCapabilities;
diff --git a/services/surfaceflinger/DisplayHardware/Hal.h b/services/surfaceflinger/DisplayHardware/Hal.h
index e3d9622..568d758 100644
--- a/services/surfaceflinger/DisplayHardware/Hal.h
+++ b/services/surfaceflinger/DisplayHardware/Hal.h
@@ -17,16 +17,21 @@
#pragma once
#include <android/hardware/graphics/common/1.1/types.h>
+#include <android/hardware/graphics/composer/2.1/types.h>
#include <android/hardware/graphics/composer/2.4/IComposer.h>
#include <android/hardware/graphics/composer/2.4/IComposerClient.h>
+#include <android/hardware/graphics/composer/2.4/types.h>
#include <aidl/android/hardware/graphics/common/DisplayHotplugEvent.h>
#include <aidl/android/hardware/graphics/common/Hdr.h>
#include <aidl/android/hardware/graphics/composer3/Composition.h>
#include <aidl/android/hardware/graphics/composer3/DisplayCapability.h>
#include <aidl/android/hardware/graphics/composer3/DisplayConfiguration.h>
+#include <aidl/android/hardware/graphics/composer3/IComposerClient.h>
#include <aidl/android/hardware/graphics/composer3/VrrConfig.h>
+#include <ftl/enum.h>
+
#define ERROR_HAS_CHANGES 5
namespace android {
@@ -46,7 +51,6 @@
using types::V1_2::Dataspace;
using types::V1_2::PixelFormat;
-using V2_1::Error;
using V2_4::IComposer;
using V2_4::IComposerCallback;
using V2_4::IComposerClient;
@@ -78,6 +82,22 @@
using DisplayConfiguration = V3_0::DisplayConfiguration;
using VrrConfig = V3_0::VrrConfig;
+enum class Error : int32_t {
+ NONE = static_cast<int32_t>(V2_1::Error::NONE),
+ BAD_CONFIG = static_cast<int32_t>(V2_1::Error::BAD_CONFIG),
+ BAD_DISPLAY = static_cast<int32_t>(V2_1::Error::BAD_DISPLAY),
+ BAD_LAYER = static_cast<int32_t>(V2_1::Error::BAD_LAYER),
+ BAD_PARAMETER = static_cast<int32_t>(V2_1::Error::BAD_PARAMETER),
+ NO_RESOURCES = static_cast<int32_t>(V2_1::Error::NO_RESOURCES),
+ NOT_VALIDATED = static_cast<int32_t>(V2_1::Error::NOT_VALIDATED),
+ UNSUPPORTED = static_cast<int32_t>(V2_1::Error::UNSUPPORTED),
+ SEAMLESS_NOT_ALLOWED = static_cast<int32_t>(V2_4::Error::SEAMLESS_NOT_ALLOWED),
+ SEAMLESS_NOT_POSSIBLE = static_cast<int32_t>(V2_4::Error::SEAMLESS_NOT_POSSIBLE),
+ CONFIG_FAILED = V3_0::IComposerClient::EX_CONFIG_FAILED,
+ PICTURE_PROFILE_MAX_EXCEEDED = V3_0::IComposerClient::EX_PICTURE_PROFILE_MAX_EXCEEDED,
+ ftl_last = PICTURE_PROFILE_MAX_EXCEEDED
+};
+
} // namespace hardware::graphics::composer::hal
inline bool hasChangesError(hardware::graphics::composer::hal::Error error) {
@@ -210,7 +230,11 @@
}
inline std::string to_string(hardware::graphics::composer::hal::Error error) {
- return to_string(static_cast<hardware::graphics::composer::hal::V2_4::Error>(error));
+ // 5 is reserved for historical reason, during validation 5 means has changes.
+ if (hasChangesError(error)) {
+ return "HAS_CHANGES";
+ }
+ return ftl::enum_string(error);
}
// For utils::Dumper ADL.
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
index 056ecd7..a010353 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
@@ -27,6 +27,8 @@
#include <SurfaceFlingerProperties.h>
#include <aidl/android/hardware/graphics/common/DisplayHotplugEvent.h>
#include <android/binder_manager.h>
+#include <android/hardware/graphics/composer/2.1/types.h>
+#include <common/FlagManager.h>
#include <common/trace.h>
#include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
#include <hidl/HidlTransportSupport.h>
@@ -47,7 +49,7 @@
using aidl::android::hardware::graphics::composer3::DimmingStage;
using aidl::android::hardware::graphics::composer3::DisplayCapability;
using aidl::android::hardware::graphics::composer3::DisplayLuts;
-using aidl::android::hardware::graphics::composer3::Lut;
+using aidl::android::hardware::graphics::composer3::Luts;
using aidl::android::hardware::graphics::composer3::OverlayProperties;
namespace android {
@@ -173,7 +175,7 @@
};
// assume NO_RESOURCES when Status::isOk returns false
-constexpr Error kDefaultError = Error::NO_RESOURCES;
+constexpr V2_1::Error kDefaultError = V2_1::Error::NO_RESOURCES;
constexpr V2_4::Error kDefaultError_2_4 = static_cast<V2_4::Error>(kDefaultError);
template <typename T, typename U>
@@ -181,7 +183,7 @@
return (ret.isOk()) ? static_cast<T>(ret) : static_cast<T>(default_val);
}
-Error unwrapRet(Return<Error>& ret) {
+V2_1::Error unwrapRet(Return<V2_1::Error>& ret) {
return unwrapRet(ret, kDefaultError);
}
@@ -235,7 +237,7 @@
});
} else if (sp<V2_3::IComposer> composer_2_3 = V2_3::IComposer::castFrom(mComposer)) {
composer_2_3->createClient_2_3([&](const auto& tmpError, const auto& tmpClient) {
- if (tmpError == Error::NONE) {
+ if (tmpError == V2_1::Error::NONE) {
mClient = tmpClient;
mClient_2_2 = tmpClient;
mClient_2_3 = tmpClient;
@@ -243,7 +245,7 @@
});
} else {
mComposer->createClient([&](const auto& tmpError, const auto& tmpClient) {
- if (tmpError != Error::NONE) {
+ if (tmpError != V2_1::Error::NONE) {
return;
}
@@ -300,7 +302,9 @@
}
void HidlComposer::registerCallback(const sp<IComposerCallback>& callback) {
- android::hardware::setMinSchedulerPolicy(callback, SCHED_FIFO, 2);
+ if (!FlagManager::getInstance().disable_sched_fifo_composer_callback()) {
+ android::hardware::setMinSchedulerPolicy(callback, SCHED_FIFO, 2);
+ }
auto ret = [&]() {
if (mClient_2_4) {
@@ -325,14 +329,14 @@
Error HidlComposer::createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format,
Display* outDisplay) {
const uint32_t bufferSlotCount = 1;
- Error error = kDefaultError;
+ Error error = static_cast<Error>(kDefaultError);
if (mClient_2_2) {
mClient_2_2->createVirtualDisplay_2_2(width, height,
static_cast<types::V1_1::PixelFormat>(*format),
bufferSlotCount,
[&](const auto& tmpError, const auto& tmpDisplay,
const auto& tmpFormat) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error != Error::NONE) {
return;
}
@@ -346,7 +350,7 @@
bufferSlotCount,
[&](const auto& tmpError, const auto& tmpDisplay,
const auto& tmpFormat) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error != Error::NONE) {
return;
}
@@ -361,7 +365,7 @@
Error HidlComposer::destroyVirtualDisplay(Display display) {
auto ret = mClient->destroyVirtualDisplay(display);
- return unwrapRet(ret);
+ return static_cast<Error>(unwrapRet(ret));
}
Error HidlComposer::acceptDisplayChanges(Display display) {
@@ -371,10 +375,10 @@
}
Error HidlComposer::createLayer(Display display, Layer* outLayer) {
- Error error = kDefaultError;
+ Error error = static_cast<Error>(kDefaultError);
mClient->createLayer(display, kMaxLayerBufferCount,
[&](const auto& tmpError, const auto& tmpLayer) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error != Error::NONE) {
return;
}
@@ -387,13 +391,13 @@
Error HidlComposer::destroyLayer(Display display, Layer layer) {
auto ret = mClient->destroyLayer(display, layer);
- return unwrapRet(ret);
+ return static_cast<Error>(unwrapRet(ret));
}
Error HidlComposer::getActiveConfig(Display display, Config* outConfig) {
- Error error = kDefaultError;
+ Error error = static_cast<Error>(kDefaultError);
mClient->getActiveConfig(display, [&](const auto& tmpError, const auto& tmpConfig) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error != Error::NONE) {
return;
}
@@ -412,11 +416,11 @@
}
Error HidlComposer::getColorModes(Display display, std::vector<ColorMode>* outModes) {
- Error error = kDefaultError;
+ Error error = static_cast<Error>(kDefaultError);
if (mClient_2_3) {
mClient_2_3->getColorModes_2_3(display, [&](const auto& tmpError, const auto& tmpModes) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error != Error::NONE) {
return;
}
@@ -425,7 +429,7 @@
});
} else if (mClient_2_2) {
mClient_2_2->getColorModes_2_2(display, [&](const auto& tmpError, const auto& tmpModes) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error != Error::NONE) {
return;
}
@@ -436,7 +440,7 @@
});
} else {
mClient->getColorModes(display, [&](const auto& tmpError, const auto& tmpModes) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error != Error::NONE) {
return;
}
@@ -451,7 +455,7 @@
Error HidlComposer::getDisplayAttribute(Display display, Config config,
IComposerClient::Attribute attribute, int32_t* outValue) {
- Error error = kDefaultError;
+ Error error = static_cast<Error>(kDefaultError);
if (mClient_2_4) {
mClient_2_4->getDisplayAttribute_2_4(display, config, attribute,
[&](const auto& tmpError, const auto& tmpValue) {
@@ -466,7 +470,7 @@
mClient->getDisplayAttribute(display, config,
static_cast<V2_1::IComposerClient::Attribute>(attribute),
[&](const auto& tmpError, const auto& tmpValue) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error != Error::NONE) {
return;
}
@@ -479,9 +483,9 @@
}
Error HidlComposer::getDisplayConfigs(Display display, std::vector<Config>* outConfigs) {
- Error error = kDefaultError;
+ Error error = static_cast<Error>(kDefaultError);
mClient->getDisplayConfigs(display, [&](const auto& tmpError, const auto& tmpConfigs) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error != Error::NONE) {
return;
}
@@ -499,9 +503,9 @@
}
Error HidlComposer::getDisplayName(Display display, std::string* outName) {
- Error error = kDefaultError;
+ Error error = static_cast<Error>(kDefaultError);
mClient->getDisplayName(display, [&](const auto& tmpError, const auto& tmpName) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error != Error::NONE) {
return;
}
@@ -520,9 +524,9 @@
}
Error HidlComposer::getDozeSupport(Display display, bool* outSupport) {
- Error error = kDefaultError;
+ Error error = static_cast<Error>(kDefaultError);
mClient->getDozeSupport(display, [&](const auto& tmpError, const auto& tmpSupport) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error != Error::NONE) {
return;
}
@@ -541,14 +545,14 @@
Error HidlComposer::getHdrCapabilities(Display display, std::vector<Hdr>* outHdrTypes,
float* outMaxLuminance, float* outMaxAverageLuminance,
float* outMinLuminance) {
- Error error = kDefaultError;
+ Error error = static_cast<Error>(kDefaultError);
if (mClient_2_3) {
mClient_2_3->getHdrCapabilities_2_3(display,
[&](const auto& tmpError, const auto& tmpHdrTypes,
const auto& tmpMaxLuminance,
const auto& tmpMaxAverageLuminance,
const auto& tmpMinLuminance) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error != Error::NONE) {
return;
}
@@ -564,7 +568,7 @@
const auto& tmpMaxLuminance,
const auto& tmpMaxAverageLuminance,
const auto& tmpMinLuminance) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error != Error::NONE) {
return;
}
@@ -589,6 +593,11 @@
return Error::NONE;
}
+Error HidlComposer::getLayerPresentFences(Display, std::vector<Layer>*, std::vector<int>*,
+ std::vector<int64_t>*) {
+ return Error::UNSUPPORTED;
+}
+
Error HidlComposer::presentDisplay(Display display, int* outPresentFence) {
SFTRACE_NAME("HwcPresentDisplay");
mWriter.selectDisplay(display);
@@ -606,7 +615,7 @@
Error HidlComposer::setActiveConfig(Display display, Config config) {
auto ret = mClient->setActiveConfig(display, config);
- return unwrapRet(ret);
+ return static_cast<Error>(unwrapRet(ret));
}
Error HidlComposer::setClientTarget(Display display, uint32_t slot, const sp<GraphicBuffer>& target,
@@ -625,7 +634,7 @@
}
Error HidlComposer::setColorMode(Display display, ColorMode mode, RenderIntent renderIntent) {
- hardware::Return<Error> ret(kDefaultError);
+ hardware::Return<V2_1::Error> ret(kDefaultError);
if (mClient_2_3) {
ret = mClient_2_3->setColorMode_2_3(display, mode, renderIntent);
} else if (mClient_2_2) {
@@ -634,7 +643,7 @@
} else {
ret = mClient->setColorMode(display, static_cast<types::V1_0::ColorMode>(mode));
}
- return unwrapRet(ret);
+ return static_cast<Error>(unwrapRet(ret));
}
Error HidlComposer::setColorTransform(Display display, const float* matrix) {
@@ -654,25 +663,25 @@
}
Error HidlComposer::setPowerMode(Display display, IComposerClient::PowerMode mode) {
- Return<Error> ret(Error::UNSUPPORTED);
+ Return<V2_1::Error> ret(V2_1::Error::UNSUPPORTED);
if (mClient_2_2) {
ret = mClient_2_2->setPowerMode_2_2(display, mode);
} else if (mode != IComposerClient::PowerMode::ON_SUSPEND) {
ret = mClient->setPowerMode(display, static_cast<V2_1::IComposerClient::PowerMode>(mode));
}
- return unwrapRet(ret);
+ return static_cast<Error>(unwrapRet(ret));
}
Error HidlComposer::setVsyncEnabled(Display display, IComposerClient::Vsync enabled) {
auto ret = mClient->setVsyncEnabled(display, enabled);
- return unwrapRet(ret);
+ return static_cast<Error>(unwrapRet(ret));
}
Error HidlComposer::setClientTargetSlotCount(Display display) {
const uint32_t bufferSlotCount = BufferQueue::NUM_BUFFER_SLOTS;
auto ret = mClient->setClientTargetSlotCount(display, bufferSlotCount);
- return unwrapRet(ret);
+ return static_cast<Error>(unwrapRet(ret));
}
Error HidlComposer::validateDisplay(Display display, nsecs_t /*expectedPresentTime*/,
@@ -903,7 +912,7 @@
// set up new input command queue if necessary
if (queueChanged) {
auto ret = mClient->setInputCommandQueue(*mWriter.getMQDescriptor());
- auto error = unwrapRet(ret);
+ auto error = static_cast<Error>(unwrapRet(ret));
if (error != Error::NONE) {
mWriter.reset();
return error;
@@ -915,17 +924,17 @@
return Error::NONE;
}
- Error error = kDefaultError;
+ Error error = static_cast<Error>(kDefaultError);
hardware::Return<void> ret;
auto hidl_callback = [&](const auto& tmpError, const auto& tmpOutChanged,
const auto& tmpOutLength, const auto& tmpOutHandles) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
// set up new output command queue if necessary
if (error == Error::NONE && tmpOutChanged) {
- error = kDefaultError;
+ error = static_cast<Error>(kDefaultError);
mClient->getOutputCommandQueue([&](const auto& tmpError, const auto& tmpDescriptor) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error != Error::NONE) {
return;
}
@@ -1000,11 +1009,11 @@
return keys;
}
- Error error = kDefaultError;
+ Error error = static_cast<Error>(kDefaultError);
if (mClient_2_3) {
mClient_2_3->getPerFrameMetadataKeys_2_3(display,
[&](const auto& tmpError, const auto& tmpKeys) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error != Error::NONE) {
ALOGW("getPerFrameMetadataKeys failed "
"with %d",
@@ -1016,7 +1025,7 @@
} else {
mClient_2_2
->getPerFrameMetadataKeys(display, [&](const auto& tmpError, const auto& tmpKeys) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error != Error::NONE) {
ALOGW("getPerFrameMetadataKeys failed with %d", tmpError);
return;
@@ -1039,10 +1048,10 @@
return Error::NONE;
}
- Error error = kDefaultError;
+ Error error = static_cast<Error>(kDefaultError);
auto getRenderIntentsLambda = [&](const auto& tmpError, const auto& tmpKeys) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error != Error::NONE) {
return;
}
@@ -1066,10 +1075,10 @@
return Error::NONE;
}
- Error error = kDefaultError;
+ Error error = static_cast<Error>(kDefaultError);
mClient_2_2->getDataspaceSaturationMatrix(static_cast<types::V1_1::Dataspace>(dataspace),
[&](const auto& tmpError, const auto& tmpMatrix) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error != Error::NONE) {
return;
}
@@ -1087,11 +1096,11 @@
return Error::UNSUPPORTED;
}
- Error error = kDefaultError;
+ Error error = static_cast<Error>(kDefaultError);
mClient_2_3->getDisplayIdentificationData(display,
[&](const auto& tmpError, const auto& tmpPort,
const auto& tmpData) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error != Error::NONE) {
return;
}
@@ -1123,13 +1132,13 @@
if (!mClient_2_3) {
return Error::UNSUPPORTED;
}
- Error error = kDefaultError;
+ Error error = static_cast<Error>(kDefaultError);
mClient_2_3->getDisplayedContentSamplingAttributes(display,
[&](const auto tmpError,
const auto& tmpFormat,
const auto& tmpDataspace,
const auto& tmpComponentMask) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error == Error::NONE) {
*outFormat = tmpFormat;
*outDataspace = tmpDataspace;
@@ -1149,8 +1158,9 @@
auto enable = enabled ? V2_3::IComposerClient::DisplayedContentSampling::ENABLE
: V2_3::IComposerClient::DisplayedContentSampling::DISABLE;
- return mClient_2_3->setDisplayedContentSamplingEnabled(display, enable, componentMask,
- maxFrames);
+ auto ret = mClient_2_3->setDisplayedContentSamplingEnabled(display, enable, componentMask,
+ maxFrames);
+ return static_cast<Error>(unwrapRet(ret));
}
Error HidlComposer::getDisplayedContentSample(Display display, uint64_t maxFrames,
@@ -1161,12 +1171,12 @@
if (!mClient_2_3) {
return Error::UNSUPPORTED;
}
- Error error = kDefaultError;
+ Error error = static_cast<Error>(kDefaultError);
mClient_2_3->getDisplayedContentSample(display, maxFrames, timestamp,
[&](const auto tmpError, auto tmpNumFrames,
const auto& tmpSamples0, const auto& tmpSamples1,
const auto& tmpSamples2, const auto& tmpSamples3) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error == Error::NONE) {
outStats->numFrames = tmpNumFrames;
outStats->component_0_sample = tmpSamples0;
@@ -1196,7 +1206,8 @@
if (!mClient_2_3) {
return Error::UNSUPPORTED;
}
- return mClient_2_3->setDisplayBrightness(display, brightness);
+ auto ret = mClient_2_3->setDisplayBrightness(display, brightness);
+ return static_cast<Error>(unwrapRet(ret));
}
// Composer HAL 2.4
@@ -1273,19 +1284,18 @@
return error;
}
-V2_4::Error HidlComposer::setActiveConfigWithConstraints(
+Error HidlComposer::setActiveConfigWithConstraints(
Display display, Config config,
const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
VsyncPeriodChangeTimeline* outTimeline) {
- using Error = V2_4::Error;
if (!mClient_2_4) {
return Error::UNSUPPORTED;
}
- Error error = kDefaultError_2_4;
+ Error error = static_cast<Error>(kDefaultError_2_4);
mClient_2_4->setActiveConfigWithConstraints(display, config, vsyncPeriodChangeConstraints,
[&](const auto& tmpError, const auto& tmpTimeline) {
- error = tmpError;
+ error = static_cast<Error>(tmpError);
if (error != Error::NONE) {
return;
}
@@ -1415,7 +1425,7 @@
return Error::NONE;
}
-Error HidlComposer::setLayerLuts(Display, Layer, std::vector<Lut>&) {
+Error HidlComposer::setLayerLuts(Display, Layer, Luts&) {
return Error::NONE;
}
@@ -1446,6 +1456,23 @@
"OptionalFeature::PhysicalDisplayOrientation is not supported on HIDL");
}
+Error HidlComposer::getMaxLayerPictureProfiles(Display, int32_t*) {
+ return Error::UNSUPPORTED;
+}
+
+Error HidlComposer::getLuts(Display, const std::vector<sp<GraphicBuffer>>&,
+ std::vector<aidl::android::hardware::graphics::composer3::Luts>*) {
+ return Error::UNSUPPORTED;
+}
+
+Error HidlComposer::setDisplayPictureProfileId(Display, PictureProfileId) {
+ return Error::UNSUPPORTED;
+}
+
+Error HidlComposer::setLayerPictureProfileId(Display, Layer, PictureProfileId) {
+ return Error::UNSUPPORTED;
+}
+
void HidlComposer::registerCallback(ComposerCallback& callback) {
const bool vsyncSwitchingSupported =
isSupported(Hwc2::Composer::OptionalFeature::RefreshRateSwitching);
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
index 1cc23d1..86ca4b1 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
@@ -60,7 +60,6 @@
using V2_1::Config;
using V2_1::Display;
-using V2_1::Error;
using V2_1::Layer;
using V2_4::CommandReaderBase;
using V2_4::CommandWriterBase;
@@ -215,6 +214,10 @@
Error getReleaseFences(Display display, std::vector<Layer>* outLayers,
std::vector<int>* outReleaseFences) override;
+ Error getLayerPresentFences(Display display, std::vector<Layer>* outLayers,
+ std::vector<int>* outFences,
+ std::vector<int64_t>* outLatenciesNanos) override;
+
Error presentDisplay(Display display, int* outPresentFence) override;
Error setActiveConfig(Display display, Config config) override;
@@ -308,7 +311,7 @@
V2_4::Error getDisplayConnectionType(Display display,
IComposerClient::DisplayConnectionType* outType) override;
V2_4::Error getDisplayVsyncPeriod(Display display, VsyncPeriodNanos* outVsyncPeriod) override;
- V2_4::Error setActiveConfigWithConstraints(
+ Error setActiveConfigWithConstraints(
Display display, Config config,
const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
VsyncPeriodChangeTimeline* outTimeline) override;
@@ -356,7 +359,12 @@
std::vector<aidl::android::hardware::graphics::composer3::DisplayLuts::LayerLut>*)
override;
Error setLayerLuts(Display, Layer,
- std::vector<aidl::android::hardware::graphics::composer3::Lut>&) override;
+ aidl::android::hardware::graphics::composer3::Luts&) override;
+ Error getMaxLayerPictureProfiles(Display, int32_t* outMaxProfiles) override;
+ Error setDisplayPictureProfileId(Display, PictureProfileId) override;
+ Error setLayerPictureProfileId(Display, Layer, PictureProfileId) override;
+ Error getLuts(Display, const std::vector<sp<GraphicBuffer>>&,
+ std::vector<aidl::android::hardware::graphics::composer3::Luts>*) override;
private:
class CommandWriter : public CommandWriterBase {
diff --git a/services/surfaceflinger/DisplayRenderArea.cpp b/services/surfaceflinger/DisplayRenderArea.cpp
deleted file mode 100644
index c63c738..0000000
--- a/services/surfaceflinger/DisplayRenderArea.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2020 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 "DisplayRenderArea.h"
-#include "DisplayDevice.h"
-
-namespace android {
-
-std::unique_ptr<RenderArea> DisplayRenderArea::create(wp<const DisplayDevice> displayWeak,
- const Rect& sourceCrop, ui::Size reqSize,
- ui::Dataspace reqDataSpace,
- ftl::Flags<Options> options) {
- if (auto display = displayWeak.promote()) {
- // Using new to access a private constructor.
- return std::unique_ptr<DisplayRenderArea>(new DisplayRenderArea(std::move(display),
- sourceCrop, reqSize,
- reqDataSpace, options));
- }
- return nullptr;
-}
-
-DisplayRenderArea::DisplayRenderArea(sp<const DisplayDevice> display, const Rect& sourceCrop,
- ui::Size reqSize, ui::Dataspace reqDataSpace,
- ftl::Flags<Options> options)
- : RenderArea(reqSize, CaptureFill::OPAQUE, reqDataSpace, options),
- mDisplay(std::move(display)),
- mSourceCrop(sourceCrop) {}
-
-const ui::Transform& DisplayRenderArea::getTransform() const {
- return mTransform;
-}
-
-bool DisplayRenderArea::isSecure() const {
- return mOptions.test(Options::CAPTURE_SECURE_LAYERS) && mDisplay->isSecure();
-}
-
-sp<const DisplayDevice> DisplayRenderArea::getDisplayDevice() const {
- return mDisplay;
-}
-
-Rect DisplayRenderArea::getSourceCrop() const {
- // use the projected display viewport by default.
- if (mSourceCrop.isEmpty()) {
- return mDisplay->getLayerStackSpaceRect();
- }
- return mSourceCrop;
-}
-
-} // namespace android
diff --git a/services/surfaceflinger/DisplayRenderArea.h b/services/surfaceflinger/DisplayRenderArea.h
deleted file mode 100644
index 677d019..0000000
--- a/services/surfaceflinger/DisplayRenderArea.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2020 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 <ui/GraphicTypes.h>
-#include <ui/Transform.h>
-
-#include "RenderArea.h"
-
-namespace android {
-
-class DisplayDevice;
-
-class DisplayRenderArea : public RenderArea {
-public:
- static std::unique_ptr<RenderArea> create(wp<const DisplayDevice>, const Rect& sourceCrop,
- ui::Size reqSize, ui::Dataspace,
- ftl::Flags<Options> options);
-
- const ui::Transform& getTransform() const override;
- bool isSecure() const override;
- sp<const DisplayDevice> getDisplayDevice() const override;
- Rect getSourceCrop() const override;
-
-private:
- DisplayRenderArea(sp<const DisplayDevice>, const Rect& sourceCrop, ui::Size reqSize,
- ui::Dataspace, ftl::Flags<Options> options);
-
- const sp<const DisplayDevice> mDisplay;
- const Rect mSourceCrop;
- const ui::Transform mTransform;
-};
-
-} // namespace android
diff --git a/services/surfaceflinger/FrameTimeline/Android.bp b/services/surfaceflinger/FrameTimeline/Android.bp
deleted file mode 100644
index 8e28cc3..0000000
--- a/services/surfaceflinger/FrameTimeline/Android.bp
+++ /dev/null
@@ -1,35 +0,0 @@
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_native_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_native_license"],
- default_team: "trendy_team_android_core_graphics_stack",
-}
-
-cc_library_static {
- name: "libframetimeline",
- defaults: ["surfaceflinger_defaults"],
- srcs: [
- "FrameTimeline.cpp",
- ],
- header_libs: [
- "libscheduler_headers",
- ],
- shared_libs: [
- "android.hardware.graphics.composer@2.4",
- "libbase",
- "libcutils",
- "liblog",
- "libgui",
- "libtimestats",
- "libui",
- "libutils",
- ],
- static_libs: [
- "libperfetto_client_experimental",
- "libsurfaceflinger_common",
- ],
- export_include_dirs: ["."],
-}
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index 47b811b..008b057 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -29,6 +29,7 @@
#include <cinttypes>
#include <numeric>
#include <unordered_set>
+#include <vector>
#include "../Jank/JankTracker.h"
@@ -378,6 +379,11 @@
}
}
+void SurfaceFrame::setDesiredPresentTime(nsecs_t desiredPresentTime) {
+ std::scoped_lock lock(mMutex);
+ mActuals.desiredPresentTime = desiredPresentTime;
+}
+
void SurfaceFrame::setDropTime(nsecs_t dropTime) {
std::scoped_lock lock(mMutex);
mDropTime = dropTime;
@@ -605,7 +611,11 @@
mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
}
- if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
+ const nsecs_t presentThreshold =
+ FlagManager::getInstance().increase_missed_frame_jank_threshold()
+ ? mJankClassificationThresholds.presentThresholdExtended
+ : mJankClassificationThresholds.presentThresholdLegacy;
+ if (std::abs(presentDelta) > presentThreshold) {
mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
: FramePresentMetadata::EarlyPresent;
// Jank that is missing by less than the render rate period is classified as partial jank,
@@ -623,9 +633,8 @@
} else if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
// Finish on time, Present early
- if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
- deltaToVsync >= refreshRate.getPeriodNsecs() -
- mJankClassificationThresholds.presentThreshold) {
+ if (deltaToVsync < presentThreshold ||
+ deltaToVsync >= refreshRate.getPeriodNsecs() - presentThreshold) {
// Delta factor of vsync
mJankType = JankType::SurfaceFlingerScheduling;
} else {
@@ -645,7 +654,7 @@
// We try to do this by moving the deadline. Since the queue could be stuffed by more
// than one buffer, we take the last latch time as reference and give one vsync
// worth of time for the frame to be ready.
- nsecs_t adjustedDeadline = mLastLatchTime + refreshRate.getPeriodNsecs();
+ nsecs_t adjustedDeadline = mLastLatchTime + displayFrameRenderRate.getPeriodNsecs();
if (adjustedDeadline > mActuals.endTime) {
mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
} else {
@@ -661,9 +670,8 @@
if (!(mJankType & JankType::BufferStuffing)) {
// In a stuffed state, if the app finishes on time and there is no display frame
// jank, only buffer stuffing is the root cause of the jank.
- if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
- deltaToVsync >= refreshRate.getPeriodNsecs() -
- mJankClassificationThresholds.presentThreshold) {
+ if (deltaToVsync < presentThreshold ||
+ deltaToVsync >= refreshRate.getPeriodNsecs() - presentThreshold) {
// Delta factor of vsync
mJankType |= JankType::SurfaceFlingerScheduling;
} else {
@@ -997,6 +1005,11 @@
finalizeCurrentDisplayFrame();
}
+const std::vector<std::shared_ptr<frametimeline::SurfaceFrame>>& FrameTimeline::getPresentFrames()
+ const {
+ return mPresentFrames;
+}
+
void FrameTimeline::onCommitNotComposited() {
SFTRACE_CALL();
std::scoped_lock lock(mMutex);
@@ -1080,7 +1093,11 @@
? std::abs(presentDelta) % mRefreshRate.getPeriodNsecs()
: 0;
- if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
+ nsecs_t presentThreshold = FlagManager::getInstance().increase_missed_frame_jank_threshold()
+ ? mJankClassificationThresholds.presentThresholdExtended
+ : mJankClassificationThresholds.presentThresholdLegacy;
+
+ if (std::abs(presentDelta) > presentThreshold) {
mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
: FramePresentMetadata::EarlyPresent;
// Jank that is missing by less than the render rate period is classified as partial jank,
@@ -1111,9 +1128,8 @@
if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
// Finish on time, Present early
- if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
- deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
- mJankClassificationThresholds.presentThreshold)) {
+ if (deltaToVsync < presentThreshold ||
+ deltaToVsync >= (mRefreshRate.getPeriodNsecs() - presentThreshold)) {
// Delta is a factor of vsync if its within the presentTheshold on either side
// of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
// of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
@@ -1131,7 +1147,7 @@
}
} else if (mFramePresentMetadata == FramePresentMetadata::LatePresent) {
if (std::abs(mSurfaceFlingerPredictions.presentTime - previousPresentTime) <=
- mJankClassificationThresholds.presentThreshold ||
+ presentThreshold ||
previousPresentTime > mSurfaceFlingerPredictions.presentTime) {
// The previous frame was either presented in the current frame's expected vsync or
// it was presented even later than the current frame's expected vsync.
@@ -1140,9 +1156,8 @@
if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish &&
!(mJankType & JankType::SurfaceFlingerStuffing)) {
// Finish on time, Present late
- if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
- deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
- mJankClassificationThresholds.presentThreshold)) {
+ if (deltaToVsync < presentThreshold ||
+ deltaToVsync >= (mRefreshRate.getPeriodNsecs() - presentThreshold)) {
// Delta is a factor of vsync if its within the presentTheshold on either side
// of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
// of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
@@ -1154,8 +1169,7 @@
} else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
if (!(mJankType & JankType::SurfaceFlingerStuffing) ||
mSurfaceFlingerActuals.presentTime - previousPresentTime >
- mRefreshRate.getPeriodNsecs() +
- mJankClassificationThresholds.presentThreshold) {
+ mRefreshRate.getPeriodNsecs() + presentThreshold) {
// Classify CPU vs GPU if SF wasn't stuffed or if SF was stuffed but this frame
// was presented more than a vsync late.
if (mGpuFence != FenceTime::NO_FENCE) {
@@ -1456,6 +1470,30 @@
static_cast<float>(totalPresentToPresentWalls);
}
+void FrameTimeline::generateFrameStats(int32_t layer, size_t count, FrameStats* outStats) const {
+ std::scoped_lock lock(mMutex);
+
+ // TODO: Include FPS calculation here
+ for (auto displayFrame : mDisplayFrames) {
+ if (!count--) {
+ break;
+ }
+
+ if (displayFrame->getActuals().presentTime <= 0) {
+ continue;
+ }
+
+ for (const auto& surfaceFrame : displayFrame->getSurfaceFrames()) {
+ if (surfaceFrame->getLayerId() == layer) {
+ outStats->actualPresentTimesNano.push_back(surfaceFrame->getActuals().presentTime);
+ outStats->desiredPresentTimesNano.push_back(
+ surfaceFrame->getActuals().desiredPresentTime);
+ outStats->frameReadyTimesNano.push_back(surfaceFrame->getActuals().endTime);
+ }
+ }
+ }
+}
+
std::optional<size_t> FrameTimeline::getFirstSignalFenceIndex() const {
for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
const auto& [fence, _] = mPendingPresentFences[i];
@@ -1492,6 +1530,7 @@
mPendingPresentFences.erase(mPendingPresentFences.begin());
}
+ mPresentFrames.clear();
for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
const auto& pendingPresentFence = mPendingPresentFences[i];
nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
@@ -1504,6 +1543,13 @@
auto& displayFrame = pendingPresentFence.second;
displayFrame->onPresent(signalTime, mPreviousActualPresentTime);
+
+ // Surface frames have been jank classified and can be provided to caller
+ // to detect if buffer stuffing is occurring.
+ for (const auto& frame : displayFrame->getSurfaceFrames()) {
+ mPresentFrames.push_back(frame);
+ }
+
mPreviousPredictionPresentTime =
displayFrame->trace(mSurfaceFlingerPid, monoBootOffset,
mPreviousPredictionPresentTime, mFilterFramesBeforeTraceStarts);
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
index cffb61e..9fedb57 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
@@ -85,16 +85,20 @@
*/
struct TimelineItem {
TimelineItem(const nsecs_t startTime = 0, const nsecs_t endTime = 0,
- const nsecs_t presentTime = 0)
- : startTime(startTime), endTime(endTime), presentTime(presentTime) {}
+ const nsecs_t presentTime = 0, const nsecs_t desiredPresentTime = 0)
+ : startTime(startTime),
+ endTime(endTime),
+ presentTime(presentTime),
+ desiredPresentTime(desiredPresentTime) {}
nsecs_t startTime;
nsecs_t endTime;
nsecs_t presentTime;
+ nsecs_t desiredPresentTime;
bool operator==(const TimelineItem& other) const {
return startTime == other.startTime && endTime == other.endTime &&
- presentTime == other.presentTime;
+ presentTime == other.presentTime && desiredPresentTime != other.desiredPresentTime;
}
bool operator!=(const TimelineItem& other) const { return !(*this == other); }
@@ -103,7 +107,10 @@
struct JankClassificationThresholds {
// The various thresholds for App and SF. If the actual timestamp falls within the threshold
// compared to prediction, we treat it as on time.
- nsecs_t presentThreshold = std::chrono::duration_cast<std::chrono::nanoseconds>(2ms).count();
+ nsecs_t presentThresholdLegacy =
+ std::chrono::duration_cast<std::chrono::nanoseconds>(2ms).count();
+ nsecs_t presentThresholdExtended =
+ std::chrono::duration_cast<std::chrono::nanoseconds>(4ms).count();
nsecs_t deadlineThreshold = std::chrono::duration_cast<std::chrono::nanoseconds>(0ms).count();
nsecs_t startThreshold = std::chrono::duration_cast<std::chrono::nanoseconds>(2ms).count();
};
@@ -183,6 +190,7 @@
void setActualStartTime(nsecs_t actualStartTime);
void setActualQueueTime(nsecs_t actualQueueTime);
void setAcquireFenceTime(nsecs_t acquireFenceTime);
+ void setDesiredPresentTime(nsecs_t desiredPresentTime);
void setDropTime(nsecs_t dropTime);
void setPresentState(PresentState presentState, nsecs_t lastLatchTime = 0);
void setRenderRate(Fps renderRate);
@@ -323,6 +331,11 @@
virtual void setSfPresent(nsecs_t sfPresentTime, const std::shared_ptr<FenceTime>& presentFence,
const std::shared_ptr<FenceTime>& gpuFence) = 0;
+ // Provides surface frames that have already been jank classified in the most recent
+ // flush of pending present fences. This allows buffer stuffing detection from SF.
+ virtual const std::vector<std::shared_ptr<frametimeline::SurfaceFrame>>& getPresentFrames()
+ const = 0;
+
// Tells FrameTimeline that a frame was committed but not composited. This is used to flush
// all the associated surface frames.
virtual void onCommitNotComposited() = 0;
@@ -341,6 +354,9 @@
// containing at least one layer ID.
virtual float computeFps(const std::unordered_set<int32_t>& layerIds) = 0;
+ // Supports the legacy FrameStats interface
+ virtual void generateFrameStats(int32_t layer, size_t count, FrameStats* outStats) const = 0;
+
// Restores the max number of display frames to default. Called by SF backdoor.
virtual void reset() = 0;
};
@@ -497,10 +513,13 @@
void setSfWakeUp(int64_t token, nsecs_t wakeupTime, Fps refreshRate, Fps renderRate) override;
void setSfPresent(nsecs_t sfPresentTime, const std::shared_ptr<FenceTime>& presentFence,
const std::shared_ptr<FenceTime>& gpuFence = FenceTime::NO_FENCE) override;
+ const std::vector<std::shared_ptr<frametimeline::SurfaceFrame>>& getPresentFrames()
+ const override;
void onCommitNotComposited() override;
void parseArgs(const Vector<String16>& args, std::string& result) override;
void setMaxDisplayFrames(uint32_t size) override;
float computeFps(const std::unordered_set<int32_t>& layerIds) override;
+ void generateFrameStats(int32_t layer, size_t count, FrameStats* outStats) const override;
void reset() override;
// Sets up the perfetto tracing backend and data source.
@@ -543,6 +562,9 @@
// display frame, this is a good starting size for the vector so that we can avoid the
// internal vector resizing that happens with push_back.
static constexpr uint32_t kNumSurfaceFramesInitial = 10;
+ // Presented surface frames that have been jank classified and can
+ // indicate of potential buffer stuffing.
+ std::vector<std::shared_ptr<frametimeline::SurfaceFrame>> mPresentFrames;
};
} // namespace impl
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
index d709530..da536b6 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
@@ -166,7 +166,8 @@
}
out << "(Mirroring) ";
}
- out << *mLayer;
+
+ out << *mLayer << " pid=" << mLayer->ownerPid.val() << " uid=" << mLayer->ownerUid.val();
}
for (size_t i = 0; i < mChildren.size(); i++) {
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.h b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
index 47d0041..4fdbae1 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.h
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
@@ -102,6 +102,8 @@
// Returns true if the node is a clone.
bool isClone() const { return !mirrorRootIds.empty(); }
+ TraversalPath getClonedFrom() const { return {.id = id, .variant = variant}; }
+
bool operator==(const TraversalPath& other) const {
return id == other.id && mirrorRootIds == other.mirrorRootIds;
}
diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
index f1091a6..d369403 100644
--- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
@@ -182,8 +182,8 @@
}
}
-void LayerLifecycleManager::applyTransactions(const std::vector<TransactionState>& transactions,
- bool ignoreUnknownLayers) {
+void LayerLifecycleManager::applyTransactions(
+ const std::vector<QueuedTransactionState>& transactions, bool ignoreUnknownLayers) {
for (const auto& transaction : transactions) {
for (const auto& resolvedComposerState : transaction.states) {
const auto& clientState = resolvedComposerState.state;
diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h
index 330da9a..072be35 100644
--- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h
+++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h
@@ -16,8 +16,8 @@
#pragma once
+#include "QueuedTransactionState.h"
#include "RequestedLayerState.h"
-#include "TransactionState.h"
namespace android::surfaceflinger::frontend {
@@ -43,7 +43,8 @@
// the layers it is unreachable. When using the LayerLifecycleManager for layer trace
// generation we may encounter layers which are known because we don't have an explicit
// lifecycle. Ignore these errors while we have to interop with legacy.
- void applyTransactions(const std::vector<TransactionState>&, bool ignoreUnknownLayers = false);
+ void applyTransactions(const std::vector<QueuedTransactionState>&,
+ bool ignoreUnknownLayers = false);
// Ignore unknown handles when iteroping with legacy front end. In the old world, we
// would create child layers which are not necessary with the new front end. This means
// we will get notified for handle changes that don't exist in the new front end.
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
index e5f6b7b..1f0d5d0 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
@@ -18,12 +18,17 @@
#undef LOG_TAG
#define LOG_TAG "SurfaceFlinger"
-#include "LayerSnapshot.h"
+#include <PowerAdvisor/Workload.h>
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+#include <gui/LayerState.h>
+
#include "Layer.h"
+#include "LayerSnapshot.h"
namespace android::surfaceflinger::frontend {
using namespace ftl::flag_operators;
+using namespace aidl::android::hardware::graphics::composer3;
namespace {
@@ -250,6 +255,7 @@
if (drawShadows()) reason << " shadowSettings.length=" << shadowSettings.length;
if (backgroundBlurRadius > 0) reason << " backgroundBlurRadius=" << backgroundBlurRadius;
if (blurRegions.size() > 0) reason << " blurRegions.size()=" << blurRegions.size();
+ if (contentDirty) reason << " contentDirty";
return reason.str();
}
@@ -299,7 +305,11 @@
out << rootId << ",";
}
}
- out << "] " << obj.name << "\n " << (obj.isVisible ? "visible" : "invisible")
+ out << "] ";
+ if (obj.isSecure) {
+ out << "(Secure) ";
+ }
+ out << obj.name << "\n " << (obj.isVisible ? "visible" : "invisible")
<< " reason=" << obj.getIsVisibleReason();
if (!obj.geomLayerBounds.isEmpty()) {
@@ -359,8 +369,9 @@
uint32_t displayRotationFlags) {
clientChanges = requested.what;
changes = requested.changes;
- contentDirty = requested.what & layer_state_t::CONTENT_DIRTY;
- hasReadyFrame = requested.autoRefresh;
+ autoRefresh = requested.autoRefresh;
+ contentDirty = requested.what & layer_state_t::CONTENT_DIRTY || autoRefresh;
+ hasReadyFrame = autoRefresh;
sidebandStreamHasFrame = requested.hasSidebandStreamFrame();
updateSurfaceDamage(requested, requested.hasReadyFrame(), forceFullDamage, surfaceDamage);
@@ -399,6 +410,7 @@
if (forceUpdate || requested.what & layer_state_t::eShadowRadiusChanged) {
shadowSettings.length = requested.shadowRadius;
}
+
if (forceUpdate || requested.what & layer_state_t::eFrameRateSelectionPriority) {
frameRateSelectionPriority = requested.frameRateSelectionPriority;
}
@@ -411,6 +423,13 @@
if (forceUpdate || requested.what & layer_state_t::eCropChanged) {
geomCrop = requested.crop;
}
+ if (forceUpdate || requested.what & layer_state_t::ePictureProfileHandleChanged) {
+ pictureProfileHandle = requested.pictureProfileHandle;
+ }
+ if (forceUpdate || requested.what & layer_state_t::eAppContentPriorityChanged) {
+ // TODO(b/337330263): Also consider the system-determined priority of the app
+ pictureProfilePriority = int64_t(requested.appContentPriority) + INT_MAX;
+ }
if (forceUpdate || requested.what & layer_state_t::eDefaultFrameRateCompatibilityChanged) {
const auto compatibility =
@@ -513,6 +532,56 @@
isOpaque = contentOpaque && !roundedCorner.hasRoundedCorners() && color.a == 1.f;
blendMode = getBlendMode(requested);
}
+
+ if (forceUpdate || requested.what & layer_state_t::eLutsChanged) {
+ luts = requested.luts;
+ }
+}
+
+char LayerSnapshot::classifyCompositionForDebug(
+ const compositionengine::LayerFE::HwcLayerDebugState& hwcState) const {
+ if (!isVisible) {
+ return '.';
+ }
+
+ switch (hwcState.lastCompositionType) {
+ case Composition::INVALID:
+ return 'i';
+ case Composition::SOLID_COLOR:
+ return 'e';
+ case Composition::CURSOR:
+ return 'u';
+ case Composition::SIDEBAND:
+ return 'd';
+ case Composition::DISPLAY_DECORATION:
+ return 'a';
+ case Composition::REFRESH_RATE_INDICATOR:
+ return 'f';
+ case Composition::CLIENT:
+ case Composition::DEVICE:
+ break;
+ }
+
+ char code = '.'; // Default to invisible
+ if (hasBlur()) {
+ code = 'l'; // Blur
+ } else if (hasProtectedContent) {
+ code = 'p'; // Protected content
+ } else if (roundedCorner.hasRoundedCorners()) {
+ code = 'r'; // Rounded corners
+ } else if (drawShadows()) {
+ code = 's'; // Shadow
+ } else if (fillsColor()) {
+ code = 'c'; // Solid color
+ } else if (hasBufferOrSidebandStream()) {
+ code = 'b';
+ }
+
+ if (hwcState.lastCompositionType == Composition::CLIENT) {
+ return static_cast<char>(std::toupper(code));
+ } else {
+ return code;
+ }
}
} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.h b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
index b7d4cc5..69120bd 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
@@ -16,6 +16,7 @@
#pragma once
+#include <PowerAdvisor/Workload.h>
#include <compositionengine/LayerFECompositionState.h>
#include <renderengine/LayerSettings.h>
#include "DisplayHardware/ComposerHal.h"
@@ -23,21 +24,29 @@
#include "RequestedLayerState.h"
#include "Scheduler/LayerInfo.h"
#include "android-base/stringprintf.h"
+#include "compositionengine/LayerFE.h"
namespace android::surfaceflinger::frontend {
struct RoundedCornerState {
RoundedCornerState() = default;
- RoundedCornerState(const FloatRect& cropRect, const vec2& radius)
- : cropRect(cropRect), radius(radius) {}
// Rounded rectangle in local layer coordinate space.
FloatRect cropRect = FloatRect();
- // Radius of the rounded rectangle.
+ // Radius of the rounded rectangle for composition
vec2 radius;
+ // Requested radius of the rounded rectangle
+ vec2 requestedRadius;
+ // Radius drawn by client for the rounded rectangle
+ vec2 clientDrawnRadius;
+ bool hasClientDrawnRadius() const {
+ return clientDrawnRadius.x > 0.0f && clientDrawnRadius.y > 0.0f;
+ }
+ bool hasRequestedRadius() const { return requestedRadius.x > 0.0f && requestedRadius.y > 0.0f; }
bool hasRoundedCorners() const { return radius.x > 0.0f && radius.y > 0.0f; }
bool operator==(RoundedCornerState const& rhs) const {
- return cropRect == rhs.cropRect && radius == rhs.radius;
+ return cropRect == rhs.cropRect && radius == rhs.radius &&
+ clientDrawnRadius == rhs.clientDrawnRadius;
}
};
@@ -77,6 +86,7 @@
gui::LayerMetadata layerMetadata;
gui::LayerMetadata relativeLayerMetadata;
bool hasReadyFrame; // used in post composition to check if there is another frame ready
+ bool autoRefresh;
ui::Transform localTransformInverse;
gui::WindowInfo inputInfo;
ui::Transform localTransform;
@@ -151,6 +161,10 @@
friend std::ostream& operator<<(std::ostream& os, const LayerSnapshot& obj);
void merge(const RequestedLayerState& requested, bool forceUpdate, bool displayChanges,
bool forceFullDamage, uint32_t displayRotationFlags);
+ // Returns a char summarizing the composition request
+ // This function tries to maintain parity with planner::Plan chars.
+ char classifyCompositionForDebug(
+ const compositionengine::LayerFE::HwcLayerDebugState& hwcState) const;
};
} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index 10e212e..86ef6ca 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -16,6 +16,8 @@
// #define LOG_NDEBUG 0
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#include "FrontEnd/LayerSnapshot.h"
+#include "ui/Transform.h"
#undef LOG_TAG
#define LOG_TAG "SurfaceFlinger"
@@ -25,6 +27,7 @@
#include <common/FlagManager.h>
#include <common/trace.h>
#include <ftl/small_map.h>
+#include <math/vec2.h>
#include <ui/DisplayMap.h>
#include <ui/FloatRect.h>
@@ -275,6 +278,7 @@
const bool visibleForInput =
snapshot.hasInputInfo() ? snapshot.canReceiveInput() : snapshot.isVisible;
snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visibleForInput);
+
LLOGV(snapshot.sequence, "updating visibility %s %s", visible ? "true" : "false",
snapshot.getDebugString().c_str());
}
@@ -314,8 +318,8 @@
void clearChanges(LayerSnapshot& snapshot) {
snapshot.changes.clear();
snapshot.clientChanges = 0;
- snapshot.contentDirty = false;
- snapshot.hasReadyFrame = false;
+ snapshot.contentDirty = snapshot.autoRefresh;
+ snapshot.hasReadyFrame = snapshot.autoRefresh;
snapshot.sidebandStreamHasFrame = false;
snapshot.surfaceDamage.clear();
}
@@ -724,10 +728,12 @@
if (args.displayChanges) snapshot.changes |= RequestedLayerState::Changes::Geometry;
snapshot.reachablilty = LayerSnapshot::Reachablilty::Reachable;
snapshot.clientChanges |= (parentSnapshot.clientChanges & layer_state_t::AFFECTS_CHILDREN);
+ // mark the content as dirty if the parent state changes can dirty the child's content (for
+ // example alpha)
+ snapshot.contentDirty |= (snapshot.clientChanges & layer_state_t::CONTENT_DIRTY) != 0;
snapshot.isHiddenByPolicyFromParent = parentSnapshot.isHiddenByPolicyFromParent ||
parentSnapshot.invalidTransform || requested.isHiddenByPolicy() ||
(args.excludeLayerIds.find(path.id) != args.excludeLayerIds.end());
-
const bool forceUpdate = args.forceUpdate == ForceUpdateFlags::ALL ||
snapshot.clientChanges & layer_state_t::eReparent ||
snapshot.changes.any(RequestedLayerState::Changes::Visibility |
@@ -922,7 +928,8 @@
if (forceUpdate || snapshot.clientChanges & layer_state_t::eCornerRadiusChanged ||
snapshot.changes.any(RequestedLayerState::Changes::Geometry |
- RequestedLayerState::Changes::BufferUsageFlags)) {
+ RequestedLayerState::Changes::BufferUsageFlags) ||
+ snapshot.clientChanges & layer_state_t::eClientDrawnCornerRadiusChanged) {
updateRoundedCorner(snapshot, requested, parentSnapshot, args);
}
@@ -962,19 +969,27 @@
}
snapshot.roundedCorner = RoundedCornerState();
RoundedCornerState parentRoundedCorner;
- if (parentSnapshot.roundedCorner.hasRoundedCorners()) {
+ if (parentSnapshot.roundedCorner.hasRequestedRadius()) {
parentRoundedCorner = parentSnapshot.roundedCorner;
ui::Transform t = snapshot.localTransform.inverse();
parentRoundedCorner.cropRect = t.transform(parentRoundedCorner.cropRect);
parentRoundedCorner.radius.x *= t.getScaleX();
parentRoundedCorner.radius.y *= t.getScaleY();
+ parentRoundedCorner.requestedRadius.x *= t.getScaleX();
+ parentRoundedCorner.requestedRadius.y *= t.getScaleY();
}
FloatRect layerCropRect = snapshot.croppedBufferSize;
- const vec2 radius(requested.cornerRadius, requested.cornerRadius);
- RoundedCornerState layerSettings(layerCropRect, radius);
- const bool layerSettingsValid = layerSettings.hasRoundedCorners() && !layerCropRect.isEmpty();
- const bool parentRoundedCornerValid = parentRoundedCorner.hasRoundedCorners();
+ const vec2 requestedRadius(requested.cornerRadius, requested.cornerRadius);
+ const vec2 clientDrawnRadius(requested.clientDrawnCornerRadius,
+ requested.clientDrawnCornerRadius);
+ RoundedCornerState layerSettings;
+ layerSettings.cropRect = layerCropRect;
+ layerSettings.requestedRadius = requestedRadius;
+ layerSettings.clientDrawnRadius = clientDrawnRadius;
+
+ const bool layerSettingsValid = layerSettings.hasRequestedRadius() && !layerCropRect.isEmpty();
+ const bool parentRoundedCornerValid = parentRoundedCorner.hasRequestedRadius();
if (layerSettingsValid && parentRoundedCornerValid) {
// If the parent and the layer have rounded corner settings, use the parent settings if
// the parent crop is entirely inside the layer crop. This has limitations and cause
@@ -992,6 +1007,14 @@
} else if (parentRoundedCornerValid) {
snapshot.roundedCorner = parentRoundedCorner;
}
+
+ if (snapshot.roundedCorner.requestedRadius.x == requested.clientDrawnCornerRadius) {
+ // If the client drawn radius matches the requested radius, then surfaceflinger
+ // does not need to draw rounded corners for this layer
+ snapshot.roundedCorner.radius = vec2(0.f, 0.f);
+ } else {
+ snapshot.roundedCorner.radius = snapshot.roundedCorner.requestedRadius;
+ }
}
/**
@@ -1155,7 +1178,7 @@
auto displayInfo = displayInfoOpt.value_or(sDefaultInfo);
if (!requested.hasInputInfo()) {
- snapshot.inputInfo.inputConfig = InputConfig::NO_INPUT_CHANNEL;
+ snapshot.inputInfo.inputConfig |= InputConfig::NO_INPUT_CHANNEL;
}
fillInputFrameInfo(snapshot.inputInfo, displayInfo.transform, snapshot);
@@ -1195,13 +1218,27 @@
snapshot.inputInfo.contentSize = {snapshot.croppedBufferSize.getHeight(),
snapshot.croppedBufferSize.getWidth()};
- // If the layer is a clone, we need to crop the input region to cloned root to prevent
- // touches from going outside the cloned area.
+ snapshot.inputInfo.cloneLayerStackTransform.reset();
+
if (path.isClone()) {
snapshot.inputInfo.inputConfig |= InputConfig::CLONE;
// Cloned layers shouldn't handle watch outside since their z order is not determined by
// WM or the client.
snapshot.inputInfo.inputConfig.clear(InputConfig::WATCH_OUTSIDE_TOUCH);
+
+ // Compute the transform that maps the clone's display to the layer stack space of the
+ // cloned window.
+ const LayerSnapshot* clonedSnapshot = getSnapshot(path.getClonedFrom());
+ if (clonedSnapshot != nullptr) {
+ const auto& [clonedInputBounds, s] =
+ getInputBounds(*clonedSnapshot, /*fillParentBounds=*/false);
+ ui::Transform inputToLayer;
+ inputToLayer.set(clonedInputBounds.left, clonedInputBounds.top);
+ const ui::Transform& layerToLayerStack = getInputTransform(*clonedSnapshot);
+ const auto& displayToInput = snapshot.inputInfo.transform;
+ snapshot.inputInfo.cloneLayerStackTransform =
+ layerToLayerStack * inputToLayer * displayToInput;
+ }
}
}
@@ -1258,6 +1295,10 @@
for (int i = mNumInterestingSnapshots - 1; i >= 0; i--) {
LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
if (!snapshot.hasInputInfo()) continue;
+ if (FlagManager::getInstance().skip_invisible_windows_in_input() &&
+ snapshot.inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NOT_VISIBLE)) {
+ continue;
+ }
visitor(snapshot);
}
}
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
index 713a5c5..58c235e 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -107,6 +107,7 @@
hdrMetadata.validTypes = 0;
surfaceDamageRegion = Region::INVALID_REGION;
cornerRadius = 0.0f;
+ clientDrawnCornerRadius = 0.0f;
backgroundBlurRadius = 0;
api = -1;
hasColorTransform = false;
@@ -163,7 +164,7 @@
uint64_t clientChanges = what | layer_state_t::diff(clientState);
layer_state_t::merge(clientState);
what = clientChanges;
- LLOGV(layerId, "requested=%" PRIu64 "flags=%" PRIu64, clientState.what, clientChanges);
+ LLOGV(layerId, "requested=%" PRIu64 " flags=%" PRIu64 " ", clientState.what, clientChanges);
if (clientState.what & layer_state_t::eFlagsChanged) {
if ((oldFlags ^ flags) &
@@ -348,6 +349,11 @@
requestedFrameRate.category = category;
changes |= RequestedLayerState::Changes::FrameRate;
}
+
+ if (clientState.what & layer_state_t::eClientDrawnCornerRadiusChanged) {
+ clientDrawnCornerRadius = clientState.clientDrawnCornerRadius;
+ changes |= RequestedLayerState::Changes::Geometry;
+ }
}
ui::Size RequestedLayerState::getUnrotatedBufferSize(uint32_t displayRotationFlags) const {
@@ -561,7 +567,7 @@
return false;
}
- if ((sidebandStream != nullptr) || (externalTexture != nullptr)) {
+ if (hasBufferOrSidebandStream() || fillsColor()) {
return true;
}
@@ -574,6 +580,15 @@
windowInfo->inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL);
}
+bool RequestedLayerState::hasBufferOrSidebandStream() const {
+ return ((sidebandStream != nullptr) || (externalTexture != nullptr));
+}
+
+bool RequestedLayerState::fillsColor() const {
+ return !hasBufferOrSidebandStream() && color.r >= 0.0_hf && color.g >= 0.0_hf &&
+ color.b >= 0.0_hf;
+}
+
bool RequestedLayerState::hasBlur() const {
return backgroundBlurRadius > 0 || blurRegions.size() > 0;
}
@@ -624,6 +639,7 @@
const uint64_t deniedChanges = layer_state_t::ePositionChanged | layer_state_t::eAlphaChanged |
layer_state_t::eColorTransformChanged | layer_state_t::eBackgroundColorChanged |
layer_state_t::eMatrixChanged | layer_state_t::eCornerRadiusChanged |
+ layer_state_t::eClientDrawnCornerRadiusChanged |
layer_state_t::eBackgroundBlurRadiusChanged | layer_state_t::eBufferTransformChanged |
layer_state_t::eTransformToDisplayInverseChanged | layer_state_t::eCropChanged |
layer_state_t::eDataspaceChanged | layer_state_t::eHdrMetadataChanged |
@@ -633,7 +649,7 @@
layer_state_t::eEdgeExtensionChanged | layer_state_t::eBufferCropChanged |
layer_state_t::eDestinationFrameChanged | layer_state_t::eDimmingEnabledChanged |
layer_state_t::eExtendedRangeBrightnessChanged |
- layer_state_t::eDesiredHdrHeadroomChanged |
+ layer_state_t::eDesiredHdrHeadroomChanged | layer_state_t::eLutsChanged |
(FlagManager::getInstance().latch_unsignaled_with_auto_refresh_changed()
? layer_state_t::eFlagsChanged
: 0);
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.h b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
index 7ddd7ba..7232379 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.h
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
@@ -23,7 +23,7 @@
#include "Scheduler/LayerInfo.h"
#include "LayerCreationArgs.h"
-#include "TransactionState.h"
+#include "QueuedTransactionState.h"
namespace android::surfaceflinger::frontend {
using namespace ftl::flag_operators;
@@ -88,6 +88,8 @@
bool hasValidRelativeParent() const;
bool hasInputInfo() const;
bool needsInputInfo() const;
+ bool hasBufferOrSidebandStream() const;
+ bool fillsColor() const;
bool hasBlur() const;
bool hasFrameUpdate() const;
bool hasReadyFrame() const;
diff --git a/services/surfaceflinger/FrontEnd/TransactionHandler.cpp b/services/surfaceflinger/FrontEnd/TransactionHandler.cpp
index a1e8213..5bf86e5 100644
--- a/services/surfaceflinger/FrontEnd/TransactionHandler.cpp
+++ b/services/surfaceflinger/FrontEnd/TransactionHandler.cpp
@@ -28,7 +28,7 @@
namespace android::surfaceflinger::frontend {
-void TransactionHandler::queueTransaction(TransactionState&& state) {
+void TransactionHandler::queueTransaction(QueuedTransactionState&& state) {
mLocklessTransactionQueue.push(std::move(state));
mPendingTransactionCount.fetch_add(1);
SFTRACE_INT("TransactionQueue", static_cast<int>(mPendingTransactionCount.load()));
@@ -45,9 +45,9 @@
}
}
-std::vector<TransactionState> TransactionHandler::flushTransactions() {
+std::vector<QueuedTransactionState> TransactionHandler::flushTransactions() {
// Collect transaction that are ready to be applied.
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
TransactionFlushState flushState;
flushState.queueProcessTime = systemTime();
// Transactions with a buffer pending on a barrier may be on a different applyToken
@@ -76,7 +76,7 @@
}
void TransactionHandler::applyUnsignaledBufferTransaction(
- std::vector<TransactionState>& transactions, TransactionFlushState& flushState) {
+ std::vector<QueuedTransactionState>& transactions, TransactionFlushState& flushState) {
if (!flushState.queueWithUnsignaledBuffer) {
return;
}
@@ -98,9 +98,9 @@
}
}
-void TransactionHandler::popTransactionFromPending(std::vector<TransactionState>& transactions,
- TransactionFlushState& flushState,
- std::queue<TransactionState>& queue) {
+void TransactionHandler::popTransactionFromPending(
+ std::vector<QueuedTransactionState>& transactions, TransactionFlushState& flushState,
+ std::queue<QueuedTransactionState>& queue) {
auto& transaction = queue.front();
// Transaction is ready move it from the pending queue.
flushState.firstTransaction = false;
@@ -146,8 +146,8 @@
return ready;
}
-int TransactionHandler::flushPendingTransactionQueues(std::vector<TransactionState>& transactions,
- TransactionFlushState& flushState) {
+int TransactionHandler::flushPendingTransactionQueues(
+ std::vector<QueuedTransactionState>& transactions, TransactionFlushState& flushState) {
int transactionsPendingBarrier = 0;
auto it = mPendingTransactionQueues.begin();
while (it != mPendingTransactionQueues.end()) {
diff --git a/services/surfaceflinger/FrontEnd/TransactionHandler.h b/services/surfaceflinger/FrontEnd/TransactionHandler.h
index 00f6bce..e78dd88 100644
--- a/services/surfaceflinger/FrontEnd/TransactionHandler.h
+++ b/services/surfaceflinger/FrontEnd/TransactionHandler.h
@@ -22,7 +22,7 @@
#include <vector>
#include <LocklessQueue.h>
-#include <TransactionState.h>
+#include <QueuedTransactionState.h>
#include <android-base/thread_annotations.h>
#include <ftl/small_map.h>
#include <ftl/small_vector.h>
@@ -35,7 +35,7 @@
class TransactionHandler {
public:
struct TransactionFlushState {
- TransactionState* transaction;
+ QueuedTransactionState* transaction;
bool firstTransaction = true;
nsecs_t queueProcessTime = 0;
// Layer handles that have transactions with buffers that are ready to be applied.
@@ -61,9 +61,9 @@
bool hasPendingTransactions();
// Moves transactions from the lockless queue.
void collectTransactions();
- std::vector<TransactionState> flushTransactions();
+ std::vector<QueuedTransactionState> flushTransactions();
void addTransactionReadyFilter(TransactionFilter&&);
- void queueTransaction(TransactionState&&);
+ void queueTransaction(QueuedTransactionState&&);
struct StalledTransactionInfo {
pid_t pid;
@@ -81,14 +81,15 @@
// For unit tests
friend class ::android::TestableSurfaceFlinger;
- int flushPendingTransactionQueues(std::vector<TransactionState>&, TransactionFlushState&);
- void applyUnsignaledBufferTransaction(std::vector<TransactionState>&, TransactionFlushState&);
- void popTransactionFromPending(std::vector<TransactionState>&, TransactionFlushState&,
- std::queue<TransactionState>&);
+ int flushPendingTransactionQueues(std::vector<QueuedTransactionState>&, TransactionFlushState&);
+ void applyUnsignaledBufferTransaction(std::vector<QueuedTransactionState>&,
+ TransactionFlushState&);
+ void popTransactionFromPending(std::vector<QueuedTransactionState>&, TransactionFlushState&,
+ std::queue<QueuedTransactionState>&);
TransactionReadiness applyFilters(TransactionFlushState&);
- std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IListenerHash>
+ std::unordered_map<sp<IBinder>, std::queue<QueuedTransactionState>, IListenerHash>
mPendingTransactionQueues;
- LocklessQueue<TransactionState> mLocklessTransactionQueue;
+ LocklessQueue<QueuedTransactionState> mLocklessTransactionQueue;
std::atomic<size_t> mPendingTransactionCount = 0;
ftl::SmallVector<TransactionFilter, 2> mTransactionReadyFilters;
diff --git a/services/surfaceflinger/FrontEnd/Update.h b/services/surfaceflinger/FrontEnd/Update.h
index 4af27ab..f7dfeb8 100644
--- a/services/surfaceflinger/FrontEnd/Update.h
+++ b/services/surfaceflinger/FrontEnd/Update.h
@@ -19,15 +19,15 @@
#include <gui/DisplayInfo.h>
#include "FrontEnd/LayerCreationArgs.h"
+#include "QueuedTransactionState.h"
#include "RequestedLayerState.h"
-#include "TransactionState.h"
namespace android::surfaceflinger::frontend {
// Atomic set of changes affecting layer state. These changes are queued in binder threads and
// applied every vsync.
struct Update {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
std::vector<sp<Layer>> legacyLayers;
std::vector<std::unique_ptr<frontend::RequestedLayerState>> newLayers;
std::vector<LayerCreationArgs> layerCreationArgs;
diff --git a/services/surfaceflinger/FrontEnd/readme.md b/services/surfaceflinger/FrontEnd/readme.md
index e5f51a5..6258f7e 100644
--- a/services/surfaceflinger/FrontEnd/readme.md
+++ b/services/surfaceflinger/FrontEnd/readme.md
@@ -17,6 +17,29 @@
This allows control to be delegated to different parts of the system - such as SystemServer,
SysUI and Apps.
+### Layer Drawing Order
+Layers are drawn based on an inorder traversal, treating relative parents as
+direct parents. Negative z-values place layers below their parent, while
+non-negative values place them above. Layers with the same z-value are drawn
+in creation order (newer on top). However, relying on creation order for
+z-ordering is discouraged; use unique z-values whenever possible for better
+control.
+
+Traversal pseudo code:
+```
+fn traverseBottomToTop(root):
+ for each child node including relative children,
+ sorted by z then layer id, with z less than 0:
+ traverseBottomToTop(childNode)
+
+ visit(root)
+
+ for each child node including relative children,
+ sorted by z then layer id, with z greater than
+ or equal to 0:
+ traverseBottomToTop(childNode)
+```
+
### Layer Lifecycle
Layer is created by a client. The client receives a strong binder reference to the layer
handle, which will keep the layer alive as long as the client holds the reference. The
diff --git a/services/surfaceflinger/Jank/JankTracker.cpp b/services/surfaceflinger/Jank/JankTracker.cpp
index 8e0e084..5e6267d 100644
--- a/services/surfaceflinger/Jank/JankTracker.cpp
+++ b/services/surfaceflinger/Jank/JankTracker.cpp
@@ -88,7 +88,8 @@
}
void JankTracker::addJankListenerLocked(int32_t layerId, sp<IBinder> listener) {
- for (auto it = mJankListeners.find(layerId); it != mJankListeners.end(); it++) {
+ auto range = mJankListeners.equal_range(layerId);
+ for (auto it = range.first; it != range.second; it++) {
if (it->second.mListener == listener) {
// Undo the duplicate increment in addJankListener.
sListenerCount--;
@@ -106,7 +107,8 @@
std::vector<sp<IBinder>> toSend;
mLock.lock();
- for (auto it = mJankListeners.find(layerId); it != mJankListeners.end();) {
+ auto range = mJankListeners.equal_range(layerId);
+ for (auto it = range.first; it != range.second;) {
if (!jankData.empty()) {
toSend.emplace_back(it->second.mListener);
}
@@ -133,7 +135,8 @@
void JankTracker::markJankListenerForRemovalLocked(int32_t layerId, sp<IBinder> listener,
int64_t afterVysnc) {
- for (auto it = mJankListeners.find(layerId); it != mJankListeners.end(); it++) {
+ auto range = mJankListeners.equal_range(layerId);
+ for (auto it = range.first; it != range.second; it++) {
if (it->second.mListener == listener) {
it->second.mRemoveAfter = std::max(static_cast<int64_t>(0), afterVysnc);
return;
@@ -156,7 +159,8 @@
void JankTracker::dropJankListener(int32_t layerId, sp<IBinder> listener) {
const std::lock_guard<std::mutex> _l(mLock);
- for (auto it = mJankListeners.find(layerId); it != mJankListeners.end(); it++) {
+ auto range = mJankListeners.equal_range(layerId);
+ for (auto it = range.first; it != range.second; it++) {
if (it->second.mListener == listener) {
mJankListeners.erase(it);
sListenerCount--;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index c14769e..95a7170 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -64,7 +64,7 @@
#include "DisplayDevice.h"
#include "DisplayHardware/HWComposer.h"
-#include "FrameTimeline.h"
+#include "FrameTimeline/FrameTimeline.h"
#include "FrameTracer/FrameTracer.h"
#include "FrontEnd/LayerCreationArgs.h"
#include "FrontEnd/LayerHandle.h"
@@ -154,7 +154,7 @@
mDrawingState.metadata = args.metadata;
mDrawingState.frameTimelineInfo = {};
mDrawingState.postTime = -1;
- mFrameTracker.setDisplayRefreshPeriod(
+ mDeprecatedFrameTracker.setDisplayRefreshPeriod(
args.flinger->mScheduler->getPacesetterVsyncPeriod().ns());
mOwnerUid = args.ownerUid;
@@ -185,6 +185,14 @@
mFlinger->onLayerDestroyed(this);
+ const auto currentTime = std::chrono::steady_clock::now();
+ if (mBufferInfo.mTimeSinceDataspaceUpdate > std::chrono::steady_clock::time_point::min()) {
+ mFlinger->mLayerEvents.emplace_back(mOwnerUid, getSequence(), mBufferInfo.mDataspace,
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ currentTime -
+ mBufferInfo.mTimeSinceDataspaceUpdate));
+ }
+
if (mDrawingState.sidebandStream != nullptr) {
mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount();
}
@@ -354,7 +362,7 @@
// transaction
// ----------------------------------------------------------------------------
-void Layer::commitTransaction() {
+void Layer::commitTransaction() REQUIRES(mFlinger->mStateLock) {
// Set the present state for all bufferlessSurfaceFramesTX to Presented. The
// bufferSurfaceFrameTX will be presented in latchBuffer.
for (auto& [token, surfaceFrame] : mDrawingState.bufferlessSurfaceFramesTX) {
@@ -386,7 +394,8 @@
};
void Layer::setFrameTimelineVsyncForBufferTransaction(const FrameTimelineInfo& info,
- nsecs_t postTime, gui::GameMode gameMode) {
+ nsecs_t postTime, gui::GameMode gameMode)
+ REQUIRES(mFlinger->mStateLock) {
mDrawingState.postTime = postTime;
// Check if one of the bufferlessSurfaceFramesTX contains the same vsyncId. This can happen if
@@ -450,7 +459,7 @@
void Layer::addSurfaceFramePresentedForBuffer(
std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame, nsecs_t acquireFenceTime,
- nsecs_t currentLatchTime) {
+ nsecs_t currentLatchTime) REQUIRES(mFlinger->mStateLock) {
surfaceFrame->setAcquireFenceTime(acquireFenceTime);
surfaceFrame->setPresentState(PresentState::Presented, mLastLatchTime);
mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame);
@@ -458,12 +467,16 @@
}
std::shared_ptr<frametimeline::SurfaceFrame> Layer::createSurfaceFrameForTransaction(
- const FrameTimelineInfo& info, nsecs_t postTime, gui::GameMode gameMode) {
+ const FrameTimelineInfo& info, nsecs_t postTime, gui::GameMode gameMode)
+ REQUIRES(mFlinger->mStateLock) {
auto surfaceFrame =
mFlinger->mFrameTimeline->createSurfaceFrameForToken(info, mOwnerPid, mOwnerUid,
getSequence(), mName,
mTransactionName,
/*isBuffer*/ false, gameMode);
+ // Buffer hasn't yet been latched, so use mDrawingState
+ surfaceFrame->setDesiredPresentTime(mDrawingState.desiredPresentTime);
+
surfaceFrame->setActualStartTime(info.startTimeNanos);
// For Transactions, the post time is considered to be both queue and acquire fence time.
surfaceFrame->setActualQueueTime(postTime);
@@ -477,11 +490,13 @@
std::shared_ptr<frametimeline::SurfaceFrame> Layer::createSurfaceFrameForBuffer(
const FrameTimelineInfo& info, nsecs_t queueTime, std::string debugName,
- gui::GameMode gameMode) {
+ gui::GameMode gameMode) REQUIRES(mFlinger->mStateLock) {
auto surfaceFrame =
mFlinger->mFrameTimeline->createSurfaceFrameForToken(info, mOwnerPid, mOwnerUid,
getSequence(), mName, debugName,
/*isBuffer*/ true, gameMode);
+ // Buffer hasn't yet been latched, so use mDrawingState
+ surfaceFrame->setDesiredPresentTime(mDrawingState.desiredPresentTime);
surfaceFrame->setActualStartTime(info.startTimeNanos);
// For buffers, acquire fence time will set during latch.
surfaceFrame->setActualQueueTime(queueTime);
@@ -493,7 +508,8 @@
}
void Layer::setFrameTimelineVsyncForSkippedFrames(const FrameTimelineInfo& info, nsecs_t postTime,
- std::string debugName, gui::GameMode gameMode) {
+ std::string debugName, gui::GameMode gameMode)
+ REQUIRES(mFlinger->mStateLock) {
if (info.skippedFrameVsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) {
return;
}
@@ -506,6 +522,8 @@
mOwnerPid, mOwnerUid,
getSequence(), mName, debugName,
/*isBuffer*/ false, gameMode);
+ // Buffer hasn't yet been latched, so use mDrawingState
+ surfaceFrame->setDesiredPresentTime(mDrawingState.desiredPresentTime);
surfaceFrame->setActualStartTime(skippedFrameTimelineInfo.skippedFrameStartTimeNanos);
// For Transactions, the post time is considered to be both queue and acquire fence time.
surfaceFrame->setActualQueueTime(postTime);
@@ -597,15 +615,42 @@
}
void Layer::dumpFrameStats(std::string& result) const {
- mFrameTracker.dumpStats(result);
+ if (FlagManager::getInstance().deprecate_frame_tracker()) {
+ FrameStats fs = FrameStats();
+ getFrameStats(&fs);
+ for (auto desired = fs.desiredPresentTimesNano.begin(),
+ actual = fs.actualPresentTimesNano.begin(),
+ ready = fs.frameReadyTimesNano.begin();
+ desired != fs.desiredPresentTimesNano.end() &&
+ actual != fs.actualPresentTimesNano.end() && ready != fs.frameReadyTimesNano.end();
+ ++desired, ++actual, ++ready) {
+ result.append(std::format("{}\t{}\t{}\n", *desired, *actual, *ready));
+ }
+
+ result.push_back('\n');
+ } else {
+ mDeprecatedFrameTracker.dumpStats(result);
+ }
}
void Layer::clearFrameStats() {
- mFrameTracker.clearStats();
+ if (FlagManager::getInstance().deprecate_frame_tracker()) {
+ mFrameStatsHistorySize = 0;
+ } else {
+ mDeprecatedFrameTracker.clearStats();
+ }
}
void Layer::getFrameStats(FrameStats* outStats) const {
- mFrameTracker.getStats(outStats);
+ if (FlagManager::getInstance().deprecate_frame_tracker()) {
+ if (auto ftl = getTimeline()) {
+ float fps = ftl->get().computeFps({getSequence()});
+ ftl->get().generateFrameStats(getSequence(), mFrameStatsHistorySize, outStats);
+ outStats->refreshPeriodNano = Fps::fromValue(fps).getPeriodNsecs();
+ }
+ } else {
+ mDeprecatedFrameTracker.getStats(outStats);
+ }
}
void Layer::onDisconnect() {
@@ -681,8 +726,20 @@
listener->onReleaseBuffer(callbackId, fence, currentMaxAcquiredBufferCount);
}
- if (mBufferReleaseChannel) {
- mBufferReleaseChannel->writeReleaseFence(callbackId, fence, currentMaxAcquiredBufferCount);
+ if (!mBufferReleaseChannel) {
+ return;
+ }
+
+ status_t status = mBufferReleaseChannel->writeReleaseFence(callbackId, fence,
+ currentMaxAcquiredBufferCount);
+ if (status != OK) {
+ int error = -status;
+ // callReleaseBufferCallback is called during Layer's destructor. In this case, it's
+ // expected to receive connection errors.
+ if (error != EPIPE && error != ECONNRESET) {
+ ALOGD("[%s] writeReleaseFence failed. error %d (%s)", getDebugName(), error,
+ strerror(error));
+ }
}
}
@@ -751,54 +808,6 @@
}
}
-void Layer::onLayerDisplayed(ftl::SharedFuture<FenceResult> futureFenceResult,
- ui::LayerStack layerStack,
- std::function<FenceResult(FenceResult)>&& continuation) {
- sp<CallbackHandle> ch = findCallbackHandle();
-
- if (!FlagManager::getInstance().screenshot_fence_preservation() && continuation) {
- futureFenceResult = ftl::Future(futureFenceResult).then(std::move(continuation)).share();
- }
-
- if (ch != nullptr) {
- ch->previousReleaseCallbackId = mPreviousReleaseCallbackId;
- ch->previousSharedReleaseFences.emplace_back(std::move(futureFenceResult));
- ch->name = mName;
- } else if (FlagManager::getInstance().screenshot_fence_preservation()) {
- // If we didn't get a release callback yet, e.g. some scenarios when capturing screenshots
- // asynchronously, then make sure we don't drop the fence.
- mPreviousReleaseFenceAndContinuations.emplace_back(std::move(futureFenceResult),
- std::move(continuation));
- std::vector<FenceAndContinuation> mergedFences;
- sp<Fence> prevFence = nullptr;
- // For a layer that's frequently screenshotted, try to merge fences to make sure we don't
- // grow unbounded.
- for (const auto& futureAndContinuation : mPreviousReleaseFenceAndContinuations) {
- auto result = futureAndContinuation.future.wait_for(0s);
- if (result != std::future_status::ready) {
- mergedFences.emplace_back(futureAndContinuation);
- continue;
- }
-
- mergeFence(getDebugName(),
- futureAndContinuation.chain().get().value_or(Fence::NO_FENCE), prevFence);
- }
- if (prevFence != nullptr) {
- mergedFences.emplace_back(ftl::yield(FenceResult(std::move(prevFence))).share());
- }
-
- mPreviousReleaseFenceAndContinuations.swap(mergedFences);
- }
-
- if (mBufferInfo.mBuffer) {
- mPreviouslyPresentedLayerStacks.push_back(layerStack);
- }
-
- if (mDrawingState.frameNumber > 0) {
- mDrawingState.previousFrameNumber = mDrawingState.frameNumber;
- }
-}
-
void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
for (const auto& handle : mDrawingState.callbackHandles) {
handle->bufferReleaseChannel = mBufferReleaseChannel;
@@ -836,7 +845,7 @@
return true;
}
-void Layer::releasePreviousBuffer() {
+void Layer::releasePreviousBuffer() REQUIRES(mFlinger->mStateLock) {
mReleasePreviousBuffer = true;
if (!mBufferInfo.mBuffer ||
(!mDrawingState.buffer->hasSameBuffer(*mBufferInfo.mBuffer) ||
@@ -878,7 +887,8 @@
bool Layer::setBuffer(std::shared_ptr<renderengine::ExternalTexture>& buffer,
const BufferData& bufferData, nsecs_t postTime, nsecs_t desiredPresentTime,
- bool isAutoTimestamp, const FrameTimelineInfo& info, gui::GameMode gameMode) {
+ bool isAutoTimestamp, const FrameTimelineInfo& info, gui::GameMode gameMode)
+ REQUIRES(mFlinger->mStateLock) {
SFTRACE_FORMAT("setBuffer %s - hasBuffer=%s", getDebugName(), (buffer ? "true" : "false"));
const bool frameNumberChanged =
@@ -1068,7 +1078,8 @@
}
bool Layer::setSidebandStream(const sp<NativeHandle>& sidebandStream, const FrameTimelineInfo& info,
- nsecs_t postTime, gui::GameMode gameMode) {
+ nsecs_t postTime, gui::GameMode gameMode)
+ REQUIRES(mFlinger->mStateLock) {
if (mDrawingState.sidebandStream == sidebandStream) return false;
if (mDrawingState.sidebandStream != nullptr && sidebandStream == nullptr) {
@@ -1111,22 +1122,13 @@
handle->acquireTimeOrFence = mCallbackHandleAcquireTimeOrFence;
handle->frameNumber = mDrawingState.frameNumber;
handle->previousFrameNumber = mDrawingState.previousFrameNumber;
- if (FlagManager::getInstance().ce_fence_promise() &&
- mPreviousReleaseBufferEndpoint == handle->listener) {
+ if (mPreviousReleaseBufferEndpoint == handle->listener) {
// Add fence from previous screenshot now so that it can be dispatched to the
// client.
for (auto& [_, future] : mAdditionalPreviousReleaseFences) {
handle->previousReleaseFences.emplace_back(std::move(future));
}
mAdditionalPreviousReleaseFences.clear();
- } else if (FlagManager::getInstance().screenshot_fence_preservation() &&
- mPreviousReleaseBufferEndpoint == handle->listener) {
- // Add fences from previous screenshots now so that they can be dispatched to the
- // client.
- for (const auto& futureAndContinution : mPreviousReleaseFenceAndContinuations) {
- handle->previousSharedReleaseFences.emplace_back(futureAndContinution.chain());
- }
- mPreviousReleaseFenceAndContinuations.clear();
}
// Store so latched time and release fence can be set
mDrawingState.callbackHandles.push_back(handle);
@@ -1210,7 +1212,7 @@
return false;
}
-void Layer::updateTexImage(nsecs_t latchTime, bool bgColorOnly) {
+void Layer::updateTexImage(nsecs_t latchTime, bool bgColorOnly) REQUIRES(mFlinger->mStateLock) {
const State& s(getDrawingState());
if (!s.buffer) {
@@ -1318,8 +1320,17 @@
}
}
}
- if (lastDataspace != mBufferInfo.mDataspace) {
+ if (lastDataspace != mBufferInfo.mDataspace ||
+ mBufferInfo.mTimeSinceDataspaceUpdate == std::chrono::steady_clock::time_point::min()) {
mFlinger->mHdrLayerInfoChanged = true;
+ const auto currentTime = std::chrono::steady_clock::now();
+ if (mBufferInfo.mTimeSinceDataspaceUpdate > std::chrono::steady_clock::time_point::min()) {
+ mFlinger->mLayerEvents
+ .emplace_back(mOwnerUid, getSequence(), lastDataspace,
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ currentTime - mBufferInfo.mTimeSinceDataspaceUpdate));
+ }
+ mBufferInfo.mTimeSinceDataspaceUpdate = currentTime;
}
if (mBufferInfo.mDesiredHdrSdrRatio != mDrawingState.desiredHdrSdrRatio) {
mBufferInfo.mDesiredHdrSdrRatio = mDrawingState.desiredHdrSdrRatio;
@@ -1376,9 +1387,9 @@
handle->compositorTiming = compositorTiming;
}
- // Update mFrameTracker.
+ // Update mDeprecatedFrameTracker.
nsecs_t desiredPresentTime = mBufferInfo.mDesiredPresentTime;
- mFrameTracker.setDesiredPresentTime(desiredPresentTime);
+ mDeprecatedFrameTracker.setDesiredPresentTime(desiredPresentTime);
const int32_t layerId = getSequence();
mFlinger->mTimeStats->setDesiredTime(layerId, mCurrentFrameNumber, desiredPresentTime);
@@ -1398,15 +1409,15 @@
}
}
+ // The SurfaceFrame's AcquireFence is the same as this.
std::shared_ptr<FenceTime> frameReadyFence = mBufferInfo.mFenceTime;
if (frameReadyFence->isValid()) {
- mFrameTracker.setFrameReadyFence(std::move(frameReadyFence));
+ mDeprecatedFrameTracker.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);
+ mDeprecatedFrameTracker.setFrameReadyTime(desiredPresentTime);
}
-
if (display) {
const auto activeMode = display->refreshRateSelector().getActiveMode();
const Fps refreshRate = activeMode.fps;
@@ -1421,7 +1432,7 @@
mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber,
presentFence,
FrameTracer::FrameEvent::PRESENT_FENCE);
- mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
+ mDeprecatedFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
} else if (const auto displayId = PhysicalDisplayId::tryCast(display->getId());
displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
// The HWC doesn't support present fences, so use the present timestamp instead.
@@ -1442,15 +1453,17 @@
mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(),
mCurrentFrameNumber, actualPresentTime,
FrameTracer::FrameEvent::PRESENT_FENCE);
- mFrameTracker.setActualPresentTime(actualPresentTime);
+ mDeprecatedFrameTracker.setActualPresentTime(actualPresentTime);
}
}
- mFrameTracker.advanceFrame();
+ mFrameStatsHistorySize++;
+ mDeprecatedFrameTracker.advanceFrame();
mBufferInfo.mFrameLatencyNeeded = false;
}
-bool Layer::latchBufferImpl(bool& recomputeVisibleRegions, nsecs_t latchTime, bool bgColorOnly) {
+bool Layer::latchBufferImpl(bool& recomputeVisibleRegions, nsecs_t latchTime, bool bgColorOnly)
+ REQUIRES(mFlinger->mStateLock) {
SFTRACE_FORMAT_INSTANT("latchBuffer %s - %" PRIu64, getDebugName(),
getDrawingState().frameNumber);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index ce4b9c4..6af0f59 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -18,6 +18,7 @@
#include <android/gui/DropInputMode.h>
#include <android/gui/ISurfaceComposerClient.h>
+#include <com_android_graphics_surfaceflinger_flags.h>
#include <ftl/small_map.h>
#include <gui/BufferQueue.h>
#include <gui/LayerState.h>
@@ -44,6 +45,7 @@
#include <scheduler/Seamlessness.h>
#include <cstdint>
+#include <functional>
#include <optional>
#include <vector>
@@ -242,6 +244,8 @@
sp<Fence> mFence;
uint32_t mTransform{0};
ui::Dataspace mDataspace{ui::Dataspace::UNKNOWN};
+ std::chrono::steady_clock::time_point mTimeSinceDataspaceUpdate =
+ std::chrono::steady_clock::time_point::min();
Rect mCrop;
PixelFormat mPixelFormat{PIXEL_FORMAT_NONE};
bool mTransformToDisplayInverse{false};
@@ -257,8 +261,6 @@
bool fenceHasSignaled() const;
void onPreComposition(nsecs_t refreshStartTime);
- void onLayerDisplayed(ftl::SharedFuture<FenceResult>, ui::LayerStack layerStack,
- std::function<FenceResult(FenceResult)>&& continuation = nullptr);
// Tracks mLastClientCompositionFence and gets the callback handle for this layer.
sp<CallbackHandle> findCallbackHandle();
@@ -387,20 +389,6 @@
// from the layer.
std::vector<ui::LayerStack> mPreviouslyPresentedLayerStacks;
- struct FenceAndContinuation {
- ftl::SharedFuture<FenceResult> future;
- std::function<FenceResult(FenceResult)> continuation;
-
- ftl::SharedFuture<FenceResult> chain() const {
- if (continuation) {
- return ftl::Future(future).then(continuation).share();
- } else {
- return future;
- }
- }
- };
- std::vector<FenceAndContinuation> mPreviousReleaseFenceAndContinuations;
-
// Release fences for buffers that have not yet received a release
// callback. A release callback may not be given when capturing
// screenshots asynchronously. There may be no buffer update for the
@@ -447,8 +435,12 @@
uint32_t mTransactionFlags{0};
+ // Leverages FrameTimeline to generate FrameStats. Since FrameTimeline already has the data,
+ // statistical history needs to only be tracked by count of frames.
+ // TODO: Deprecate the '--latency-clear' and get rid of this.
+ std::atomic<uint16_t> mFrameStatsHistorySize;
// Timestamp history for UIAutomation. Thread safe.
- FrameTracker mFrameTracker;
+ FrameTracker mDeprecatedFrameTracker;
// main thread
sp<NativeHandle> mSidebandStream;
@@ -524,11 +516,6 @@
bool mGetHandleCalled = false;
- // The inherited shadow radius after taking into account the layer hierarchy. This is the
- // final shadow radius for this layer. If a shadow is specified for a layer, then effective
- // shadow radius is the set shadow radius, otherwise its the parent's shadow radius.
- float mEffectiveShadowRadius = 0.f;
-
// Game mode for the layer. Set by WindowManagerShell and recorded by SurfaceFlingerStats.
gui::GameMode mGameMode = gui::GameMode::Unsupported;
@@ -570,6 +557,9 @@
std::vector<std::pair<frontend::LayerHierarchy::TraversalPath, sp<LayerFE>>> mLayerFEs;
bool mHandleAlive = false;
+ std::optional<std::reference_wrapper<frametimeline::FrameTimeline>> getTimeline() const {
+ return *mFlinger->mFrameTimeline;
+ }
};
std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate);
diff --git a/services/surfaceflinger/LayerFE.cpp b/services/surfaceflinger/LayerFE.cpp
index b05f0ee..b619268 100644
--- a/services/surfaceflinger/LayerFE.cpp
+++ b/services/surfaceflinger/LayerFE.cpp
@@ -26,9 +26,7 @@
#include "LayerFE.h"
#include "SurfaceFlinger.h"
-#include "common/FlagManager.h"
#include "ui/FenceResult.h"
-#include "ui/LayerStack.h"
namespace android {
@@ -84,8 +82,7 @@
// Ensures that no promise is left unfulfilled before the LayerFE is destroyed.
// An unfulfilled promise could occur when a screenshot is attempted, but the
// render area is invalid and there is no memory for the capture result.
- if (FlagManager::getInstance().ce_fence_promise() &&
- mReleaseFencePromiseStatus == ReleaseFencePromiseStatus::INITIALIZED) {
+ if (mReleaseFencePromiseStatus == ReleaseFencePromiseStatus::INITIALIZED) {
setReleaseFence(Fence::NO_FENCE);
}
}
@@ -176,6 +173,7 @@
layerSettings.edgeExtensionEffect = mSnapshot->edgeExtensionEffect;
// Record the name of the layer for debugging further down the stack.
layerSettings.name = mSnapshot->name;
+ layerSettings.luts = mSnapshot->luts ? mSnapshot->luts : targetSettings.luts;
if (hasEffect() && !hasBufferOrSidebandStream()) {
prepareEffectsClientComposition(layerSettings, targetSettings);
@@ -193,6 +191,7 @@
layerSettings.disableBlending = true;
layerSettings.bufferId = 0;
layerSettings.frameNumber = 0;
+ layerSettings.sequence = -1;
// If layer is blacked out, force alpha to 1 so that we draw a black color layer.
layerSettings.alpha = blackout ? 1.0f : 0.0f;
@@ -264,6 +263,7 @@
layerSettings.source.buffer.maxLuminanceNits = maxLuminance;
layerSettings.frameNumber = mSnapshot->frameNumber;
layerSettings.bufferId = mSnapshot->externalTexture->getId();
+ layerSettings.sequence = mSnapshot->sequence;
const bool useFiltering = targetSettings.needsFiltering ||
mSnapshot->geomLayerTransform.needsBilinearFiltering();
@@ -344,13 +344,15 @@
caster.shadow = state;
}
-void LayerFE::onLayerDisplayed(ftl::SharedFuture<FenceResult> futureFenceResult,
- ui::LayerStack layerStack) {
- mCompositionResult.releaseFences.emplace_back(std::move(futureFenceResult), layerStack);
+void LayerFE::onPictureProfileCommitted() {
+ mCompositionResult.wasPictureProfileCommitted = true;
+ mCompositionResult.pictureProfileHandle = mSnapshot->pictureProfileHandle;
}
-CompositionResult&& LayerFE::stealCompositionResult() {
- return std::move(mCompositionResult);
+CompositionResult LayerFE::stealCompositionResult() {
+ CompositionResult result;
+ std::swap(mCompositionResult, result);
+ return result;
}
const char* LayerFE::getDebugName() const {
@@ -425,4 +427,13 @@
LayerFE::ReleaseFencePromiseStatus LayerFE::getReleaseFencePromiseStatus() {
return mReleaseFencePromiseStatus;
}
+
+void LayerFE::setLastHwcState(const LayerFE::HwcLayerDebugState &state) {
+ mLastHwcState = state;
+}
+
+const LayerFE::HwcLayerDebugState& LayerFE::getLastHwcState() const {
+ return mLastHwcState;
+};
+
} // namespace android
diff --git a/services/surfaceflinger/LayerFE.h b/services/surfaceflinger/LayerFE.h
index 658f949..a537456 100644
--- a/services/surfaceflinger/LayerFE.h
+++ b/services/surfaceflinger/LayerFE.h
@@ -18,19 +18,24 @@
#include <android/gui/CachingHint.h>
#include <gui/LayerMetadata.h>
+#include <ui/LayerStack.h>
+#include <ui/PictureProfileHandle.h>
+
#include "FrontEnd/LayerSnapshot.h"
#include "compositionengine/LayerFE.h"
#include "compositionengine/LayerFECompositionState.h"
#include "renderengine/LayerSettings.h"
-#include "ui/LayerStack.h"
#include <ftl/future.h>
namespace android {
struct CompositionResult {
- std::vector<std::pair<ftl::SharedFuture<FenceResult>, ui::LayerStack>> releaseFences;
sp<Fence> lastClientCompositionFence = nullptr;
+ bool wasPictureProfileCommitted = false;
+ // TODO(b/337330263): Why does LayerFE coming from SF have a null composition state?
+ // It would be better not to duplicate this information
+ PictureProfileHandle pictureProfileHandle = PictureProfileHandle::NONE;
};
class LayerFE : public virtual RefBase, public virtual compositionengine::LayerFE {
@@ -41,7 +46,6 @@
// compositionengine::LayerFE overrides
const compositionengine::LayerFECompositionState* getCompositionState() const override;
bool onPreComposition(bool updatingOutputGeometryThisFrame) override;
- void onLayerDisplayed(ftl::SharedFuture<FenceResult>, ui::LayerStack) override;
const char* getDebugName() const override;
int32_t getSequence() const override;
bool hasRoundedCorners() const override;
@@ -50,10 +54,15 @@
const gui::LayerMetadata* getRelativeMetadata() const override;
std::optional<compositionengine::LayerFE::LayerSettings> prepareClientComposition(
compositionengine::LayerFE::ClientCompositionTargetSettings&) const;
- CompositionResult&& stealCompositionResult();
+ CompositionResult stealCompositionResult();
ftl::Future<FenceResult> createReleaseFenceFuture() override;
void setReleaseFence(const FenceResult& releaseFence) override;
LayerFE::ReleaseFencePromiseStatus getReleaseFencePromiseStatus() override;
+ void onPictureProfileCommitted() override;
+
+ // Used for debugging purposes, e.g. perfetto tracing, dumpsys.
+ void setLastHwcState(const HwcLayerDebugState &state) override;
+ const HwcLayerDebugState &getLastHwcState() const override;
std::unique_ptr<surfaceflinger::frontend::LayerSnapshot> mSnapshot;
@@ -85,6 +94,7 @@
std::string mName;
std::promise<FenceResult> mReleaseFence;
ReleaseFencePromiseStatus mReleaseFencePromiseStatus = ReleaseFencePromiseStatus::UNINITIALIZED;
+ HwcLayerDebugState mLastHwcState;
};
} // namespace android
diff --git a/services/surfaceflinger/LayerRenderArea.cpp b/services/surfaceflinger/LayerRenderArea.cpp
deleted file mode 100644
index bfe6d2a..0000000
--- a/services/surfaceflinger/LayerRenderArea.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <ui/GraphicTypes.h>
-#include <ui/Transform.h>
-
-#include "DisplayDevice.h"
-#include "FrontEnd/LayerCreationArgs.h"
-#include "Layer.h"
-#include "LayerRenderArea.h"
-#include "SurfaceFlinger.h"
-
-namespace android {
-
-LayerRenderArea::LayerRenderArea(sp<Layer> layer, frontend::LayerSnapshot layerSnapshot,
- const Rect& crop, ui::Size reqSize, ui::Dataspace reqDataSpace,
- const ui::Transform& layerTransform, const Rect& layerBufferSize,
- ftl::Flags<RenderArea::Options> options)
- : RenderArea(reqSize, CaptureFill::CLEAR, reqDataSpace, options),
- mLayer(std::move(layer)),
- mLayerSnapshot(std::move(layerSnapshot)),
- mLayerBufferSize(layerBufferSize),
- mCrop(crop),
- mTransform(layerTransform) {}
-
-const ui::Transform& LayerRenderArea::getTransform() const {
- return mTransform;
-}
-
-bool LayerRenderArea::isSecure() const {
- return mOptions.test(Options::CAPTURE_SECURE_LAYERS);
-}
-
-sp<const DisplayDevice> LayerRenderArea::getDisplayDevice() const {
- return nullptr;
-}
-
-Rect LayerRenderArea::getSourceCrop() const {
- if (mCrop.isEmpty()) {
- // TODO this should probably be mBounds instead of just buffer bounds
- return mLayerBufferSize;
- } else {
- return mCrop;
- }
-}
-
-} // namespace android
diff --git a/services/surfaceflinger/LayerRenderArea.h b/services/surfaceflinger/LayerRenderArea.h
deleted file mode 100644
index f72c7c7..0000000
--- a/services/surfaceflinger/LayerRenderArea.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2020 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 <string>
-
-#include <ui/GraphicTypes.h>
-#include <ui/Transform.h>
-#include <utils/StrongPointer.h>
-
-#include "RenderArea.h"
-
-namespace android {
-
-class DisplayDevice;
-class Layer;
-class SurfaceFlinger;
-
-class LayerRenderArea : public RenderArea {
-public:
- LayerRenderArea(sp<Layer> layer, frontend::LayerSnapshot layerSnapshot, const Rect& crop,
- ui::Size reqSize, ui::Dataspace reqDataSpace,
- const ui::Transform& layerTransform, const Rect& layerBufferSize,
- ftl::Flags<RenderArea::Options> options);
-
- const ui::Transform& getTransform() const override;
- bool isSecure() const override;
- sp<const DisplayDevice> getDisplayDevice() const override;
- Rect getSourceCrop() const override;
-
- sp<Layer> getParentLayer() const override { return mLayer; }
- const frontend::LayerSnapshot* getLayerSnapshot() const override { return &mLayerSnapshot; }
-
-private:
- const sp<Layer> mLayer;
- const frontend::LayerSnapshot mLayerSnapshot;
- const Rect mLayerBufferSize;
- const Rect mCrop;
-
- ui::Transform mTransform;
-};
-
-} // namespace android
diff --git a/services/surfaceflinger/OWNERS b/services/surfaceflinger/OWNERS
index fa0ecee..13edd16 100644
--- a/services/surfaceflinger/OWNERS
+++ b/services/surfaceflinger/OWNERS
@@ -12,6 +12,5 @@
ramindani@google.com
rnlee@google.com
sallyqi@google.com
-scroggo@google.com
vishnun@google.com
xwxw@google.com
diff --git a/services/surfaceflinger/PowerAdvisor/Android.bp b/services/surfaceflinger/PowerAdvisor/Android.bp
new file mode 100644
index 0000000..4efbcb9
--- /dev/null
+++ b/services/surfaceflinger/PowerAdvisor/Android.bp
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2024 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.
+ */
+
+// ADPF uses FMQ which can't build to CPP backend, and is thus not
+// compatible with the rest of SF aidl for this reason
+
+aidl_interface {
+ name: "android.adpf.sessionmanager_aidl",
+ srcs: [
+ "aidl/android/adpf/*.aidl",
+ ],
+ local_include_dir: "aidl",
+ unstable: true,
+ backend: {
+ java: {
+ sdk_version: "module_current",
+ enabled: true,
+ },
+ cpp: {
+ enabled: false,
+ },
+ ndk: {
+ enabled: true,
+ },
+ },
+}
+
+cc_defaults {
+ name: "poweradvisor_deps",
+ shared_libs: [
+ "libpowermanager",
+ "android.adpf.sessionmanager_aidl-ndk",
+ ],
+}
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp b/services/surfaceflinger/PowerAdvisor/Common.h
similarity index 62%
copy from services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp
copy to services/surfaceflinger/PowerAdvisor/Common.h
index d383283..b4a87dd 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp
+++ b/services/surfaceflinger/PowerAdvisor/Common.h
@@ -14,12 +14,15 @@
* limitations under the License.
*/
-#include "mock/DisplayHardware/MockPowerHintSessionWrapper.h"
+#pragma once
-namespace android::Hwc2::mock {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+#include <aidl/android/adpf/ISessionManager.h>
+#include <aidl/android/hardware/power/CompositionData.h>
+#pragma clang diagnostic pop
-// Explicit default instantiation is recommended.
-MockPowerHintSessionWrapper::MockPowerHintSessionWrapper()
- : power::PowerHintSessionWrapper(nullptr) {}
-
-} // namespace android::Hwc2::mock
+namespace android::adpf {
+using namespace ::aidl::android::adpf;
+namespace hal = ::aidl::android::hardware::power;
+} // namespace android::adpf
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/PowerAdvisor/PowerAdvisor.cpp
similarity index 85%
rename from services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
rename to services/surfaceflinger/PowerAdvisor/PowerAdvisor.cpp
index 334c104..cd7210c 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
+++ b/services/surfaceflinger/PowerAdvisor/PowerAdvisor.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-//#define LOG_NDEBUG 0
+// #define LOG_NDEBUG 0
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
@@ -24,54 +24,39 @@
#include <unistd.h>
#include <cinttypes>
#include <cstdint>
+#include <functional>
#include <optional>
#include <android-base/properties.h>
+#include <android/binder_libbinder.h>
+#include <common/WorkloadTracer.h>
#include <common/trace.h>
+#include <ftl/concat.h>
#include <utils/Log.h>
#include <utils/Mutex.h>
#include <binder/IServiceManager.h>
-#include "../SurfaceFlingerProperties.h"
+#include <powermanager/PowerHalController.h>
+#include <powermanager/PowerHintSessionWrapper.h>
+#include <common/FlagManager.h>
#include "PowerAdvisor.h"
-#include "SurfaceFlinger.h"
+#include "SessionManager.h"
-namespace android {
-namespace Hwc2 {
+namespace android::adpf::impl {
-PowerAdvisor::~PowerAdvisor() = default;
-
-namespace impl {
-
-using aidl::android::hardware::power::Boost;
-using aidl::android::hardware::power::ChannelConfig;
-using aidl::android::hardware::power::Mode;
-using aidl::android::hardware::power::SessionHint;
-using aidl::android::hardware::power::SessionTag;
-using aidl::android::hardware::power::WorkDuration;
-using aidl::android::hardware::power::WorkDurationFixedV1;
-
-using aidl::android::hardware::common::fmq::MQDescriptor;
+using namespace android::ftl::flag_operators;
using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
-using aidl::android::hardware::power::ChannelMessage;
using android::hardware::EventFlag;
-using ChannelMessageContents = ChannelMessage::ChannelMessageContents;
-using MsgQueue = android::AidlMessageQueue<ChannelMessage, SynchronizedReadWrite>;
+using ChannelMessageContents = hal::ChannelMessage::ChannelMessageContents;
+using MsgQueue = android::AidlMessageQueue<hal::ChannelMessage, SynchronizedReadWrite>;
using FlagQueue = android::AidlMessageQueue<int8_t, SynchronizedReadWrite>;
PowerAdvisor::~PowerAdvisor() = default;
namespace {
-std::chrono::milliseconds getUpdateTimeout() {
- // Default to a timeout of 80ms if nothing else is specified
- static std::chrono::milliseconds timeout =
- std::chrono::milliseconds(sysprop::display_update_imminent_timeout_ms(80));
- return timeout;
-}
-
void traceExpensiveRendering(bool enabled) {
if (enabled) {
SFTRACE_ASYNC_BEGIN("ExpensiveRendering", 0);
@@ -80,30 +65,34 @@
}
}
+static constexpr ftl::Flags<Workload> TRIGGER_LOAD_CHANGE_HINTS = Workload::EFFECTS |
+ Workload::VISIBLE_REGION | Workload::DISPLAY_CHANGES | Workload::SCREENSHOT;
} // namespace
-PowerAdvisor::PowerAdvisor(SurfaceFlinger& flinger)
- : mPowerHal(std::make_unique<power::PowerHalController>()), mFlinger(flinger) {
- if (getUpdateTimeout() > 0ms) {
- mScreenUpdateTimer.emplace("UpdateImminentTimer", getUpdateTimeout(),
+PowerAdvisor::PowerAdvisor(std::function<void()>&& sfDisableExpensiveFn,
+ std::chrono::milliseconds timeout)
+ : mPowerHal(std::make_unique<power::PowerHalController>()) {
+ if (timeout > 0ms) {
+ mScreenUpdateTimer.emplace("UpdateImminentTimer", timeout,
/* resetCallback */ nullptr,
/* timeoutCallback */
- [this] {
+ [this, disableExpensiveFn = std::move(sfDisableExpensiveFn),
+ timeout] {
while (true) {
auto timeSinceLastUpdate = std::chrono::nanoseconds(
systemTime() - mLastScreenUpdatedTime.load());
- if (timeSinceLastUpdate >= getUpdateTimeout()) {
+ if (timeSinceLastUpdate >= timeout) {
break;
}
// We may try to disable expensive rendering and allow
// for sending DISPLAY_UPDATE_IMMINENT hints too early if
// we idled very shortly after updating the screen, so
// make sure we wait enough time.
- std::this_thread::sleep_for(getUpdateTimeout() -
+ std::this_thread::sleep_for(timeout -
timeSinceLastUpdate);
}
mSendUpdateImminent.store(true);
- mFlinger.disableExpensiveRendering();
+ disableExpensiveFn();
});
}
}
@@ -132,7 +121,7 @@
const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
- auto ret = getPowerHal().setMode(Mode::EXPENSIVE_RENDERING, expectsExpensiveRendering);
+ auto ret = getPowerHal().setMode(hal::Mode::EXPENSIVE_RENDERING, expectsExpensiveRendering);
if (!ret.isOk()) {
if (ret.isUnsupported()) {
mHasExpensiveRendering = false;
@@ -151,7 +140,7 @@
if (!mBootFinished.load()) {
return;
}
- sendHintSessionHint(SessionHint::CPU_LOAD_UP);
+ sendHintSessionHint(hal::SessionHint::CPU_LOAD_UP);
}
void PowerAdvisor::notifyDisplayUpdateImminentAndCpuReset() {
@@ -163,12 +152,12 @@
if (mSendUpdateImminent.exchange(false)) {
ALOGV("AIDL notifyDisplayUpdateImminentAndCpuReset");
- sendHintSessionHint(SessionHint::CPU_LOAD_RESET);
+ sendHintSessionHint(hal::SessionHint::CPU_LOAD_RESET);
if (!mHasDisplayUpdateImminent) {
ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
} else {
- auto ret = getPowerHal().setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
+ auto ret = getPowerHal().setBoost(hal::Boost::DISPLAY_UPDATE_IMMINENT, 0);
if (ret.isUnsupported()) {
mHasDisplayUpdateImminent = false;
}
@@ -205,7 +194,7 @@
FlagManager::getInstance().adpf_use_fmq_channel();
}
-void PowerAdvisor::sendHintSessionHint(SessionHint hint) {
+void PowerAdvisor::sendHintSessionHint(hal::SessionHint hint) {
if (!mBootFinished || !usePowerHintSession()) {
ALOGV("Power hint session is not enabled, skip sending session hint");
return;
@@ -236,11 +225,12 @@
static_cast<int32_t>(getuid()),
mHintSessionThreadIds,
mTargetDuration.ns(),
- SessionTag::SURFACEFLINGER,
+ hal::SessionTag::SURFACEFLINGER,
&mSessionConfig);
if (ret.isOk()) {
mHintSession = ret.value();
- if (FlagManager::getInstance().adpf_use_fmq_channel_fixed()) {
+ if (FlagManager::getInstance().adpf_use_fmq_channel_fixed() &&
+ FlagManager::getInstance().adpf_fmq_sf()) {
setUpFmq();
}
}
@@ -325,7 +315,7 @@
return;
}
SFTRACE_CALL();
- std::optional<WorkDuration> actualDuration = estimateWorkDuration();
+ std::optional<hal::WorkDuration> actualDuration = estimateWorkDuration();
if (!actualDuration.has_value() || actualDuration->durationNanos < 0) {
ALOGV("Failed to send actual work duration, skipping");
return;
@@ -376,7 +366,7 @@
mHintSessionQueue.clear();
}
-template <ChannelMessage::ChannelMessageContents::Tag T, class In>
+template <hal::ChannelMessage::ChannelMessageContents::Tag T, class In>
bool PowerAdvisor::writeHintSessionMessage(In* contents, size_t count) {
if (!mMsgQueue) {
ALOGV("Skip using FMQ with message tag %hhd as it's not supported", T);
@@ -394,13 +384,13 @@
}
for (size_t i = 0; i < count; ++i) {
if constexpr (T == ChannelMessageContents::Tag::workDuration) {
- const WorkDuration& duration = contents[i];
- new (tx.getSlot(i)) ChannelMessage{
+ const hal::WorkDuration& duration = contents[i];
+ new (tx.getSlot(i)) hal::ChannelMessage{
.sessionID = static_cast<int32_t>(mSessionConfig.id),
.timeStampNanos =
(i == count - 1) ? ::android::uptimeNanos() : duration.timeStampNanos,
.data = ChannelMessageContents::make<ChannelMessageContents::Tag::workDuration,
- WorkDurationFixedV1>({
+ hal::WorkDurationFixedV1>({
.durationNanos = duration.durationNanos,
.workPeriodStartTimestampNanos = duration.workPeriodStartTimestampNanos,
.cpuDurationNanos = duration.cpuDurationNanos,
@@ -408,7 +398,7 @@
}),
};
} else {
- new (tx.getSlot(i)) ChannelMessage{
+ new (tx.getSlot(i)) hal::ChannelMessage{
.sessionID = static_cast<int32_t>(mSessionConfig.id),
.timeStampNanos = ::android::uptimeNanos(),
.data = ChannelMessageContents::make<T, In>(std::move(contents[i])),
@@ -557,6 +547,18 @@
mTotalFrameTargetDuration = targetDuration;
}
+std::shared_ptr<SessionManager> PowerAdvisor::getSessionManager() {
+ return mSessionManager;
+}
+
+sp<IBinder> PowerAdvisor::getOrCreateSessionManagerForBinder(uid_t uid) {
+ // Flag guards the creation of SessionManager
+ if (mSessionManager == nullptr && FlagManager::getInstance().adpf_native_session_manager()) {
+ mSessionManager = ndk::SharedRefBase::make<SessionManager>(uid);
+ }
+ return AIBinder_toPlatformBinder(mSessionManager->asBinder().get());
+}
+
std::vector<DisplayId> PowerAdvisor::getOrderedDisplayIds(
std::optional<TimePoint> DisplayTimingData::*sortBy) {
std::vector<DisplayId> sortedDisplays;
@@ -571,7 +573,7 @@
return sortedDisplays;
}
-std::optional<WorkDuration> PowerAdvisor::estimateWorkDuration() {
+std::optional<hal::WorkDuration> PowerAdvisor::estimateWorkDuration() {
if (!mExpectedPresentTimes.isFull() || !mCommitStartTimes.isFull()) {
return std::nullopt;
}
@@ -656,7 +658,7 @@
Duration combinedDuration = combineTimingEstimates(totalDuration, flingerDuration);
Duration cpuDuration = combineTimingEstimates(totalDurationWithoutGpu, flingerDuration);
- WorkDuration duration{
+ hal::WorkDuration duration{
.timeStampNanos = TimePoint::now().ns(),
.durationNanos = combinedDuration.ns(),
.workPeriodStartTimestampNanos = mCommitStartTimes[0].ns(),
@@ -759,6 +761,58 @@
return *mPowerHal;
}
-} // namespace impl
-} // namespace Hwc2
-} // namespace android
+void PowerAdvisor::setQueuedWorkload(ftl::Flags<Workload> queued) {
+ queued &= TRIGGER_LOAD_CHANGE_HINTS;
+ if (!(queued).get()) return;
+ uint32_t previousQueuedWorkload = mQueuedWorkload.fetch_or(queued.get());
+
+ uint32_t newHints = (previousQueuedWorkload ^ queued.get()) & queued.get();
+ if (newHints) {
+ SFTRACE_INSTANT_FOR_TRACK(WorkloadTracer::TRACK_NAME,
+ ftl::Concat("QueuedWorkload: ",
+ ftl::truncated<20>(ftl::Flags<Workload>(newHints)
+ .string()
+ .c_str()))
+ .c_str());
+ }
+ if (!previousQueuedWorkload) {
+ // TODO(b/385028458) maybe load up hint if close to wake up
+ }
+}
+
+void PowerAdvisor::setScreenshotWorkload() {
+ mCommittedWorkload |= Workload::SCREENSHOT;
+}
+
+void PowerAdvisor::setCommittedWorkload(ftl::Flags<Workload> workload) {
+ workload &= TRIGGER_LOAD_CHANGE_HINTS;
+ uint32_t queued = mQueuedWorkload.exchange(0);
+ mCommittedWorkload |= workload;
+
+ bool cancelLoadupHint = queued && !mCommittedWorkload.get();
+ if (cancelLoadupHint) {
+ SFTRACE_INSTANT_FOR_TRACK(WorkloadTracer::TRACK_NAME,
+ ftl::Concat("UncommittedQueuedWorkload: ",
+ ftl::truncated<20>(ftl::Flags<Workload>(queued)
+ .string()
+ .c_str()))
+ .c_str());
+ // TODO(b/385028458) cancel load up hint
+ }
+
+ bool increasedWorkload = queued == 0 && mCommittedWorkload.get() != 0;
+ if (increasedWorkload) {
+ SFTRACE_INSTANT_FOR_TRACK(WorkloadTracer::TRACK_NAME,
+ ftl::Concat("CommittedWorkload: ",
+ ftl::truncated<20>(mCommittedWorkload.string()))
+ .c_str());
+
+ // TODO(b/385028458) load up hint
+ }
+}
+
+void PowerAdvisor::setCompositedWorkload(ftl::Flags<Workload> composited) {
+ composited &= TRIGGER_LOAD_CHANGE_HINTS;
+ mCommittedWorkload = composited;
+}
+} // namespace android::adpf::impl
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/PowerAdvisor/PowerAdvisor.h
similarity index 83%
rename from services/surfaceflinger/DisplayHardware/PowerAdvisor.h
rename to services/surfaceflinger/PowerAdvisor/PowerAdvisor.h
index 1076b2b..540a9df 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
+++ b/services/surfaceflinger/PowerAdvisor/PowerAdvisor.h
@@ -17,7 +17,7 @@
#pragma once
#include <atomic>
-#include <chrono>
+#include <future>
#include <unordered_map>
#include <unordered_set>
@@ -30,25 +30,33 @@
#pragma clang diagnostic ignored "-Wconversion"
#include <aidl/android/hardware/power/IPower.h>
#include <fmq/AidlMessageQueue.h>
-#include <powermanager/PowerHalController.h>
#pragma clang diagnostic pop
-#include <compositionengine/impl/OutputCompositionState.h>
+#include <common/trace.h>
+#include <ftl/flags.h>
#include <scheduler/Time.h>
#include <ui/DisplayIdentification.h>
#include "../Scheduler/OneShotTimer.h"
+#include "Workload.h"
+
+#include "SessionManager.h"
using namespace std::chrono_literals;
namespace android {
-class SurfaceFlinger;
+namespace power {
+class PowerHalController;
+class PowerHintSessionWrapper;
+} // namespace power
-namespace Hwc2 {
+namespace adpf {
+
+namespace hal = aidl::android::hardware::power;
class PowerAdvisor {
public:
- virtual ~PowerAdvisor();
+ virtual ~PowerAdvisor() = default;
// Initializes resources that cannot be initialized on construction
virtual void init() = 0;
@@ -101,21 +109,47 @@
virtual void setDisplays(std::vector<DisplayId>& displayIds) = 0;
// Sets the target duration for the entire pipeline including the gpu
virtual void setTotalFrameTargetWorkDuration(Duration targetDuration) = 0;
+ // Get the session manager, if it exists
+ virtual std::shared_ptr<SessionManager> getSessionManager() = 0;
+
+ // --- Track per frame workloads to use for load up hint heuristics
+ // Track queued workload from transactions as they are queued from the binder thread.
+ // The workload is accumulated and reset on frame commit. The queued workload may be
+ // relevant for the next frame so can be used as an early load up hint. Note this is
+ // only a hint because the transaction can remain in the queue and not be applied on
+ // the next frame.
+ virtual void setQueuedWorkload(ftl::Flags<Workload> workload) = 0;
+ // Track additional workload dur to a screenshot request for load up hint heuristics. This
+ // would indicate an immediate increase in GPU workload.
+ virtual void setScreenshotWorkload() = 0;
+ // Track committed workload from transactions that are applied on the main thread.
+ // This workload is determined from the applied transactions. This can provide a high
+ // confidence that the CPU and or GPU workload will increase immediately.
+ virtual void setCommittedWorkload(ftl::Flags<Workload> workload) = 0;
+ // Update committed workload with the actual workload from post composition. This is
+ // used to update the baseline workload so we can detect increases in workloads on the
+ // next commit. We use composite instead of commit to update the baseline to account
+ // for optimizations like caching which may reduce the workload.
+ virtual void setCompositedWorkload(ftl::Flags<Workload> workload) = 0;
// --- The following methods may run on threads besides SF main ---
// Send a hint about an upcoming increase in the CPU workload
virtual void notifyCpuLoadUp() = 0;
// Send a hint about the imminent start of a new CPU workload
virtual void notifyDisplayUpdateImminentAndCpuReset() = 0;
+
+ // --- The following methods specifically run on binder threads ---
+ // Retrieve a SessionManager for HintManagerService to call
+ virtual sp<IBinder> getOrCreateSessionManagerForBinder(uid_t uid) = 0;
};
namespace impl {
// PowerAdvisor is a wrapper around IPower HAL which takes into account the
// full state of the system when sending out power hints to things like the GPU.
-class PowerAdvisor final : public Hwc2::PowerAdvisor {
+class PowerAdvisor final : public adpf::PowerAdvisor {
public:
- PowerAdvisor(SurfaceFlinger& flinger);
+ PowerAdvisor(std::function<void()>&& function, std::chrono::milliseconds timeout);
~PowerAdvisor() override;
void init() override;
@@ -145,11 +179,20 @@
void setCompositeEnd(TimePoint compositeEndTime) override;
void setDisplays(std::vector<DisplayId>& displayIds) override;
void setTotalFrameTargetWorkDuration(Duration targetDuration) override;
+ std::shared_ptr<SessionManager> getSessionManager() override;
+
+ void setQueuedWorkload(ftl::Flags<Workload> workload) override;
+ void setScreenshotWorkload() override;
+ void setCommittedWorkload(ftl::Flags<Workload> workload) override;
+ void setCompositedWorkload(ftl::Flags<Workload> workload) override;
// --- The following methods may run on threads besides SF main ---
void notifyCpuLoadUp() override;
void notifyDisplayUpdateImminentAndCpuReset() override;
+ // --- The following methods specifically run on binder threads ---
+ sp<IBinder> getOrCreateSessionManagerForBinder(uid_t uid) override;
+
private:
friend class PowerAdvisorTest;
@@ -159,7 +202,6 @@
std::unordered_set<DisplayId> mExpensiveDisplays;
bool mNotifiedExpensiveRendering = false;
- SurfaceFlinger& mFlinger;
std::atomic_bool mSendUpdateImminent = true;
std::atomic<nsecs_t> mLastScreenUpdatedTime = 0;
std::optional<scheduler::OneShotTimer> mScreenUpdateTimer;
@@ -318,13 +360,20 @@
static constexpr const Duration kFenceWaitStartDelayValidated{150us};
static constexpr const Duration kFenceWaitStartDelaySkippedValidate{250us};
+ // Track queued and committed workloads per frame. Queued workload is atomic because it's
+ // updated on both binder and the main thread.
+ std::atomic<uint32_t> mQueuedWorkload;
+ ftl::Flags<Workload> mCommittedWorkload;
+
void sendHintSessionHint(aidl::android::hardware::power::SessionHint hint);
template <aidl::android::hardware::power::ChannelMessage::ChannelMessageContents::Tag T,
class In>
bool writeHintSessionMessage(In* elements, size_t count) REQUIRES(mHintSessionMutex);
+
+ std::shared_ptr<SessionManager> mSessionManager;
};
} // namespace impl
-} // namespace Hwc2
+} // namespace adpf
} // namespace android
diff --git a/services/surfaceflinger/PowerAdvisor/SessionLayerMap.cpp b/services/surfaceflinger/PowerAdvisor/SessionLayerMap.cpp
new file mode 100644
index 0000000..9f95163
--- /dev/null
+++ b/services/surfaceflinger/PowerAdvisor/SessionLayerMap.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2024 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 "SessionLayerMap.h"
+#include <android/binder_libbinder.h>
+
+namespace android::adpf {
+
+void SessionLayerMap::notifySessionsDied(std::vector<int32_t>& sessionIds) {
+ for (int id : sessionIds) {
+ auto&& iter = mSessions.find(id);
+ if (iter != mSessions.end()) {
+ mSessions.erase(iter);
+ }
+ }
+}
+
+void SessionLayerMap::notifyLayersDied(std::vector<int32_t>& layers) {
+ for (auto&& layer : layers) {
+ auto&& iter = mLayers.find(layer);
+ if (iter != mLayers.end()) {
+ mLayers.erase(iter);
+ }
+ }
+}
+
+bool SessionLayerMap::bindSessionIDToLayers(int sessionId, const std::vector<int32_t>& layerIds) {
+ // If there is no association, just drop from map
+ if (layerIds.empty()) {
+ mSessions.erase(sessionId);
+ return false;
+ }
+
+ // Ensure session exists
+ if (!mSessions.contains(sessionId)) {
+ mSessions.emplace(sessionId, MappedType(sessionId, mLayers));
+ }
+
+ MappedType& session = mSessions.at(sessionId);
+ std::set<int32_t> newLinks;
+
+ // For each incoming link
+ for (auto&& layerId : layerIds) {
+ auto&& iter = mLayers.find(layerId);
+
+ // If it's not in the map, add it
+ if (iter == mLayers.end()) {
+ mLayers.emplace(layerId, MappedType(layerId, mSessions));
+ }
+
+ // Make a ref to it in the session's new association map
+ newLinks.insert(layerId);
+ }
+
+ session.swapLinks(std::move(newLinks));
+ return true;
+}
+
+void SessionLayerMap::getAssociatedSessions(int32_t layerId, std::vector<int32_t>& sessionIdsOut) {
+ sessionIdsOut.clear();
+ auto&& iter = mLayers.find(layerId);
+
+ if (iter == mLayers.end()) {
+ return;
+ }
+
+ // Dump the internal association set into this vector
+ sessionIdsOut.insert(sessionIdsOut.begin(), iter->second.mLinks.begin(),
+ iter->second.mLinks.end());
+}
+
+void SessionLayerMap::getCurrentlyRelevantLayers(
+ std::unordered_set<int32_t>& currentlyRelevantLayers) {
+ currentlyRelevantLayers.clear();
+ for (auto&& layer : mLayers) {
+ currentlyRelevantLayers.insert(layer.first);
+ }
+}
+
+} // namespace android::adpf
\ No newline at end of file
diff --git a/services/surfaceflinger/PowerAdvisor/SessionLayerMap.h b/services/surfaceflinger/PowerAdvisor/SessionLayerMap.h
new file mode 100644
index 0000000..51808a6
--- /dev/null
+++ b/services/surfaceflinger/PowerAdvisor/SessionLayerMap.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2024 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 <log/log.h>
+#include <set>
+#include <unordered_map>
+#include <unordered_set>
+
+namespace android::adpf {
+
+class SessionLayerMap {
+public:
+ // Inform the SessionLayerMap about dead sessions
+ void notifySessionsDied(std::vector<int32_t>& sessionIds);
+ // Inform the SessionLayerMap about dead layers
+ void notifyLayersDied(std::vector<int32_t>& layers);
+ // Associate a session with a specific set of layer ids
+ bool bindSessionIDToLayers(int sessionId, const std::vector<int32_t>& layerIds);
+ // Get the set of sessions that are mapped to a specific layer id
+ void getAssociatedSessions(int32_t layerId, std::vector<int32_t>& sessionIdsOut);
+ // Get the set of layers that are currently being tracked
+ void getCurrentlyRelevantLayers(std::unordered_set<int32_t>& currentlyRelevantLayers);
+
+private:
+ struct MappedType {
+ MappedType(int32_t id, std::unordered_map<int32_t, MappedType>& otherList)
+ : mId(id), mOtherList(otherList) {};
+ MappedType() = delete;
+ ~MappedType() { swapLinks({}); }
+
+ // Replace the set of associated IDs for this mapped type with a different set of IDs,
+ // updating only associations which have changed between the two sets
+ void swapLinks(std::set<int32_t>&& incoming) {
+ auto&& oldIter = mLinks.begin();
+ auto&& newIter = incoming.begin();
+
+ // Dump all outdated values and insert new ones
+ while (oldIter != mLinks.end() || newIter != incoming.end()) {
+ // If there is a value in the new set but not the old set
+ // We should have already ensured what we're linking to exists
+ if (oldIter == mLinks.end() || (newIter != incoming.end() && *newIter < *oldIter)) {
+ addRemoteAssociation(*newIter);
+ ++newIter;
+ continue;
+ }
+
+ // If there is a value in the old set but not the new set
+ if (newIter == incoming.end() || (oldIter != mLinks.end() && *oldIter < *newIter)) {
+ dropRemoteAssociation(*oldIter);
+ ++oldIter;
+ continue;
+ }
+
+ // If they're the same, skip
+ if (*oldIter == *newIter) {
+ ++oldIter;
+ ++newIter;
+ continue;
+ }
+ }
+
+ mLinks.swap(incoming);
+ }
+
+ void addRemoteAssociation(int32_t other) {
+ auto&& iter = mOtherList.find(other);
+ if (iter != mOtherList.end()) {
+ iter->second.mLinks.insert(mId);
+ } else {
+ ALOGE("Existing entry in SessionLayerMap, link failed");
+ }
+ }
+
+ void dropRemoteAssociation(int32_t other) {
+ auto&& iter = mOtherList.find(other);
+ if (iter != mOtherList.end()) {
+ iter->second.mLinks.erase(mId);
+ if (iter->second.mLinks.empty()) {
+ // This only erases them from the map, not from general tracking
+ mOtherList.erase(iter);
+ }
+ } else {
+ ALOGE("Missing entry in SessionLayerMap, unlinking failed");
+ }
+ }
+
+ int32_t mId;
+ std::set<int> mLinks;
+ std::unordered_map<int32_t, MappedType>& mOtherList;
+ };
+
+ std::unordered_map<int32_t, MappedType> mSessions;
+ std::unordered_map<int32_t, MappedType> mLayers;
+};
+
+} // namespace android::adpf
diff --git a/services/surfaceflinger/PowerAdvisor/SessionManager.cpp b/services/surfaceflinger/PowerAdvisor/SessionManager.cpp
new file mode 100644
index 0000000..a855f07
--- /dev/null
+++ b/services/surfaceflinger/PowerAdvisor/SessionManager.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2024 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 "PowerAdvisor/SessionManager.h"
+#include <android/binder_libbinder.h>
+#include <android/binder_status.h>
+#include <binder/IPCThreadState.h>
+#include "FrontEnd/LayerHandle.h"
+#include "Layer.h"
+#include "SurfaceFlinger.h"
+
+namespace android::adpf {
+
+SessionManager::SessionManager(uid_t uid) : mUid(uid) {}
+
+ndk::ScopedAStatus SessionManager::associateSessionToLayers(
+ int32_t sessionId, int32_t ownerUid, const std::vector<::ndk::SpAIBinder>& layerTokens) {
+ std::scoped_lock lock{mSessionManagerMutex};
+
+ std::vector<int32_t> layerIds;
+
+ for (auto&& token : layerTokens) {
+ auto platformToken = AIBinder_toPlatformBinder(token.get());
+
+ // Get the layer id for it
+ int32_t layerId =
+ static_cast<int32_t>(surfaceflinger::LayerHandle::getLayerId(platformToken));
+ auto&& iter = mTrackedLayerData.find(layerId);
+
+ // Ensure it is being tracked
+ if (iter == mTrackedLayerData.end()) {
+ mTrackedLayerData.emplace(layerId, LayerData{.layerId = layerId});
+ }
+ layerIds.push_back(layerId);
+ }
+
+ // Register the session then track it
+ if (mMap.bindSessionIDToLayers(sessionId, layerIds) &&
+ !mTrackedSessionData.contains(sessionId)) {
+ mTrackedSessionData.emplace(sessionId,
+ SessionData{.sessionId = sessionId, .uid = ownerUid});
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus SessionManager::trackedSessionsDied(const std::vector<int32_t>& sessionIds) {
+ std::scoped_lock lock{mSessionManagerMutex};
+ for (int sessionId : sessionIds) {
+ mDeadSessions.push_back(sessionId);
+ mTrackedSessionData.erase(sessionId);
+ }
+
+ return ndk::ScopedAStatus::ok();
+}
+
+void SessionManager::updateTrackingState(
+ const std::vector<std::pair<uint32_t, std::string>>& handles) {
+ std::scoped_lock lock{mSessionManagerMutex};
+ std::vector<int32_t> deadLayers;
+ for (auto&& handle : handles) {
+ int32_t handleId = static_cast<int32_t>(handle.first);
+ auto it = mTrackedLayerData.find(handleId);
+ if (it != mTrackedLayerData.end()) {
+ // Track any dead layers to remove from the mapping
+ mTrackedLayerData.erase(it);
+ deadLayers.push_back(it->first);
+ }
+ }
+ mMap.notifyLayersDied(deadLayers);
+ mMap.notifySessionsDied(mDeadSessions);
+
+ mDeadSessions.clear();
+ mMap.getCurrentlyRelevantLayers(mCurrentlyRelevantLayers);
+}
+
+bool SessionManager::isLayerRelevant(int32_t layerId) {
+ return mCurrentlyRelevantLayers.contains(layerId);
+}
+
+} // namespace android::adpf
\ No newline at end of file
diff --git a/services/surfaceflinger/PowerAdvisor/SessionManager.h b/services/surfaceflinger/PowerAdvisor/SessionManager.h
new file mode 100644
index 0000000..93a80b5
--- /dev/null
+++ b/services/surfaceflinger/PowerAdvisor/SessionManager.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2024 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 <aidl/android/adpf/BnSessionManager.h>
+#include <sys/types.h>
+
+#include <utils/Thread.h>
+#include "Common.h"
+#include "SessionLayerMap.h"
+
+#include <string>
+
+namespace android {
+
+class Layer;
+
+namespace adpf {
+namespace impl {
+
+class PowerAdvisor;
+
+}
+
+// Talks to HMS to manage sessions for PowerHAL
+class SessionManager : public BnSessionManager {
+public:
+ SessionManager(uid_t uid);
+
+ // ISessionManager binder methods
+ ndk::ScopedAStatus trackedSessionsDied(const std::vector<int32_t>& in_sessionId) override;
+ ndk::ScopedAStatus associateSessionToLayers(
+ int32_t sessionId, int32_t ownerUid,
+ const std::vector<::ndk::SpAIBinder>& layers) override;
+
+ // Update the lifecycles of any tracked sessions or layers. This is intended to accepts the
+ // "destroyedHandles" object from updateLayerSnapshots in SF, and should reflect that type
+ void updateTrackingState(const std::vector<std::pair<uint32_t, std::string>>& handles);
+
+private:
+ // Session metadata tracked by the mTrackedSessionData map
+ struct SessionData {
+ int32_t sessionId;
+ int uid;
+ };
+
+ // Layer metadata tracked by the mTrackedSessionData map
+ struct LayerData {
+ int32_t layerId;
+ };
+
+ // Checks if the layer is currently associated with a specific session in the SessionLayerMap
+ // This helps us know which layers might be included in an update for the HAL
+ bool isLayerRelevant(int32_t layerId);
+
+ // The UID of whoever created our ISessionManager connection
+ const uid_t mUid;
+
+ // State owned by the main thread
+
+ // Set of layers that are currently being tracked in the SessionLayerMap. This is used to
+ // filter out which layers we actually care about during the latching process
+ std::unordered_set<int32_t> mCurrentlyRelevantLayers;
+
+ // Tracks active associations between sessions and layers. Items in this map can be thought of
+ // as "active" connections, and any session or layer not in this map will not receive updates or
+ // be collected in SurfaceFlinger
+ SessionLayerMap mMap;
+
+ // The list of currently-living layers which have ever been tracked, this is used to persist any
+ // data we want to track across potential mapping disconnects, and to determine when to send
+ // death updates
+ std::unordered_map<int32_t, LayerData> mTrackedLayerData;
+
+ // The list of currently-living sessions which have ever been tracked, this is used to persist
+ // any data we want to track across mapping disconnects
+ std::unordered_map<int32_t, SessionData> mTrackedSessionData;
+
+ // State owned by mSessionManagerMutex
+
+ std::mutex mSessionManagerMutex;
+
+ // The list of sessions that have died since we last called updateTrackingState
+ std::vector<int32_t> mDeadSessions GUARDED_BY(mSessionManagerMutex);
+};
+
+} // namespace adpf
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/PowerAdvisor/Workload.h b/services/surfaceflinger/PowerAdvisor/Workload.h
new file mode 100644
index 0000000..7002357
--- /dev/null
+++ b/services/surfaceflinger/PowerAdvisor/Workload.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2024 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 <ftl/flags.h>
+#include <stdint.h>
+
+namespace android::adpf {
+// Additional composition workload that can increase cpu load.
+enum class Workload : uint32_t {
+ NONE = 0,
+ // Layer effects like blur and shadows which forces client composition
+ EFFECTS = 1 << 0,
+
+ // Geometry changes which requires HWC to validate and share composition strategy
+ VISIBLE_REGION = 1 << 1,
+
+ // Diplay changes which can cause geometry changes
+ DISPLAY_CHANGES = 1 << 2,
+
+ // Changes in sf duration which can shorten the deadline for sf to composite the frame
+ WAKEUP = 1 << 3,
+
+ // Increases in refresh rates can cause the deadline for sf to composite to be shorter
+ REFRESH_RATE_INCREASE = 1 << 4,
+
+ // Screenshot requests increase both the cpu and gpu workload
+ SCREENSHOT = 1 << 5
+};
+} // namespace android::adpf
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp b/services/surfaceflinger/PowerAdvisor/aidl/android/adpf/ISessionManager.aidl
similarity index 64%
copy from services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp
copy to services/surfaceflinger/PowerAdvisor/aidl/android/adpf/ISessionManager.aidl
index d383283..c1a6a9e 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp
+++ b/services/surfaceflinger/PowerAdvisor/aidl/android/adpf/ISessionManager.aidl
@@ -14,12 +14,13 @@
* limitations under the License.
*/
-#include "mock/DisplayHardware/MockPowerHintSessionWrapper.h"
+package android.adpf;
-namespace android::Hwc2::mock {
-
-// Explicit default instantiation is recommended.
-MockPowerHintSessionWrapper::MockPowerHintSessionWrapper()
- : power::PowerHintSessionWrapper(nullptr) {}
-
-} // namespace android::Hwc2::mock
+/**
+ * Private service for SessionManager to use. Ideally this will
+ * eventually take the role of HintManagerService.
+ */
+interface ISessionManager {
+ oneway void associateSessionToLayers(in int sessionId, in int ownerUid, in IBinder[] layers);
+ oneway void trackedSessionsDied(in int[] sessionId);
+}
diff --git a/services/surfaceflinger/TransactionState.h b/services/surfaceflinger/QueuedTransactionState.h
similarity index 84%
rename from services/surfaceflinger/TransactionState.h
rename to services/surfaceflinger/QueuedTransactionState.h
index e5d6481..86683da 100644
--- a/services/surfaceflinger/TransactionState.h
+++ b/services/surfaceflinger/QueuedTransactionState.h
@@ -16,14 +16,14 @@
#pragma once
-#include <condition_variable>
#include <memory>
-#include <mutex>
#include <vector>
#include "FrontEnd/LayerCreationArgs.h"
#include "renderengine/ExternalTexture.h"
+#include <PowerAdvisor/Workload.h>
#include <common/FlagManager.h>
+#include <ftl/flags.h>
#include <gui/LayerState.h>
#include <system/window.h>
@@ -47,18 +47,20 @@
uint32_t touchCropId = UNASSIGNED_LAYER_ID;
};
-struct TransactionState {
- TransactionState() = default;
+struct QueuedTransactionState {
+ QueuedTransactionState() = default;
- TransactionState(const FrameTimelineInfo& frameTimelineInfo,
- std::vector<ResolvedComposerState>& composerStates,
- const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
- const sp<IBinder>& applyToken, const InputWindowCommands& inputWindowCommands,
- int64_t desiredPresentTime, bool isAutoTimestamp,
- std::vector<uint64_t> uncacheBufferIds, int64_t postTime,
- bool hasListenerCallbacks, std::vector<ListenerCallbacks> listenerCallbacks,
- int originPid, int originUid, uint64_t transactionId,
- std::vector<uint64_t> mergedTransactionIds)
+ QueuedTransactionState(const FrameTimelineInfo& frameTimelineInfo,
+ std::vector<ResolvedComposerState>& composerStates,
+ const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
+ const sp<IBinder>& applyToken,
+ const InputWindowCommands& inputWindowCommands,
+ int64_t desiredPresentTime, bool isAutoTimestamp,
+ std::vector<uint64_t> uncacheBufferIds, int64_t postTime,
+ bool hasListenerCallbacks,
+ std::vector<ListenerCallbacks> listenerCallbacks, int originPid,
+ int originUid, uint64_t transactionId,
+ std::vector<uint64_t> mergedTransactionIds)
: frameTimelineInfo(frameTimelineInfo),
states(std::move(composerStates)),
displays(displayStates),
@@ -148,6 +150,7 @@
uint64_t id;
bool sentFenceTimeoutWarning = false;
std::vector<uint64_t> mergedTransactionIds;
+ ftl::Flags<adpf::Workload> workloadHint;
};
} // namespace android
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 06c2f26..514adac 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -39,11 +39,8 @@
#include <string>
#include "DisplayDevice.h"
-#include "DisplayRenderArea.h"
#include "FrontEnd/LayerCreationArgs.h"
#include "Layer.h"
-#include "RenderAreaBuilder.h"
-#include "Scheduler/VsyncController.h"
#include "SurfaceFlinger.h"
namespace android {
@@ -259,6 +256,7 @@
ui::LayerStack layerStack;
ui::Transform::RotationFlags orientation;
ui::Size displaySize;
+ Rect layerStackSpaceRect;
{
// TODO(b/159112860): Don't keep sp<DisplayDevice> outside of SF main thread
@@ -267,6 +265,7 @@
layerStack = display->getLayerStack();
orientation = ui::Transform::toRotationFlags(display->getOrientation());
displaySize = display->getSize();
+ layerStackSpaceRect = display->getLayerStackSpaceRect();
}
std::vector<RegionSamplingThread::Descriptor> descriptors;
@@ -346,29 +345,21 @@
constexpr bool kRegionSampling = true;
constexpr bool kGrayscale = false;
constexpr bool kIsProtected = false;
- constexpr bool kAttachGainmap = false;
- SurfaceFlinger::RenderAreaBuilderVariant
- renderAreaBuilder(std::in_place_type<DisplayRenderAreaBuilder>, sampledBounds,
- sampledBounds.getSize(), ui::Dataspace::V0_SRGB, displayWeak,
- RenderArea::Options::CAPTURE_SECURE_LAYERS);
+ SurfaceFlinger::ScreenshotArgs screenshotArgs;
+ screenshotArgs.captureTypeVariant = displayWeak;
+ screenshotArgs.displayId = std::nullopt;
+ screenshotArgs.sourceCrop = sampledBounds.isEmpty() ? layerStackSpaceRect : sampledBounds;
+ screenshotArgs.reqSize = sampledBounds.getSize();
+ screenshotArgs.dataspace = ui::Dataspace::V0_SRGB;
+ screenshotArgs.isSecure = true;
+ screenshotArgs.seamlessTransition = false;
- FenceResult fenceResult;
- if (FlagManager::getInstance().single_hop_screenshot() &&
- FlagManager::getInstance().ce_fence_promise() && mFlinger.mRenderEngine->isThreaded()) {
- std::vector<sp<LayerFE>> layerFEs;
- auto displayState = mFlinger.getSnapshotsFromMainThread(renderAreaBuilder,
- getLayerSnapshotsFn, layerFEs);
- fenceResult = mFlinger.captureScreenshot(renderAreaBuilder, buffer, kRegionSampling,
- kGrayscale, kIsProtected, kAttachGainmap, nullptr,
- displayState, layerFEs)
- .get();
- } else {
- fenceResult = mFlinger.captureScreenshotLegacy(renderAreaBuilder, getLayerSnapshotsFn,
- buffer, kRegionSampling, kGrayscale,
- kIsProtected, kAttachGainmap, nullptr)
- .get();
- }
+ std::vector<std::pair<Layer*, sp<LayerFE>>> layers;
+ mFlinger.getSnapshotsFromMainThread(screenshotArgs, getLayerSnapshotsFn, layers);
+ FenceResult fenceResult = mFlinger.captureScreenshot(screenshotArgs, buffer, kRegionSampling,
+ kGrayscale, kIsProtected, nullptr, layers)
+ .get();
if (fenceResult.ok()) {
fenceResult.value()->waitForever(LOG_TAG);
}
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
deleted file mode 100644
index aa66ccf..0000000
--- a/services/surfaceflinger/RenderArea.h
+++ /dev/null
@@ -1,98 +0,0 @@
-#pragma once
-
-#include <ui/GraphicTypes.h>
-#include <ui/Transform.h>
-
-#include <functional>
-
-#include "FrontEnd/LayerSnapshot.h"
-#include "Layer.h"
-
-namespace android {
-
-class DisplayDevice;
-
-// RenderArea describes a rectangular area that layers can be rendered to.
-//
-// There is a logical render area and a physical render area. When a layer is
-// rendered to the render area, it is first transformed and clipped to the logical
-// render area. The transformed and clipped layer is then projected onto the
-// physical render area.
-class RenderArea {
-public:
- enum class CaptureFill {CLEAR, OPAQUE};
- enum class Options {
- // If not set, the secure layer would be blacked out or skipped
- // when rendered to an insecure render area
- CAPTURE_SECURE_LAYERS = 1 << 0,
-
- // If set, the render result may be used for system animations
- // that must preserve the exact colors of the display
- HINT_FOR_SEAMLESS_TRANSITION = 1 << 1,
- };
- static float getCaptureFillValue(CaptureFill captureFill);
-
- RenderArea(ui::Size reqSize, CaptureFill captureFill, ui::Dataspace reqDataSpace,
- ftl::Flags<Options> options)
- : mOptions(options),
- mReqSize(reqSize),
- mReqDataSpace(reqDataSpace),
- mCaptureFill(captureFill) {}
-
- virtual ~RenderArea() = default;
-
- // Returns true if the render area is secure. A secure layer should be
- // blacked out / skipped when rendered to an insecure render area.
- virtual bool isSecure() const = 0;
-
- // Returns the transform to be applied on layers to transform them into
- // the logical render area.
- virtual const ui::Transform& getTransform() const = 0;
-
- // Returns the source crop of the render area. The source crop defines
- // how layers are projected from the logical render area onto the physical
- // render area. It can be larger than the logical render area. It can
- // also be optionally rotated.
- //
- // The source crop is specified in layer space (when rendering a layer and
- // its children), or in layer-stack space (when rendering all layers visible
- // on the display).
- virtual Rect getSourceCrop() const = 0;
-
- // Returns the size of the physical render area.
- int getReqWidth() const { return mReqSize.width; }
- int getReqHeight() const { return mReqSize.height; }
-
- // Returns the composition data space of the render area.
- ui::Dataspace getReqDataSpace() const { return mReqDataSpace; }
-
- // Returns the fill color of the physical render area. Regions not
- // covered by any rendered layer should be filled with this color.
- CaptureFill getCaptureFill() const { return mCaptureFill; }
-
- virtual sp<const DisplayDevice> getDisplayDevice() const = 0;
-
- // If this is a LayerRenderArea, return the root layer of the
- // capture operation.
- virtual sp<Layer> getParentLayer() const { return nullptr; }
-
- // If this is a LayerRenderArea, return the layer snapshot
- // of the root layer of the capture operation
- virtual const frontend::LayerSnapshot* getLayerSnapshot() const { return nullptr; }
-
- // Returns whether the render result may be used for system animations that
- // must preserve the exact colors of the display.
- bool getHintForSeamlessTransition() const {
- return mOptions.test(Options::HINT_FOR_SEAMLESS_TRANSITION);
- }
-
-protected:
- ftl::Flags<Options> mOptions;
-
-private:
- const ui::Size mReqSize;
- const ui::Dataspace mReqDataSpace;
- const CaptureFill mCaptureFill;
-};
-
-} // namespace android
diff --git a/services/surfaceflinger/RenderAreaBuilder.h b/services/surfaceflinger/RenderAreaBuilder.h
deleted file mode 100644
index 599fa7e..0000000
--- a/services/surfaceflinger/RenderAreaBuilder.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2024 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 "DisplayDevice.h"
-#include "DisplayRenderArea.h"
-#include "LayerRenderArea.h"
-#include "ui/Size.h"
-#include "ui/Transform.h"
-
-namespace android {
-/**
- * A parameter object for creating a render area
- */
-struct RenderAreaBuilder {
- // Source crop of the render area
- Rect crop;
-
- // Size of the physical render area
- ui::Size reqSize;
-
- // Composition data space of the render area
- ui::Dataspace reqDataSpace;
-
- ftl::Flags<RenderArea::Options> options;
- virtual std::unique_ptr<RenderArea> build() const = 0;
-
- RenderAreaBuilder(Rect crop, ui::Size reqSize, ui::Dataspace reqDataSpace,
- ftl::Flags<RenderArea::Options> options)
- : crop(crop), reqSize(reqSize), reqDataSpace(reqDataSpace), options(options) {}
-
- virtual ~RenderAreaBuilder() = default;
-};
-
-struct DisplayRenderAreaBuilder : RenderAreaBuilder {
- DisplayRenderAreaBuilder(Rect crop, ui::Size reqSize, ui::Dataspace reqDataSpace,
- wp<const DisplayDevice> displayWeak,
- ftl::Flags<RenderArea::Options> options)
- : RenderAreaBuilder(crop, reqSize, reqDataSpace, options), displayWeak(displayWeak) {}
-
- // Display that render area will be on
- wp<const DisplayDevice> displayWeak;
-
- std::unique_ptr<RenderArea> build() const override {
- return DisplayRenderArea::create(displayWeak, crop, reqSize, reqDataSpace, options);
- }
-};
-
-struct LayerRenderAreaBuilder : RenderAreaBuilder {
- LayerRenderAreaBuilder(Rect crop, ui::Size reqSize, ui::Dataspace reqDataSpace, sp<Layer> layer,
- bool childrenOnly, ftl::Flags<RenderArea::Options> options)
- : RenderAreaBuilder(crop, reqSize, reqDataSpace, options),
- layer(layer),
- childrenOnly(childrenOnly) {}
-
- // Root layer of the render area
- sp<Layer> layer;
-
- // Layer snapshot of the root layer
- frontend::LayerSnapshot layerSnapshot;
-
- // Transform to be applied on the layers to transform them
- // into the logical render area
- ui::Transform layerTransform{ui::Transform()};
-
- // Buffer bounds
- Rect layerBufferSize{Rect()};
-
- // If false, transform is inverted from the parent snapshot
- bool childrenOnly;
-
- // Uses parent snapshot to determine layer transform and buffer size
- void setLayerSnapshot(const frontend::LayerSnapshot& parentSnapshot) {
- layerSnapshot = parentSnapshot;
- if (!childrenOnly) {
- layerTransform = parentSnapshot.localTransform.inverse();
- }
- layerBufferSize = parentSnapshot.bufferSize;
- }
-
- std::unique_ptr<RenderArea> build() const override {
- return std::make_unique<LayerRenderArea>(layer, std::move(layerSnapshot), crop, reqSize,
- reqDataSpace, layerTransform, layerBufferSize,
- options);
- }
-};
-
-} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index e385f18..c37b965 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -43,11 +43,10 @@
#include <utils/Errors.h>
#include <common/FlagManager.h>
+#include <scheduler/FrameRateMode.h>
#include <scheduler/VsyncConfig.h>
-#include "DisplayHardware/DisplayMode.h"
-#include "FrameTimeline.h"
+#include "FrameTimeline/FrameTimeline.h"
#include "VSyncDispatch.h"
-#include "VSyncTracker.h"
#include "EventThread.h"
@@ -87,32 +86,43 @@
std::string toString(const DisplayEventReceiver::Event& event) {
switch (event.header.type) {
- case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
+ case DisplayEventType::DISPLAY_EVENT_HOTPLUG:
return StringPrintf("Hotplug{displayId=%s, %s}",
to_string(event.header.displayId).c_str(),
event.hotplug.connected ? "connected" : "disconnected");
- case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
+ case DisplayEventType::DISPLAY_EVENT_VSYNC:
return StringPrintf("VSync{displayId=%s, count=%u, expectedPresentationTime=%" PRId64
"}",
to_string(event.header.displayId).c_str(), event.vsync.count,
event.vsync.vsyncData.preferredExpectedPresentationTime());
- case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE:
+ case DisplayEventType::DISPLAY_EVENT_MODE_CHANGE:
return StringPrintf("ModeChanged{displayId=%s, modeId=%u}",
to_string(event.header.displayId).c_str(), event.modeChange.modeId);
- case DisplayEventReceiver::DISPLAY_EVENT_HDCP_LEVELS_CHANGE:
+ case DisplayEventType::DISPLAY_EVENT_HDCP_LEVELS_CHANGE:
return StringPrintf("HdcpLevelsChange{displayId=%s, connectedLevel=%d, maxLevel=%d}",
to_string(event.header.displayId).c_str(),
event.hdcpLevelsChange.connectedLevel,
event.hdcpLevelsChange.maxLevel);
- default:
- return "Event{}";
+ case DisplayEventType::DISPLAY_EVENT_MODE_REJECTION:
+ return StringPrintf("ModeRejected{displayId=%s, modeId=%u}",
+ to_string(event.header.displayId).c_str(),
+ event.modeRejection.modeId);
+ case DisplayEventType::DISPLAY_EVENT_FRAME_RATE_OVERRIDE:
+ return StringPrintf("FrameRateOverride{displayId=%s, frameRateHz=%f}",
+ to_string(event.header.displayId).c_str(),
+ event.frameRateOverride.frameRateHz);
+ case DisplayEventType::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH:
+ return StringPrintf("FrameRateOverrideFlush{displayId=%s}",
+ to_string(event.header.displayId).c_str());
+ case DisplayEventType::DISPLAY_EVENT_NULL:
+ return "NULL";
}
}
DisplayEventReceiver::Event makeHotplug(PhysicalDisplayId displayId, nsecs_t timestamp,
bool connected) {
DisplayEventReceiver::Event event;
- event.header = {DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, displayId, timestamp};
+ event.header = {DisplayEventType::DISPLAY_EVENT_HOTPLUG, displayId, timestamp};
event.hotplug.connected = connected;
return event;
}
@@ -120,7 +130,7 @@
DisplayEventReceiver::Event makeHotplugError(nsecs_t timestamp, int32_t connectionError) {
DisplayEventReceiver::Event event;
PhysicalDisplayId unusedDisplayId;
- event.header = {DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, unusedDisplayId, timestamp};
+ event.header = {DisplayEventType::DISPLAY_EVENT_HOTPLUG, unusedDisplayId, timestamp};
event.hotplug.connected = false;
event.hotplug.connectionError = connectionError;
return event;
@@ -130,7 +140,7 @@
uint32_t count, nsecs_t expectedPresentationTime,
nsecs_t deadlineTimestamp) {
DisplayEventReceiver::Event event;
- event.header = {DisplayEventReceiver::DISPLAY_EVENT_VSYNC, displayId, timestamp};
+ event.header = {DisplayEventType::DISPLAY_EVENT_VSYNC, displayId, timestamp};
event.vsync.count = count;
event.vsync.vsyncData.preferredFrameTimelineIndex = 0;
// Temporarily store the current vsync information in frameTimelines[0], marked as
@@ -145,7 +155,7 @@
DisplayEventReceiver::Event makeModeChanged(const scheduler::FrameRateMode& mode) {
DisplayEventReceiver::Event event;
- event.header = {DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE,
+ event.header = {DisplayEventType::DISPLAY_EVENT_MODE_CHANGE,
mode.modePtr->getPhysicalDisplayId(), systemTime()};
event.modeChange.modeId = ftl::to_underlying(mode.modePtr->getId());
event.modeChange.vsyncPeriod = mode.fps.getPeriodNsecs();
@@ -157,7 +167,7 @@
return DisplayEventReceiver::Event{
.header =
DisplayEventReceiver::Event::Header{
- .type = DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE,
+ .type = DisplayEventType::DISPLAY_EVENT_FRAME_RATE_OVERRIDE,
.displayId = displayId,
.timestamp = systemTime(),
},
@@ -168,7 +178,7 @@
DisplayEventReceiver::Event makeFrameRateOverrideFlushEvent(PhysicalDisplayId displayId) {
return DisplayEventReceiver::Event{
.header = DisplayEventReceiver::Event::Header{
- .type = DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH,
+ .type = DisplayEventType::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH,
.displayId = displayId,
.timestamp = systemTime(),
}};
@@ -179,7 +189,7 @@
return DisplayEventReceiver::Event{
.header =
DisplayEventReceiver::Event::Header{
- .type = DisplayEventReceiver::DISPLAY_EVENT_HDCP_LEVELS_CHANGE,
+ .type = DisplayEventType::DISPLAY_EVENT_HDCP_LEVELS_CHANGE,
.displayId = displayId,
.timestamp = systemTime(),
},
@@ -188,6 +198,18 @@
};
}
+DisplayEventReceiver::Event makeModeRejection(PhysicalDisplayId displayId, DisplayModeId modeId) {
+ return DisplayEventReceiver::Event{
+ .header =
+ DisplayEventReceiver::Event::Header{
+ .type = DisplayEventType::DISPLAY_EVENT_MODE_REJECTION,
+ .displayId = displayId,
+ .timestamp = systemTime(),
+ },
+ .modeRejection.modeId = ftl::to_underlying(modeId),
+ };
+}
+
} // namespace
EventThreadConnection::EventThreadConnection(EventThread* eventThread, uid_t callingUid,
@@ -248,10 +270,10 @@
return size < 0 ? status_t(size) : status_t(NO_ERROR);
};
- if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE ||
- event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH) {
+ if (event.header.type == DisplayEventType::DISPLAY_EVENT_FRAME_RATE_OVERRIDE ||
+ event.header.type == DisplayEventType::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH) {
mPendingEvents.emplace_back(event);
- if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE) {
+ if (event.header.type == DisplayEventType::DISPLAY_EVENT_FRAME_RATE_OVERRIDE) {
return status_t(NO_ERROR);
}
@@ -329,7 +351,8 @@
auto connection = sp<EventThreadConnection>::make(const_cast<EventThread*>(this),
IPCThreadState::self()->getCallingUid(),
eventRegistration);
- if (FlagManager::getInstance().misc1()) {
+ if (FlagManager::getInstance().misc1() &&
+ !FlagManager::getInstance().disable_sched_fifo_sf_sched()) {
const int policy = SCHED_FIFO;
connection->setMinSchedulerPolicy(policy, sched_get_priority_min(policy));
}
@@ -420,6 +443,16 @@
mCondition.notify_all();
}
+void EventThread::omitVsyncDispatching(bool omitted) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ if (!mVSyncState || mVSyncState->omitted == omitted) {
+ return;
+ }
+
+ mVSyncState->omitted = omitted;
+ mCondition.notify_all();
+}
+
void EventThread::onVsync(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
std::lock_guard<std::mutex> lock(mMutex);
mLastVsyncCallbackTime = TimePoint::fromNs(vsyncTime);
@@ -472,6 +505,21 @@
mCondition.notify_all();
}
+void EventThread::onModeRejected(PhysicalDisplayId displayId, DisplayModeId modeId) {
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ mPendingEvents.push_back(makeModeRejection(displayId, modeId));
+ mCondition.notify_all();
+}
+
+// Merge lists of buffer stuffed Uids
+void EventThread::addBufferStuffedUids(BufferStuffingMap bufferStuffedUids) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ for (auto& [uid, count] : bufferStuffedUids) {
+ mBufferStuffedUids.emplace_or_replace(uid, count);
+ }
+}
+
void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
DisplayEventConsumers consumers;
@@ -483,7 +531,7 @@
event = mPendingEvents.front();
mPendingEvents.pop_front();
- if (event->header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) {
+ if (event->header.type == DisplayEventType::DISPLAY_EVENT_HOTPLUG) {
if (event->hotplug.connectionError == 0) {
if (event->hotplug.connected && !mVSyncState) {
mVSyncState.emplace();
@@ -521,7 +569,17 @@
}
if (mVSyncState && vsyncRequested) {
- mState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
+ const bool vsyncOmitted =
+ FlagManager::getInstance().no_vsyncs_on_screen_off() && mVSyncState->omitted;
+ if (vsyncOmitted) {
+ mState = State::Idle;
+ SFTRACE_INT("VsyncPendingScreenOn", 1);
+ } else {
+ mState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
+ if (FlagManager::getInstance().no_vsyncs_on_screen_off()) {
+ SFTRACE_INT("VsyncPendingScreenOn", 0);
+ }
+ }
} else {
ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
mState = State::Idle;
@@ -585,18 +643,21 @@
};
switch (event.header.type) {
- case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
+ case DisplayEventType::DISPLAY_EVENT_HOTPLUG:
return true;
- case DisplayEventReceiver::DISPLAY_EVENT_HDCP_LEVELS_CHANGE:
+ case DisplayEventType::DISPLAY_EVENT_HDCP_LEVELS_CHANGE:
return true;
- case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: {
+ case DisplayEventType::DISPLAY_EVENT_MODE_CHANGE: {
return connection->mEventRegistration.test(
gui::ISurfaceComposer::EventRegistration::modeChanged);
}
- case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
+ case DisplayEventType::DISPLAY_EVENT_MODE_REJECTION:
+ return true;
+
+ case DisplayEventType::DISPLAY_EVENT_VSYNC:
switch (connection->vsyncRequest) {
case VSyncRequest::None:
return false;
@@ -622,13 +683,12 @@
return event.vsync.count % vsyncPeriod(connection->vsyncRequest) == 0;
}
- case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE:
+ case DisplayEventType::DISPLAY_EVENT_FRAME_RATE_OVERRIDE:
[[fallthrough]];
- case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH:
+ case DisplayEventType::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH:
return connection->mEventRegistration.test(
gui::ISurfaceComposer::EventRegistration::frameRateOverride);
-
- default:
+ case DisplayEventType::DISPLAY_EVENT_NULL:
return false;
}
}
@@ -701,15 +761,26 @@
void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
const DisplayEventConsumers& consumers) {
+ // List of Uids that have been sent vsync data with queued buffer count.
+ // Used to keep track of which Uids can be removed from the map of
+ // buffer stuffed clients.
+ ftl::SmallVector<uid_t, 10> uidsPostedQueuedBuffers;
for (const auto& consumer : consumers) {
DisplayEventReceiver::Event copy = event;
- if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
+ if (event.header.type == DisplayEventType::DISPLAY_EVENT_VSYNC) {
const Period frameInterval = mCallback.getVsyncPeriod(consumer->mOwnerUid);
copy.vsync.vsyncData.frameInterval = frameInterval.ns();
generateFrameTimeline(copy.vsync.vsyncData, frameInterval.ns(), copy.header.timestamp,
event.vsync.vsyncData.preferredExpectedPresentationTime(),
event.vsync.vsyncData.preferredDeadlineTimestamp());
}
+ auto it = mBufferStuffedUids.find(consumer->mOwnerUid);
+ if (it != mBufferStuffedUids.end()) {
+ copy.vsync.vsyncData.numberQueuedBuffers = it->second;
+ uidsPostedQueuedBuffers.emplace_back(consumer->mOwnerUid);
+ } else {
+ copy.vsync.vsyncData.numberQueuedBuffers = 0;
+ }
switch (consumer->postEvent(copy)) {
case NO_ERROR:
break;
@@ -725,7 +796,13 @@
removeDisplayEventConnectionLocked(consumer);
}
}
- if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC &&
+ // The clients that have already received the queued buffer count
+ // can be removed from the buffer stuffed Uid list to avoid
+ // being sent duplicate messages.
+ for (auto uid : uidsPostedQueuedBuffers) {
+ mBufferStuffedUids.erase(uid);
+ }
+ if (event.header.type == DisplayEventType::DISPLAY_EVENT_VSYNC &&
FlagManager::getInstance().vrr_config()) {
mLastCommittedVsyncTime =
TimePoint::fromNs(event.vsync.vsyncData.preferredExpectedPresentationTime());
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index c3c7eb0..a91dde7 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -21,6 +21,7 @@
#include <gui/DisplayEventReceiver.h>
#include <private/gui/BitTube.h>
#include <sys/types.h>
+#include <ui/DisplayId.h>
#include <utils/Errors.h>
#include <scheduler/FrameRateMode.h>
@@ -55,6 +56,7 @@
// ---------------------------------------------------------------------------
using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;
+using BufferStuffingMap = ftl::SmallMap<uid_t, uint32_t, 10>;
enum class VSyncRequest {
None = -2,
@@ -106,6 +108,8 @@
// Feed clients with fake VSYNC, e.g. while the display is off.
virtual void enableSyntheticVsync(bool) = 0;
+ virtual void omitVsyncDispatching(bool) = 0;
+
virtual void onHotplugReceived(PhysicalDisplayId displayId, bool connected) = 0;
virtual void onHotplugConnectionError(int32_t connectionError) = 0;
@@ -113,6 +117,9 @@
// called when SF changes the active mode and apps needs to be notified about the change
virtual void onModeChanged(const scheduler::FrameRateMode&) = 0;
+ // called when SF rejects the mode change request
+ virtual void onModeRejected(PhysicalDisplayId displayId, DisplayModeId modeId) = 0;
+
// called when SF updates the Frame Rate Override list
virtual void onFrameRateOverridesChanged(PhysicalDisplayId displayId,
std::vector<FrameRateOverride> overrides) = 0;
@@ -134,6 +141,10 @@
virtual void onHdcpLevelsChanged(PhysicalDisplayId displayId, int32_t connectedLevel,
int32_t maxLevel) = 0;
+
+ // An elevated number of queued buffers in the server is detected. This propagates a
+ // flag to Choreographer indicating that buffer stuffing recovery should begin.
+ virtual void addBufferStuffedUids(BufferStuffingMap bufferStuffedUids) = 0;
};
struct IEventThreadCallback {
@@ -165,12 +176,16 @@
void enableSyntheticVsync(bool) override;
+ void omitVsyncDispatching(bool) override;
+
void onHotplugReceived(PhysicalDisplayId displayId, bool connected) override;
void onHotplugConnectionError(int32_t connectionError) override;
void onModeChanged(const scheduler::FrameRateMode&) override;
+ void onModeRejected(PhysicalDisplayId displayId, DisplayModeId modeId) override;
+
void onFrameRateOverridesChanged(PhysicalDisplayId displayId,
std::vector<FrameRateOverride> overrides) override;
@@ -184,6 +199,8 @@
void onHdcpLevelsChanged(PhysicalDisplayId displayId, int32_t connectedLevel,
int32_t maxLevel) override;
+ void addBufferStuffedUids(BufferStuffingMap bufferStuffedUids) override;
+
private:
friend EventThreadTest;
@@ -224,6 +241,10 @@
scheduler::VSyncCallbackRegistration mVsyncRegistration GUARDED_BY(mMutex);
frametimeline::TokenManager* const mTokenManager;
+ // All consumers that need to recover from buffer stuffing and the number
+ // of their queued buffers.
+ BufferStuffingMap mBufferStuffedUids GUARDED_BY(mMutex);
+
IEventThreadCallback& mCallback;
std::thread mThread;
@@ -240,6 +261,9 @@
// True if VSYNC should be faked, e.g. when display is off.
bool synthetic = false;
+
+ // True if VSYNC should not be delivered to apps. Used when the display is off.
+ bool omitted = false;
};
// TODO(b/74619554): Create per-display threads waiting on respective VSYNC signals,
diff --git a/services/surfaceflinger/Scheduler/ISchedulerCallback.h b/services/surfaceflinger/Scheduler/ISchedulerCallback.h
index 2b9e88c..d02d149 100644
--- a/services/surfaceflinger/Scheduler/ISchedulerCallback.h
+++ b/services/surfaceflinger/Scheduler/ISchedulerCallback.h
@@ -31,7 +31,7 @@
virtual void onChoreographerAttached() = 0;
virtual void onExpectedPresentTimePosted(TimePoint, ftl::NonNull<DisplayModePtr>,
Fps renderRate) = 0;
- virtual void onCommitNotComposited(PhysicalDisplayId pacesetterDisplayId) = 0;
+ virtual void onCommitNotComposited() = 0;
virtual void vrrDisplayIdle(bool idle) = 0;
protected:
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 64b85c0..630beb0 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -280,6 +280,9 @@
case Layer::FrameRateCompatibility::Exact:
return LayerVoteType::ExplicitExact;
case Layer::FrameRateCompatibility::Gte:
+ if (frameRate.isNoVote()) {
+ return LayerVoteType::NoVote;
+ }
if (isVrrDevice) {
return LayerVoteType::ExplicitGte;
} else {
@@ -308,6 +311,15 @@
const auto setFrameRateVoteType =
info->isVisible() ? voteType : LayerVoteType::NoVote;
+ const bool hasSetFrameRateOpinion =
+ frameRate.isValuelessType() || frameRate.vote.rate.isValid();
+ const bool hasCategoryOpinion =
+ frameRate.category != FrameRateCategory::NoPreference &&
+ frameRate.category != FrameRateCategory::Default;
+ const bool hasFrameRateOpinionAboveGameDefault =
+ hasSetFrameRateOpinion || hasCategoryOpinion;
+ const bool hasFrameRateOpinionArr = frameRate.isValid() && !frameRate.isNoVote();
+
if (gameModeFrameRateOverride.isValid()) {
info->setLayerVote({gameFrameRateOverrideVoteType, gameModeFrameRateOverride});
SFTRACE_FORMAT_INSTANT("GameModeFrameRateOverride");
@@ -315,7 +327,8 @@
trace(*info, gameFrameRateOverrideVoteType,
gameModeFrameRateOverride.getIntValue());
}
- } else if (frameRate.isValid() && frameRate.isVoteValidForMrr(isVrrDevice)) {
+ } else if (hasFrameRateOpinionAboveGameDefault &&
+ frameRate.isVoteValidForMrr(isVrrDevice)) {
info->setLayerVote({setFrameRateVoteType,
isValuelessVote ? 0_Hz : frameRate.vote.rate,
frameRate.vote.seamlessness, frameRate.category});
@@ -331,8 +344,18 @@
trace(*info, gameFrameRateOverrideVoteType,
gameDefaultFrameRateOverride.getIntValue());
}
+ } else if (hasFrameRateOpinionArr && frameRate.isVoteValidForMrr(isVrrDevice)) {
+ // This allows NoPreference votes on ARR devices after considering the
+ // gameDefaultFrameRateOverride (above).
+ info->setLayerVote({setFrameRateVoteType,
+ isValuelessVote ? 0_Hz : frameRate.vote.rate,
+ frameRate.vote.seamlessness, frameRate.category});
+ if (CC_UNLIKELY(mTraceEnabled)) {
+ trace(*info, gameFrameRateOverrideVoteType,
+ frameRate.vote.rate.getIntValue());
+ }
} else {
- if (frameRate.isValid() && !frameRate.isVoteValidForMrr(isVrrDevice)) {
+ if (hasFrameRateOpinionArr && !frameRate.isVoteValidForMrr(isVrrDevice)) {
SFTRACE_FORMAT_INSTANT("Reset layer to ignore explicit vote on MRR %s: %s "
"%s %s",
info->getName().c_str(),
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp
index ff1926e..8c22de1 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp
@@ -504,7 +504,7 @@
return FrameRateCompatibility::Exact;
case ANATIVEWINDOW_FRAME_RATE_MIN:
return FrameRateCompatibility::Min;
- case ANATIVEWINDOW_FRAME_RATE_GTE:
+ case ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_AT_LEAST:
return FrameRateCompatibility::Gte;
case ANATIVEWINDOW_FRAME_RATE_NO_VOTE:
return FrameRateCompatibility::NoVote;
@@ -562,7 +562,10 @@
}
bool LayerInfo::FrameRate::isNoVote() const {
- return vote.type == FrameRateCompatibility::NoVote;
+ // A desired frame rate greater than or equal to 0 is treated as NoVote.
+ bool isNoVoteGte = FlagManager::getInstance().arr_setframerate_gte_enum() &&
+ vote.type == FrameRateCompatibility::Gte && !vote.rate.isValid();
+ return vote.type == FrameRateCompatibility::NoVote || isNoVoteGte;
}
bool LayerInfo::FrameRate::isValuelessType() const {
@@ -577,7 +580,12 @@
case FrameRateCompatibility::Default:
case FrameRateCompatibility::ExactOrMultiple:
case FrameRateCompatibility::Exact:
+ return false;
case FrameRateCompatibility::Gte:
+ if (isNoVote()) {
+ // Special case: GTE 0 is same as NoVote.
+ return true;
+ }
return false;
}
}
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp
index 2e1f938..91a798e 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.cpp
+++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp
@@ -24,7 +24,7 @@
#include <scheduler/interface/ICompositor.h>
#include "EventThread.h"
-#include "FrameTimeline.h"
+#include "FrameTimeline/FrameTimeline.h"
#include "MessageQueue.h"
namespace android::impl {
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
index ab9014e..97f1f8f 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
@@ -489,6 +489,20 @@
return mGetRankedFrameRatesCache->result;
}
+using LayerRequirementPtrs = std::vector<const RefreshRateSelector::LayerRequirement*>;
+using PerUidLayerRequirements = std::unordered_map<uid_t, LayerRequirementPtrs>;
+
+PerUidLayerRequirements groupLayersByUid(
+ const std::vector<RefreshRateSelector::LayerRequirement>& layers) {
+ PerUidLayerRequirements layersByUid;
+ for (const auto& layer : layers) {
+ const auto it = layersByUid.emplace(layer.ownerUid, LayerRequirementPtrs()).first;
+ auto& layersWithSameUid = it->second;
+ layersWithSameUid.push_back(&layer);
+ }
+ return layersByUid;
+}
+
auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequirement>& layers,
GlobalSignals signals, Fps pacesetterFps) const
-> RankedFrameRates {
@@ -525,6 +539,43 @@
return {ranking, GlobalSignals{.powerOnImminent = true}};
}
+ // A method for UI Toolkit to send the touch signal via "HighHint" category vote,
+ // which will touch boost when there are no ExplicitDefault layer votes on the app.
+ // At most one app can have the "HighHint" touch boost vote at a time.
+ // This accounts for cases such as games that use `setFrameRate`
+ // with Default compatibility to limit the frame rate and disabling touch boost.
+ bool isAppTouchBoost = false;
+ const auto layersByUid = groupLayersByUid(layers);
+ for (const auto& [uid, layersWithSameUid] : layersByUid) {
+ bool hasHighHint = false;
+ bool hasExplicitDefault = false;
+ for (const auto& layer : layersWithSameUid) {
+ switch (layer->vote) {
+ case LayerVoteType::ExplicitDefault:
+ hasExplicitDefault = true;
+ break;
+ case LayerVoteType::ExplicitCategory:
+ if (layer->frameRateCategory == FrameRateCategory::HighHint) {
+ hasHighHint = true;
+ }
+ break;
+ default:
+ // No action
+ break;
+ }
+ if (hasHighHint && hasExplicitDefault) {
+ break;
+ }
+ }
+
+ if (hasHighHint && !hasExplicitDefault) {
+ // Focused app has touch signal (HighHint) and no frame rate ExplicitDefault votes
+ // (which prevents touch boost due to games use case).
+ isAppTouchBoost = true;
+ break;
+ }
+ }
+
int noVoteLayers = 0;
// Layers that prefer the same mode ("no-op").
int noPreferenceLayers = 0;
@@ -535,7 +586,6 @@
int explicitExact = 0;
int explicitGteLayers = 0;
int explicitCategoryVoteLayers = 0;
- int interactiveLayers = 0;
int seamedFocusedLayers = 0;
int categorySmoothSwitchOnlyLayers = 0;
@@ -563,11 +613,9 @@
explicitGteLayers++;
break;
case LayerVoteType::ExplicitCategory:
- if (layer.frameRateCategory == FrameRateCategory::HighHint) {
- // HighHint does not count as an explicit signal from an app. It may be
- // be a touch signal.
- interactiveLayers++;
- } else {
+ // HighHint does not count as an explicit signal from an app. It is a touch signal
+ // sent from UI Toolkit.
+ if (layer.frameRateCategory != FrameRateCategory::HighHint) {
explicitCategoryVoteLayers++;
}
if (layer.frameRateCategory == FrameRateCategory::NoPreference) {
@@ -877,14 +925,11 @@
return explicitCategoryVoteLayers + noVoteLayers + explicitGteLayers != layers.size();
};
- // A method for UI Toolkit to send the touch signal via "HighHint" category vote,
- // which will touch boost when there are no ExplicitDefault layer votes. This is an
- // incomplete solution but accounts for cases such as games that use `setFrameRate` with default
+ // This accounts for cases such as games that use `setFrameRate` with Default
// compatibility to limit the frame rate, which should not have touch boost.
- const bool hasInteraction = signals.touch || interactiveLayers > 0;
-
- if (hasInteraction && explicitDefaultVoteLayers == 0 && isTouchBoostForExplicitExact() &&
- isTouchBoostForCategory()) {
+ const bool isLateGlobalTouchBoost = signals.touch && explicitDefaultVoteLayers == 0;
+ const bool isLateTouchBoost = isLateGlobalTouchBoost || isAppTouchBoost;
+ if (isLateTouchBoost && isTouchBoostForExplicitExact() && isTouchBoostForCategory()) {
const auto touchRefreshRates = rankFrameRates(anchorGroup, RefreshRateOrder::Descending);
using fps_approx_ops::operator<;
@@ -912,40 +957,6 @@
return {ranking, kNoSignals};
}
-using LayerRequirementPtrs = std::vector<const RefreshRateSelector::LayerRequirement*>;
-using PerUidLayerRequirements = std::unordered_map<uid_t, LayerRequirementPtrs>;
-
-PerUidLayerRequirements groupLayersByUid(
- const std::vector<RefreshRateSelector::LayerRequirement>& layers) {
- PerUidLayerRequirements layersByUid;
- for (const auto& layer : layers) {
- const auto it = layersByUid.emplace(layer.ownerUid, LayerRequirementPtrs()).first;
- auto& layersWithSameUid = it->second;
- layersWithSameUid.push_back(&layer);
- }
-
- // Remove uids that can't have a frame rate override
- for (auto it = layersByUid.begin(); it != layersByUid.end();) {
- const auto& layersWithSameUid = it->second;
- bool skipUid = false;
- for (const auto& layer : layersWithSameUid) {
- using LayerVoteType = RefreshRateSelector::LayerVoteType;
-
- if (layer->vote == LayerVoteType::Max || layer->vote == LayerVoteType::Heuristic) {
- skipUid = true;
- break;
- }
- }
- if (skipUid) {
- it = layersByUid.erase(it);
- } else {
- ++it;
- }
- }
-
- return layersByUid;
-}
-
auto RefreshRateSelector::getFrameRateOverrides(const std::vector<LayerRequirement>& layers,
Fps displayRefreshRate,
GlobalSignals globalSignals) const
@@ -990,6 +1001,7 @@
bool hasExplicitExactOrMultiple = false;
bool hasExplicitDefault = false;
bool hasHighHint = false;
+ bool hasSkipOverrideLayer = false;
for (const auto& layer : layersWithSameUid) {
switch (layer->vote) {
case LayerVoteType::ExplicitExactOrMultiple:
@@ -1003,15 +1015,25 @@
hasHighHint = true;
}
break;
+ case LayerVoteType::Max:
+ case LayerVoteType::Heuristic:
+ hasSkipOverrideLayer = true;
+ break;
default:
// No action
break;
}
- if (hasExplicitExactOrMultiple && hasExplicitDefault && hasHighHint) {
+ if (hasExplicitExactOrMultiple && hasExplicitDefault && hasHighHint &&
+ hasSkipOverrideLayer) {
break;
}
}
+ if (hasSkipOverrideLayer) {
+ ALOGV("%s: Skipping due to vote(s): uid=%d", __func__, uid);
+ continue;
+ }
+
// Layers with ExplicitExactOrMultiple expect touch boost
if (globalSignals.touch && hasExplicitExactOrMultiple) {
continue;
@@ -1510,6 +1532,9 @@
mPrimaryFrameRates = filterRefreshRates(policy->primaryRanges, "primary");
mAppRequestFrameRates = filterRefreshRates(policy->appRequestRanges, "app request");
+ mAllFrameRates = filterRefreshRates(FpsRanges(getSupportedFrameRateRangeLocked(),
+ getSupportedFrameRateRangeLocked()),
+ "full frame rates");
}
bool RefreshRateSelector::isVrrDevice() const {
@@ -1535,6 +1560,27 @@
return distance1 < distance2 ? *lowerBound : *std::prev(lowerBound);
}
+std::vector<float> RefreshRateSelector::getSupportedFrameRates() const {
+ std::scoped_lock lock(mLock);
+ // TODO(b/356986687) Remove the limit once we have the anchor list implementation.
+ const size_t frameRatesSize = std::min<size_t>(11, mAllFrameRates.size());
+ std::vector<float> supportedFrameRates;
+ supportedFrameRates.reserve(frameRatesSize);
+ std::transform(mAllFrameRates.rbegin(),
+ mAllFrameRates.rbegin() + static_cast<int>(frameRatesSize),
+ std::back_inserter(supportedFrameRates),
+ [](FrameRateMode mode) { return mode.fps.getValue(); });
+ return supportedFrameRates;
+}
+
+FpsRange RefreshRateSelector::getSupportedFrameRateRangeLocked() const {
+ using fps_approx_ops::operator<;
+ if (mMaxRefreshRateModeIt->second->getPeakFps() < kMinSupportedFrameRate) {
+ return {mMaxRefreshRateModeIt->second->getPeakFps(), kMinSupportedFrameRate};
+ }
+ return {kMinSupportedFrameRate, mMaxRefreshRateModeIt->second->getPeakFps()};
+}
+
auto RefreshRateSelector::getIdleTimerAction() const -> KernelIdleTimerAction {
std::lock_guard lock(mLock);
@@ -1638,9 +1684,9 @@
FpsRange RefreshRateSelector::getFrameRateCategoryRange(FrameRateCategory category) {
switch (category) {
case FrameRateCategory::High:
- return FpsRange{90_Hz, 120_Hz};
+ return FpsRange{kFrameRateCategoryRateHigh, 120_Hz};
case FrameRateCategory::Normal:
- return FpsRange{60_Hz, 120_Hz};
+ return FpsRange{kFrameRateCategoryRateNormal, 120_Hz};
case FrameRateCategory::Low:
return FpsRange{48_Hz, 120_Hz};
case FrameRateCategory::HighHint:
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.h b/services/surfaceflinger/Scheduler/RefreshRateSelector.h
index a398c01..8e173b1 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.h
@@ -52,6 +52,12 @@
// The lowest Render Frame Rate that will ever be selected
static constexpr Fps kMinSupportedFrameRate = 20_Hz;
+ // Start range for FrameRateCategory Normal and High.
+ static constexpr Fps kFrameRateCategoryRateHigh = 90_Hz;
+ static constexpr Fps kFrameRateCategoryRateNormal = 60_Hz;
+ static constexpr std::pair<Fps, Fps> kFrameRateCategoryRates = {kFrameRateCategoryRateNormal,
+ kFrameRateCategoryRateHigh};
+
class Policy {
static constexpr int kAllowGroupSwitchingDefault = false;
@@ -433,6 +439,10 @@
bool isVrrDevice() const;
+ std::pair<Fps, Fps> getFrameRateCategoryRates() const { return kFrameRateCategoryRates; }
+
+ std::vector<float> getSupportedFrameRates() const EXCLUDES(mLock);
+
private:
friend struct TestableRefreshRateSelector;
@@ -543,6 +553,7 @@
// Display modes that satisfy the Policy's ranges, filtered and sorted by refresh rate.
std::vector<FrameRateMode> mPrimaryFrameRates GUARDED_BY(mLock);
std::vector<FrameRateMode> mAppRequestFrameRates GUARDED_BY(mLock);
+ std::vector<FrameRateMode> mAllFrameRates GUARDED_BY(mLock);
// Caches whether the device is VRR-compatible based on the active display mode.
std::atomic_bool mIsVrrDevice = false;
@@ -587,6 +598,9 @@
// Used to detect (lack of) frame activity.
ftl::Optional<scheduler::OneShotTimer> mIdleTimer;
std::atomic<bool> mIdleTimerStarted = false;
+
+ // Returns the range of supported frame rates.
+ FpsRange getSupportedFrameRateRangeLocked() const REQUIRES(mLock);
};
} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index b83ff19..4da76f6 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -203,12 +203,16 @@
void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId,
TimePoint expectedVsyncTime) {
+ const auto debugPresentDelay = mDebugPresentDelay.load();
+ mDebugPresentDelay.store(std::nullopt);
+
const FrameTargeter::BeginFrameArgs beginFrameArgs =
{.frameBeginTime = SchedulerClock::now(),
.vsyncId = vsyncId,
.expectedVsyncTime = expectedVsyncTime,
.sfWorkDuration = mVsyncModulator->getVsyncConfig().sfWorkDuration,
- .hwcMinWorkDuration = mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration};
+ .hwcMinWorkDuration = mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration,
+ .debugPresentTimeDelay = debugPresentDelay};
ftl::NonNull<const Display*> pacesetterPtr = pacesetterPtrLocked();
pacesetterPtr->targeterPtr->beginFrame(beginFrameArgs, *pacesetterPtr->schedulePtr);
@@ -238,7 +242,7 @@
if (FlagManager::getInstance().vrr_config()) {
compositor.sendNotifyExpectedPresentHint(pacesetterPtr->displayId);
}
- mSchedulerCallback.onCommitNotComposited(pacesetterPtr->displayId);
+ mSchedulerCallback.onCommitNotComposited();
return;
}
}
@@ -405,6 +409,14 @@
eventThreadFor(Cycle::Render).enableSyntheticVsync(enable);
}
+void Scheduler::omitVsyncDispatching(bool omitted) {
+ eventThreadFor(Cycle::Render).omitVsyncDispatching(omitted);
+ // Note: If we don't couple Cycle::LastComposite event thread, there is a black screen
+ // after boot. This is most likely sysui or system_server dependency on sf instance
+ // Choreographer
+ eventThreadFor(Cycle::LastComposite).omitVsyncDispatching(omitted);
+}
+
void Scheduler::onFrameRateOverridesChanged() {
const auto [pacesetterId, supportsFrameRateOverrideByContent] = [this] {
std::scoped_lock lock(mDisplayLock);
@@ -428,7 +440,8 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-value" // b/369277774
-bool Scheduler::onDisplayModeChanged(PhysicalDisplayId displayId, const FrameRateMode& mode) {
+bool Scheduler::onDisplayModeChanged(PhysicalDisplayId displayId, const FrameRateMode& mode,
+ bool clearContentRequirements) {
const bool isPacesetter =
FTL_FAKE_GUARD(kMainThreadContext,
(std::scoped_lock(mDisplayLock), displayId == mPacesetterDisplayId));
@@ -437,9 +450,11 @@
std::lock_guard<std::mutex> lock(mPolicyLock);
mPolicy.emittedModeOpt = mode;
- // Invalidate content based refresh rate selection so it could be calculated
- // again for the new refresh rate.
- mPolicy.contentRequirements.clear();
+ if (clearContentRequirements) {
+ // Invalidate content based refresh rate selection so it could be calculated
+ // again for the new refresh rate.
+ mPolicy.contentRequirements.clear();
+ }
}
if (hasEventThreads()) {
@@ -450,6 +465,12 @@
}
#pragma clang diagnostic pop
+void Scheduler::onDisplayModeRejected(PhysicalDisplayId displayId, DisplayModeId modeId) {
+ if (hasEventThreads()) {
+ eventThreadFor(Cycle::Render).onModeRejected(displayId, modeId);
+ }
+}
+
void Scheduler::emitModeChangeIfNeeded() {
if (!mPolicy.modeOpt || !mPolicy.emittedModeOpt) {
ALOGW("No mode change to emit");
@@ -940,6 +961,11 @@
return mFrameRateOverrideMappings.updateFrameRateOverridesByContent(frameRateOverrides);
}
+void Scheduler::addBufferStuffedUids(BufferStuffingMap bufferStuffedUids) {
+ if (!mRenderEventThread) return;
+ mRenderEventThread->addBufferStuffedUids(std::move(bufferStuffedUids));
+}
+
void Scheduler::promotePacesetterDisplay(PhysicalDisplayId pacesetterId, PromotionParams params) {
std::shared_ptr<VsyncSchedule> pacesetterVsyncSchedule;
{
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index c88b563..3fdddac 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -36,13 +36,14 @@
#include <ftl/non_null.h>
#include <ftl/optional.h>
#include <scheduler/Features.h>
+#include <scheduler/FrameRateMode.h>
#include <scheduler/FrameTargeter.h>
#include <scheduler/Time.h>
#include <scheduler/VsyncConfig.h>
#include <ui/DisplayId.h>
#include <ui/DisplayMap.h>
-#include "Display/DisplayModeRequest.h"
+#include "DisplayHardware/DisplayMode.h"
#include "EventThread.h"
#include "FrameRateOverrideMappings.h"
#include "ISchedulerCallback.h"
@@ -151,9 +152,13 @@
void dispatchHotplugError(int32_t errorCode);
// Returns true if the PhysicalDisplayId is the pacesetter.
- bool onDisplayModeChanged(PhysicalDisplayId, const FrameRateMode&) EXCLUDES(mPolicyLock);
+ bool onDisplayModeChanged(PhysicalDisplayId, const FrameRateMode&,
+ bool clearContentRequirements) EXCLUDES(mPolicyLock);
+
+ void onDisplayModeRejected(PhysicalDisplayId, DisplayModeId);
void enableSyntheticVsync(bool = true) REQUIRES(kMainThreadContext);
+ void omitVsyncDispatching(bool) REQUIRES(kMainThreadContext);
void onHdcpLevelsChanged(Cycle, PhysicalDisplayId, int32_t, int32_t);
@@ -332,6 +337,12 @@
mPacesetterFrameDurationFractionToSkip = frameDurationFraction;
}
+ // Propagates a flag to the EventThread indicating that buffer stuffing
+ // recovery should begin.
+ void addBufferStuffedUids(BufferStuffingMap bufferStuffedUids);
+
+ void setDebugPresentDelay(TimePoint delay) { mDebugPresentDelay = delay; }
+
private:
friend class TestableScheduler;
@@ -597,6 +608,8 @@
FrameRateOverrideMappings mFrameRateOverrideMappings;
SmallAreaDetectionAllowMappings mSmallAreaDetectionAllowMappings;
+
+ std::atomic<std::optional<TimePoint>> mDebugPresentDelay;
};
} // namespace scheduler
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index 6e36f02..b9c79df 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -206,7 +206,11 @@
// Normalizing to the oldest timestamp cuts down on error in calculating the intercept.
const auto oldestTS = *std::min_element(mTimestamps.begin(), mTimestamps.end());
auto it = mRateMap.find(idealPeriod());
- auto const currentPeriod = it->second.slope;
+ // Calculated slope over the period of time can become outdated as the new timestamps are
+ // stored. Using idealPeriod instead provides a rate which is valid at all the times.
+ auto const currentPeriod = FlagManager::getInstance().vsync_predictor_recovery()
+ ? idealPeriod()
+ : it->second.slope;
// The mean of the ordinals must be precise for the intercept calculation, so scale them up for
// fixed-point arithmetic.
@@ -458,7 +462,8 @@
Duration VSyncPredictor::ensureMinFrameDurationIsKept(TimePoint expectedPresentTime,
TimePoint lastConfirmedPresentTime) {
- SFTRACE_CALL();
+ SFTRACE_FORMAT("%s mNumVsyncsForFrame=%d mPastExpectedPresentTimes.size()=%zu", __func__,
+ mNumVsyncsForFrame, mPastExpectedPresentTimes.size());
if (mNumVsyncsForFrame <= 1) {
return 0ns;
@@ -470,12 +475,8 @@
auto prev = lastConfirmedPresentTime.ns();
for (auto& current : mPastExpectedPresentTimes) {
- if (CC_UNLIKELY(mTraceOn)) {
- SFTRACE_FORMAT_INSTANT("current %.2f past last signaled fence",
- static_cast<float>(current.ns() -
- lastConfirmedPresentTime.ns()) /
- 1e6f);
- }
+ SFTRACE_FORMAT_INSTANT("current %.2f past last signaled fence",
+ static_cast<float>(current.ns() - prev) / 1e6f);
const auto minPeriodViolation = current.ns() - prev + threshold < minFramePeriod.ns();
if (minPeriodViolation) {
@@ -522,11 +523,9 @@
const auto front = mPastExpectedPresentTimes.front().ns();
const bool frontIsBeforeConfirmed = front < lastConfirmedPresentTime.ns() + threshold;
if (frontIsBeforeConfirmed) {
- if (CC_UNLIKELY(mTraceOn)) {
- SFTRACE_FORMAT_INSTANT("Discarding old vsync - %.2f before last signaled fence",
- static_cast<float>(lastConfirmedPresentTime.ns() - front) /
- 1e6f);
- }
+ SFTRACE_FORMAT_INSTANT("Discarding old vsync - %.2f before last signaled fence",
+ static_cast<float>(lastConfirmedPresentTime.ns() - front) /
+ 1e6f);
mPastExpectedPresentTimes.pop_front();
} else {
break;
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h b/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h
index f2be316..4dd3ab6 100644
--- a/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h
+++ b/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h
@@ -33,6 +33,10 @@
}
bool operator!=(const FrameRateMode& other) const { return !(*this == other); }
+
+ bool matchesResolution(const FrameRateMode& other) const {
+ return modePtr->getResolution() == other.modePtr->getResolution();
+ }
};
inline std::string to_string(const FrameRateMode& mode) {
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h b/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h
index 2185bb0..813d4de 100644
--- a/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h
+++ b/services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h
@@ -53,6 +53,8 @@
TimePoint expectedPresentTime() const { return mExpectedPresentTime; }
+ std::optional<TimePoint> debugPresentDelay() const { return mDebugPresentTimeDelay; }
+
std::optional<TimePoint> earliestPresentTime() const { return mEarliestPresentTime; }
// Equivalent to `expectedSignaledPresentFence` unless running N VSYNCs ahead.
@@ -84,6 +86,7 @@
TimePoint mFrameBeginTime;
TimePoint mExpectedPresentTime;
std::optional<TimePoint> mEarliestPresentTime;
+ std::optional<TimePoint> mDebugPresentTimeDelay;
TracedOrdinal<bool> mFramePending;
TracedOrdinal<bool> mFrameMissed;
@@ -135,6 +138,7 @@
TimePoint expectedVsyncTime;
Duration sfWorkDuration;
Duration hwcMinWorkDuration;
+ std::optional<TimePoint> debugPresentTimeDelay; // used to introduce jank for testing
};
void beginFrame(const BeginFrameArgs&, const IVsyncSource&);
diff --git a/services/surfaceflinger/Scheduler/src/FrameTargeter.cpp b/services/surfaceflinger/Scheduler/src/FrameTargeter.cpp
index 3ee1e54..5019949 100644
--- a/services/surfaceflinger/Scheduler/src/FrameTargeter.cpp
+++ b/services/surfaceflinger/Scheduler/src/FrameTargeter.cpp
@@ -31,6 +31,7 @@
std::pair<bool /* wouldBackpressure */, FrameTarget::PresentFence>
FrameTarget::expectedSignaledPresentFence(Period vsyncPeriod, Period minFramePeriod) const {
+ SFTRACE_CALL();
if (!FlagManager::getInstance().allow_n_vsyncs_in_targeter()) {
const size_t i = static_cast<size_t>(targetsVsyncsAhead<2>(minFramePeriod));
return {true, mPresentFencesLegacy[i]};
@@ -40,17 +41,28 @@
auto expectedPresentTime = mExpectedPresentTime;
for (size_t i = mPresentFences.size(); i != 0; --i) {
const auto& fence = mPresentFences[i - 1];
+ SFTRACE_FORMAT_INSTANT("fence at idx: %zu expectedPresentTime in %.2f", i - 1,
+ ticks<std::milli, float>(fence.expectedPresentTime -
+ TimePoint::now()));
if (fence.expectedPresentTime + minFramePeriod < expectedPresentTime - vsyncPeriod / 2) {
+ SFTRACE_FORMAT_INSTANT("would not backpressure");
wouldBackpressure = false;
}
if (fence.expectedPresentTime <= mFrameBeginTime) {
+ SFTRACE_FORMAT_INSTANT("fence at idx: %zu is %.2f before frame begin "
+ "(wouldBackpressure=%s)",
+ i - 1,
+ ticks<std::milli, float>(mFrameBeginTime -
+ fence.expectedPresentTime),
+ wouldBackpressure ? "true" : "false");
return {wouldBackpressure, fence};
}
expectedPresentTime = fence.expectedPresentTime;
}
+ SFTRACE_FORMAT_INSTANT("No fence found");
return {wouldBackpressure, PresentFence{}};
}
@@ -86,6 +98,7 @@
IsFencePendingFuncPtr isFencePendingFuncPtr) {
mVsyncId = args.vsyncId;
mFrameBeginTime = args.frameBeginTime;
+ mDebugPresentTimeDelay = args.debugPresentTimeDelay;
// The `expectedVsyncTime`, which was predicted when this frame was scheduled, is normally in
// the future relative to `frameBeginTime`, but may not be for delayed frames. Adjust
@@ -153,6 +166,12 @@
if (pastPresentTime < 0) return false;
mLastSignaledFrameTime = {.signalTime = TimePoint::fromNs(pastPresentTime),
.expectedPresentTime = fence.expectedPresentTime};
+ SFTRACE_FORMAT_INSTANT("LastSignaledFrameTime expectedPresentTime %.2f ago, signalTime "
+ "%.2f ago",
+ ticks<std::milli, float>(mLastSignaledFrameTime.expectedPresentTime -
+ TimePoint::now()),
+ ticks<std::milli, float>(mLastSignaledFrameTime.signalTime -
+ TimePoint::now()));
const nsecs_t frameMissedSlop = vsyncPeriod.ns() / 2;
return lastScheduledPresentTime.ns() < pastPresentTime - frameMissedSlop;
}();
diff --git a/services/surfaceflinger/Scheduler/src/Timer.cpp b/services/surfaceflinger/Scheduler/src/Timer.cpp
index 20c58eb..6a5eeba 100644
--- a/services/surfaceflinger/Scheduler/src/Timer.cpp
+++ b/services/surfaceflinger/Scheduler/src/Timer.cpp
@@ -24,6 +24,7 @@
#include <sys/timerfd.h>
#include <sys/unistd.h>
+#include <common/FlagManager.h>
#include <common/trace.h>
#include <ftl/concat.h>
#include <ftl/enum.h>
@@ -155,8 +156,10 @@
setDebugState(DebugState::Running);
struct sched_param param = {0};
param.sched_priority = 2;
- if (pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m) != 0) {
- ALOGW("Failed to set SCHED_FIFO on dispatch thread");
+ if (!FlagManager::getInstance().disable_sched_fifo_sf_sched()) {
+ if (pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m) != 0) {
+ ALOGW("Failed to set SCHED_FIFO on dispatch thread");
+ }
}
if (pthread_setname_np(pthread_self(), "TimerDispatch") != 0) {
diff --git a/services/surfaceflinger/ScreenCaptureOutput.cpp b/services/surfaceflinger/ScreenCaptureOutput.cpp
index 41a9a1b..af6d4d3 100644
--- a/services/surfaceflinger/ScreenCaptureOutput.cpp
+++ b/services/surfaceflinger/ScreenCaptureOutput.cpp
@@ -16,22 +16,28 @@
#include "ScreenCaptureOutput.h"
#include "ScreenCaptureRenderSurface.h"
+#include "common/include/common/FlagManager.h"
#include "ui/Rotation.h"
#include <compositionengine/CompositionEngine.h>
#include <compositionengine/DisplayColorProfileCreationArgs.h>
#include <compositionengine/impl/DisplayColorProfile.h>
+#include <ui/HdrRenderTypeUtils.h>
#include <ui/Rotation.h>
namespace android {
std::shared_ptr<ScreenCaptureOutput> createScreenCaptureOutput(ScreenCaptureOutputArgs args) {
std::shared_ptr<ScreenCaptureOutput> output = compositionengine::impl::createOutputTemplated<
- ScreenCaptureOutput, compositionengine::CompositionEngine, const RenderArea&,
+ ScreenCaptureOutput, compositionengine::CompositionEngine,
+ /* sourceCrop */ const Rect, std::optional<DisplayId>,
const compositionengine::Output::ColorProfile&,
- bool>(args.compositionEngine, args.renderArea, args.colorProfile, args.regionSampling,
- args.dimInGammaSpaceForEnhancedScreenshots, args.enableLocalTonemapping);
- output->editState().isSecure = args.renderArea.isSecure();
+ /* layerAlpha */ float,
+ /* regionSampling */ bool>(args.compositionEngine, args.sourceCrop, args.displayId,
+ args.colorProfile, args.layerAlpha, args.regionSampling,
+ args.dimInGammaSpaceForEnhancedScreenshots,
+ args.enableLocalTonemapping);
+ output->editState().isSecure = args.isSecure;
output->editState().isProtected = args.isProtected;
output->setCompositionEnabled(true);
output->setLayerFilter({args.layerStack});
@@ -45,16 +51,16 @@
.setHasWideColorGamut(true)
.Build()));
- const Rect& sourceCrop = args.renderArea.getSourceCrop();
+ const Rect& sourceCrop = args.sourceCrop;
const ui::Rotation orientation = ui::ROTATION_0;
output->setDisplaySize({sourceCrop.getWidth(), sourceCrop.getHeight()});
output->setProjection(orientation, sourceCrop,
- {args.renderArea.getReqWidth(), args.renderArea.getReqHeight()});
+ {args.reqBufferSize.width, args.reqBufferSize.height});
{
std::string name = args.regionSampling ? "RegionSampling" : "ScreenCaptureOutput";
- if (auto displayDevice = args.renderArea.getDisplayDevice()) {
- base::StringAppendF(&name, " for %" PRIu64, displayDevice->getId().value);
+ if (args.displayId) {
+ base::StringAppendF(&name, " for %" PRIu64, args.displayId.value().value);
}
output->setName(name);
}
@@ -62,11 +68,14 @@
}
ScreenCaptureOutput::ScreenCaptureOutput(
- const RenderArea& renderArea, const compositionengine::Output::ColorProfile& colorProfile,
+ const Rect sourceCrop, std::optional<DisplayId> displayId,
+ const compositionengine::Output::ColorProfile& colorProfile, float layerAlpha,
bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots,
bool enableLocalTonemapping)
- : mRenderArea(renderArea),
+ : mSourceCrop(sourceCrop),
+ mDisplayId(displayId),
mColorProfile(colorProfile),
+ mLayerAlpha(layerAlpha),
mRegionSampling(regionSampling),
mDimInGammaSpaceForEnhancedScreenshots(dimInGammaSpaceForEnhancedScreenshots),
mEnableLocalTonemapping(enableLocalTonemapping) {}
@@ -81,7 +90,7 @@
const std::shared_ptr<renderengine::ExternalTexture>& buffer) const {
auto clientCompositionDisplay =
compositionengine::impl::Output::generateClientCompositionDisplaySettings(buffer);
- clientCompositionDisplay.clip = mRenderArea.getSourceCrop();
+ clientCompositionDisplay.clip = mSourceCrop;
auto renderIntent = static_cast<ui::RenderIntent>(clientCompositionDisplay.renderIntent);
if (mDimInGammaSpaceForEnhancedScreenshots && renderIntent != ui::RenderIntent::COLORIMETRIC &&
@@ -104,14 +113,84 @@
return clientCompositionDisplay;
}
+std::unordered_map<int32_t, aidl::android::hardware::graphics::composer3::Luts>
+ScreenCaptureOutput::generateLuts() {
+ std::unordered_map<int32_t, aidl::android::hardware::graphics::composer3::Luts> lutsMapper;
+ if (FlagManager::getInstance().luts_api()) {
+ std::vector<sp<GraphicBuffer>> buffers;
+ std::vector<int32_t> layerIds;
+
+ for (const auto* layer : getOutputLayersOrderedByZ()) {
+ const auto& layerState = layer->getState();
+ const auto* layerFEState = layer->getLayerFE().getCompositionState();
+ auto pixelFormat = layerFEState->buffer
+ ? std::make_optional(
+ static_cast<ui::PixelFormat>(layerFEState->buffer->getPixelFormat()))
+ : std::nullopt;
+ const auto hdrType = getHdrRenderType(layerState.dataspace, pixelFormat,
+ layerFEState->desiredHdrSdrRatio);
+ if (layerFEState->buffer && !layerFEState->luts &&
+ hdrType == HdrRenderType::GENERIC_HDR) {
+ buffers.push_back(layerFEState->buffer);
+ layerIds.push_back(layer->getLayerFE().getSequence());
+ }
+ }
+
+ std::vector<aidl::android::hardware::graphics::composer3::Luts> luts;
+ if (mDisplayId) {
+ const auto id = PhysicalDisplayId::tryCast(mDisplayId.value());
+ if (id) {
+ auto& hwc = getCompositionEngine().getHwComposer();
+ hwc.getLuts(*id, buffers, &luts);
+ }
+ }
+
+ if (buffers.size() == luts.size()) {
+ for (size_t i = 0; i < luts.size(); i++) {
+ lutsMapper[layerIds[i]] = std::move(luts[i]);
+ }
+ }
+ }
+ return lutsMapper;
+}
+
std::vector<compositionengine::LayerFE::LayerSettings>
ScreenCaptureOutput::generateClientCompositionRequests(
bool supportsProtectedContent, ui::Dataspace outputDataspace,
std::vector<compositionengine::LayerFE*>& outLayerFEs) {
+ // This map maps the layer unique id to a Lut
+ std::unordered_map<int32_t, aidl::android::hardware::graphics::composer3::Luts> lutsMapper =
+ generateLuts();
+
auto clientCompositionLayers = compositionengine::impl::Output::
generateClientCompositionRequests(supportsProtectedContent, outputDataspace,
outLayerFEs);
+ for (auto& layer : clientCompositionLayers) {
+ if (lutsMapper.find(layer.sequence) != lutsMapper.end()) {
+ auto& aidlLuts = lutsMapper[layer.sequence];
+ if (aidlLuts.pfd.get() >= 0 && aidlLuts.offsets) {
+ std::vector<int32_t> offsets = *aidlLuts.offsets;
+ std::vector<int32_t> dimensions;
+ dimensions.reserve(offsets.size());
+ std::vector<int32_t> sizes;
+ sizes.reserve(offsets.size());
+ std::vector<int32_t> keys;
+ keys.reserve(offsets.size());
+ for (size_t j = 0; j < offsets.size(); j++) {
+ dimensions.emplace_back(
+ static_cast<int32_t>(aidlLuts.lutProperties[j].dimension));
+ sizes.emplace_back(aidlLuts.lutProperties[j].size);
+ keys.emplace_back(
+ static_cast<int32_t>(aidlLuts.lutProperties[j].samplingKeys[0]));
+ }
+ layer.luts = std::make_shared<gui::DisplayLuts>(base::unique_fd(
+ aidlLuts.pfd.dup().get()),
+ offsets, dimensions, sizes, keys);
+ }
+ }
+ }
+
if (mRegionSampling) {
for (auto& layer : clientCompositionLayers) {
layer.backgroundBlurRadius = 0;
@@ -129,14 +208,16 @@
}
}
- Rect sourceCrop = mRenderArea.getSourceCrop();
compositionengine::LayerFE::LayerSettings fillLayer;
+ fillLayer.name = "ScreenCaptureFillLayer";
fillLayer.source.buffer.buffer = nullptr;
fillLayer.source.solidColor = half3(0.0f, 0.0f, 0.0f);
fillLayer.geometry.boundaries =
- FloatRect(static_cast<float>(sourceCrop.left), static_cast<float>(sourceCrop.top),
- static_cast<float>(sourceCrop.right), static_cast<float>(sourceCrop.bottom));
- fillLayer.alpha = half(RenderArea::getCaptureFillValue(mRenderArea.getCaptureFill()));
+ FloatRect(static_cast<float>(mSourceCrop.left), static_cast<float>(mSourceCrop.top),
+ static_cast<float>(mSourceCrop.right),
+ static_cast<float>(mSourceCrop.bottom));
+
+ fillLayer.alpha = half(mLayerAlpha);
clientCompositionLayers.insert(clientCompositionLayers.begin(), fillLayer);
return clientCompositionLayers;
diff --git a/services/surfaceflinger/ScreenCaptureOutput.h b/services/surfaceflinger/ScreenCaptureOutput.h
index c233ead..b3e98b1 100644
--- a/services/surfaceflinger/ScreenCaptureOutput.h
+++ b/services/surfaceflinger/ScreenCaptureOutput.h
@@ -20,24 +20,27 @@
#include <compositionengine/RenderSurface.h>
#include <compositionengine/impl/Output.h>
#include <ui/Rect.h>
-
-#include "RenderArea.h"
+#include <unordered_map>
namespace android {
struct ScreenCaptureOutputArgs {
const compositionengine::CompositionEngine& compositionEngine;
const compositionengine::Output::ColorProfile& colorProfile;
- const RenderArea& renderArea;
ui::LayerStack layerStack;
+ Rect sourceCrop;
std::shared_ptr<renderengine::ExternalTexture> buffer;
+ std::optional<DisplayId> displayId;
+ ui::Size reqBufferSize;
float sdrWhitePointNits;
float displayBrightnessNits;
// Counterintuitively, when targetBrightness > 1.0 then dim the scene.
float targetBrightness;
+ float layerAlpha;
bool regionSampling;
bool treat170mAsSrgb;
bool dimInGammaSpaceForEnhancedScreenshots;
+ bool isSecure = false;
bool isProtected = false;
bool enableLocalTonemapping = false;
};
@@ -48,10 +51,10 @@
// SurfaceFlinger::captureLayers and SurfaceFlinger::captureDisplay.
class ScreenCaptureOutput : public compositionengine::impl::Output {
public:
- ScreenCaptureOutput(const RenderArea& renderArea,
+ ScreenCaptureOutput(const Rect sourceCrop, std::optional<DisplayId> displayId,
const compositionengine::Output::ColorProfile& colorProfile,
- bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots,
- bool enableLocalTonemapping);
+ float layerAlpha, bool regionSampling,
+ bool dimInGammaSpaceForEnhancedScreenshots, bool enableLocalTonemapping);
void updateColorProfile(const compositionengine::CompositionRefreshArgs&) override;
@@ -65,8 +68,11 @@
const std::shared_ptr<renderengine::ExternalTexture>& buffer) const override;
private:
- const RenderArea& mRenderArea;
+ std::unordered_map<int32_t, aidl::android::hardware::graphics::composer3::Luts> generateLuts();
+ const Rect mSourceCrop;
+ const std::optional<DisplayId> mDisplayId;
const compositionengine::Output::ColorProfile& mColorProfile;
+ const float mLayerAlpha;
const bool mRegionSampling;
const bool mDimInGammaSpaceForEnhancedScreenshots;
const bool mEnableLocalTonemapping;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index cad179c..35cb63e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -37,12 +37,14 @@
#include <android/hardware/configstore/1.1/types.h>
#include <android/native_window.h>
#include <android/os/IInputFlinger.h>
+#include <android_os.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/PermissionCache.h>
#include <com_android_graphics_libgui_flags.h>
#include <com_android_graphics_surfaceflinger_flags.h>
#include <common/FlagManager.h>
+#include <common/WorkloadTracer.h>
#include <common/trace.h>
#include <compositionengine/CompositionEngine.h>
#include <compositionengine/CompositionRefreshArgs.h>
@@ -64,11 +66,13 @@
#include <ftl/concat.h>
#include <ftl/fake_guard.h>
#include <ftl/future.h>
+#include <ftl/small_map.h>
#include <ftl/unit.h>
#include <gui/AidlUtil.h>
#include <gui/BufferQueue.h>
#include <gui/DebugEGLImageTracker.h>
#include <gui/IProducerListener.h>
+#include <gui/JankInfo.h>
#include <gui/LayerMetadata.h>
#include <gui/LayerState.h>
#include <gui/Surface.h>
@@ -83,6 +87,7 @@
#include <renderengine/RenderEngine.h>
#include <renderengine/impl/ExternalTexture.h>
#include <scheduler/FrameTargeter.h>
+#include <statslog_surfaceflinger.h>
#include <sys/types.h>
#include <ui/ColorSpace.h>
#include <ui/DebugUtils.h>
@@ -91,6 +96,7 @@
#include <ui/DisplayStatInfo.h>
#include <ui/DisplayState.h>
#include <ui/DynamicDisplayInfo.h>
+#include <ui/FrameRateCategoryRate.h>
#include <ui/GraphicBufferAllocator.h>
#include <ui/HdrRenderTypeUtils.h>
#include <ui/LayerStack.h>
@@ -129,11 +135,8 @@
#include "DisplayDevice.h"
#include "DisplayHardware/ComposerHal.h"
#include "DisplayHardware/FramebufferSurface.h"
-#include "DisplayHardware/HWComposer.h"
#include "DisplayHardware/Hal.h"
-#include "DisplayHardware/PowerAdvisor.h"
#include "DisplayHardware/VirtualDisplaySurface.h"
-#include "DisplayRenderArea.h"
#include "Effects/Daltonizer.h"
#include "FpsReporter.h"
#include "FrameTimeline/FrameTimeline.h"
@@ -147,12 +150,12 @@
#include "Jank/JankTracker.h"
#include "Layer.h"
#include "LayerProtoHelper.h"
-#include "LayerRenderArea.h"
#include "LayerVector.h"
#include "MutexUtils.h"
#include "NativeWindowSurface.h"
+#include "PowerAdvisor/PowerAdvisor.h"
+#include "PowerAdvisor/Workload.h"
#include "RegionSamplingThread.h"
-#include "RenderAreaBuilder.h"
#include "Scheduler/EventThread.h"
#include "Scheduler/LayerHistory.h"
#include "Scheduler/Scheduler.h"
@@ -167,6 +170,7 @@
#include <aidl/android/hardware/graphics/common/DisplayDecorationSupport.h>
#include <aidl/android/hardware/graphics/composer3/DisplayCapability.h>
+#include <aidl/android/hardware/graphics/composer3/OutputType.h>
#include <aidl/android/hardware/graphics/composer3/RenderIntent.h>
#undef NO_THREAD_SAFETY_ANALYSIS
@@ -368,6 +372,7 @@
const String16 sRotateSurfaceFlinger("android.permission.ROTATE_SURFACE_FLINGER");
const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
const String16 sControlDisplayBrightness("android.permission.CONTROL_DISPLAY_BRIGHTNESS");
+const String16 sObservePictureProfiles("android.permission.OBSERVE_PICTURE_PROFILES");
const String16 sDump("android.permission.DUMP");
const String16 sCaptureBlackoutContent("android.permission.CAPTURE_BLACKOUT_CONTENT");
const String16 sInternalSystemWindow("android.permission.INTERNAL_SYSTEM_WINDOW");
@@ -424,7 +429,11 @@
mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)),
mInternalDisplayDensity(
getDensityFromProperty("ro.sf.lcd_density", !mEmulatedDisplayDensity)),
- mPowerAdvisor(std::make_unique<Hwc2::impl::PowerAdvisor>(*this)),
+ mPowerAdvisor(std::make_unique<
+ adpf::impl::PowerAdvisor>([this] { disableExpensiveRendering(); },
+ std::chrono::milliseconds(
+ sysprop::display_update_imminent_timeout_ms(
+ 80)))),
mWindowInfosListenerInvoker(sp<WindowInfosListenerInvoker>::make()),
mSkipPowerOnForQuiescent(base::GetBoolProperty("ro.boot.quiescent"s, false)) {
ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str());
@@ -639,11 +648,12 @@
}
}
-VirtualDisplayId SurfaceFlinger::acquireVirtualDisplay(ui::Size resolution,
- ui::PixelFormat format) {
+VirtualDisplayId SurfaceFlinger::acquireVirtualDisplay(ui::Size resolution, ui::PixelFormat format,
+ const std::string& uniqueId) {
if (auto& generator = mVirtualDisplayIdGenerators.hal) {
if (const auto id = generator->generateId()) {
if (getHwComposer().allocateVirtualDisplay(*id, resolution, &format)) {
+ acquireVirtualDisplaySnapshot(*id, uniqueId);
return *id;
}
@@ -657,6 +667,7 @@
const auto id = mVirtualDisplayIdGenerators.gpu.generateId();
LOG_ALWAYS_FATAL_IF(!id, "Failed to generate ID for GPU virtual display");
+ acquireVirtualDisplaySnapshot(*id, uniqueId);
return *id;
}
@@ -664,6 +675,7 @@
if (const auto id = HalVirtualDisplayId::tryCast(displayId)) {
if (auto& generator = mVirtualDisplayIdGenerators.hal) {
generator->releaseId(*id);
+ releaseVirtualDisplaySnapshot(*id);
}
return;
}
@@ -671,6 +683,14 @@
const auto id = GpuVirtualDisplayId::tryCast(displayId);
LOG_ALWAYS_FATAL_IF(!id);
mVirtualDisplayIdGenerators.gpu.releaseId(*id);
+ releaseVirtualDisplaySnapshot(*id);
+}
+
+void SurfaceFlinger::releaseVirtualDisplaySnapshot(VirtualDisplayId displayId) {
+ std::lock_guard lock(mVirtualDisplaysMutex);
+ if (!mVirtualDisplays.erase(displayId)) {
+ ALOGW("%s: Virtual display snapshot was not removed", __func__);
+ }
}
std::vector<PhysicalDisplayId> SurfaceFlinger::getPhysicalDisplayIdsLocked() const {
@@ -720,7 +740,10 @@
mBootFinished = true;
FlagManager::getMutableInstance().markBootCompleted();
- ::tracing_perfetto::registerWithPerfetto();
+ if (android::os::perfetto_sdk_tracing()) {
+ ::tracing_perfetto::registerWithPerfetto();
+ }
+
mInitBootPropsFuture.wait();
mRenderEnginePrimeCacheFuture.wait();
@@ -787,6 +810,12 @@
}));
}
+bool shouldUseGraphiteIfCompiledAndSupported() {
+ return FlagManager::getInstance().graphite_renderengine() ||
+ (FlagManager::getInstance().graphite_renderengine_preview_rollout() &&
+ base::GetBoolProperty(PROPERTY_DEBUG_RENDERENGINE_GRAPHITE_PREVIEW_OPTIN, false));
+}
+
void chooseRenderEngineType(renderengine::RenderEngineCreationArgs::Builder& builder) {
char prop[PROPERTY_VALUE_MAX];
property_get(PROPERTY_DEBUG_RENDERENGINE_BACKEND, prop, "");
@@ -815,14 +844,13 @@
// is used by layertracegenerator (which also needs SurfaceFlinger.cpp). :)
#if COM_ANDROID_GRAPHICS_SURFACEFLINGER_FLAGS_GRAPHITE_RENDERENGINE || \
COM_ANDROID_GRAPHICS_SURFACEFLINGER_FLAGS_FORCE_COMPILE_GRAPHITE_RENDERENGINE
- const bool useGraphite = FlagManager::getInstance().graphite_renderengine() &&
+ const bool useGraphite = shouldUseGraphiteIfCompiledAndSupported() &&
renderengine::RenderEngine::canSupport(kVulkan);
#else
const bool useGraphite = false;
- if (FlagManager::getInstance().graphite_renderengine()) {
- ALOGE("RenderEngine's Graphite Skia backend was requested with the "
- "debug.renderengine.graphite system property, but it is not compiled in this "
- "build! Falling back to Ganesh backend selection logic.");
+ if (shouldUseGraphiteIfCompiledAndSupported()) {
+ ALOGE("RenderEngine's Graphite Skia backend was requested, but it is not compiled in "
+ "this build! Falling back to Ganesh backend selection logic.");
}
#endif
const bool useVulkan = useGraphite ||
@@ -849,7 +877,12 @@
return renderengine::RenderEngine::BlurAlgorithm::GAUSSIAN;
} else if (algorithm == "kawase2") {
return renderengine::RenderEngine::BlurAlgorithm::KAWASE_DUAL_FILTER;
+ } else if (algorithm == "kawase") {
+ return renderengine::RenderEngine::BlurAlgorithm::KAWASE;
} else {
+ if (FlagManager::getInstance().window_blur_kawase2()) {
+ return renderengine::RenderEngine::BlurAlgorithm::KAWASE_DUAL_FILTER;
+ }
return renderengine::RenderEngine::BlurAlgorithm::KAWASE;
}
}
@@ -887,7 +920,8 @@
mCompositionEngine->setTimeStats(mTimeStats);
- mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName));
+ mHWComposer = getFactory().createHWComposer(mHwcServiceName);
+ mCompositionEngine->setHwComposer(mHWComposer.get());
auto& composer = mCompositionEngine->getHwComposer();
composer.setCallback(*this);
mDisplayModeController.setHwComposer(&composer);
@@ -1008,7 +1042,8 @@
config.cacheUltraHDR =
base::GetBoolProperty("ro.surface_flinger.prime_shader_cache.ultrahdr"s, false);
config.cacheEdgeExtension =
- base::GetBoolProperty("debug.sf.edge_extension_shader"s, true);
+ base::GetBoolProperty("debug.sf.prime_shader_cache.edge_extension_shader"s,
+ true);
return getRenderEngine().primeCache(config);
});
@@ -1032,7 +1067,8 @@
void SurfaceFlinger::initBootProperties() {
property_set("service.sf.present_timestamp", mHasReliablePresentFences ? "1" : "0");
- if (base::GetBoolProperty("debug.sf.boot_animation"s, true)) {
+ if (base::GetBoolProperty("debug.sf.boot_animation"s, true) &&
+ (base::GetIntProperty("debug.sf.nobootanimation"s, 0) == 0)) {
// Reset and (if needed) start BootAnimation.
property_set("service.bootanim.exit", "0");
property_set("service.bootanim.progress", "0");
@@ -1127,8 +1163,8 @@
}
Mutex::Autolock lock(mStateLock);
- const auto id = DisplayId::fromValue<PhysicalDisplayId>(static_cast<uint64_t>(displayId));
- const auto displayOpt = mPhysicalDisplays.get(*id).and_then(getDisplayDeviceAndSnapshot());
+ const PhysicalDisplayId id = PhysicalDisplayId::fromValue(static_cast<uint64_t>(displayId));
+ const auto displayOpt = mPhysicalDisplays.get(id).and_then(getDisplayDeviceAndSnapshot());
if (!displayOpt) {
return NAME_NOT_FOUND;
@@ -1216,6 +1252,12 @@
info->activeDisplayModeId = ftl::to_underlying(mode.modePtr->getId());
info->renderFrameRate = mode.fps.getValue();
info->hasArrSupport = mode.modePtr->getVrrConfig() && FlagManager::getInstance().vrr_config();
+
+ const auto [normal, high] = display->refreshRateSelector().getFrameRateCategoryRates();
+ ui::FrameRateCategoryRate frameRateCategoryRate(normal.getValue(), high.getValue());
+ info->frameRateCategoryRate = frameRateCategoryRate;
+
+ info->supportedRefreshRates = display->refreshRateSelector().getSupportedFrameRates();
info->activeColorMode = display->getCompositionDisplay()->getState().colorMode;
info->hdrCapabilities = filterOut4k30(display->getHdrCapabilities());
@@ -1244,9 +1286,9 @@
Mutex::Autolock lock(mStateLock);
- const auto id_ =
- DisplayId::fromValue<PhysicalDisplayId>(static_cast<uint64_t>(physicalDisplayId));
- const auto displayOpt = mPhysicalDisplays.get(*id_).and_then(getDisplayDeviceAndSnapshot());
+ const PhysicalDisplayId id =
+ PhysicalDisplayId::fromValue(static_cast<uint64_t>(physicalDisplayId));
+ const auto displayOpt = mPhysicalDisplays.get(id).and_then(getDisplayDeviceAndSnapshot());
if (!displayOpt) {
return NAME_NOT_FOUND;
@@ -1321,7 +1363,8 @@
const auto selectorPtr = mDisplayModeController.selectorPtrFor(displayId);
if (!selectorPtr) break;
- const Fps renderRate = selectorPtr->getActiveMode().fps;
+ const auto activeMode = selectorPtr->getActiveMode();
+ const Fps renderRate = activeMode.fps;
// DisplayModeController::setDesiredMode updated the render rate, so inform Scheduler.
mScheduler->setRenderRate(displayId, renderRate, true /* applyImmediately */);
@@ -1340,6 +1383,15 @@
mScheduler->updatePhaseConfiguration(displayId, mode.fps);
mScheduler->setModeChangePending(true);
+
+ // The mode set to switch resolution is not initiated until the display transaction that
+ // resizes the display. DM sends this transaction in response to a mode change event, so
+ // emit the event now, not when finalizing the mode change as for a refresh rate switch.
+ if (FlagManager::getInstance().synced_resolution_switch() &&
+ !mode.matchesResolution(activeMode)) {
+ mScheduler->onDisplayModeChanged(displayId, mode,
+ /*clearContentRequirements*/ true);
+ }
break;
}
case DesiredModeAction::InitiateRenderRateSwitch:
@@ -1347,7 +1399,8 @@
mScheduler->updatePhaseConfiguration(displayId, mode.fps);
if (emitEvent) {
- mScheduler->onDisplayModeChanged(displayId, mode);
+ mScheduler->onDisplayModeChanged(displayId, mode,
+ /*clearContentRequirements*/ false);
}
break;
case DesiredModeAction::None:
@@ -1406,34 +1459,36 @@
return future.get();
}
-// TODO: b/241285876 - Restore thread safety analysis once mStateLock below is unconditional.
-[[clang::no_thread_safety_analysis]]
-void SurfaceFlinger::finalizeDisplayModeChange(PhysicalDisplayId displayId) {
+bool SurfaceFlinger::finalizeDisplayModeChange(PhysicalDisplayId displayId) {
SFTRACE_NAME(ftl::Concat(__func__, ' ', displayId.value).c_str());
const auto pendingModeOpt = mDisplayModeController.getPendingMode(displayId);
if (!pendingModeOpt) {
// There is no pending mode change. This can happen if the active
// display changed and the mode change happened on a different display.
- return;
+ return true;
}
const auto& activeMode = pendingModeOpt->mode;
+ const bool resolutionMatch = !FlagManager::getInstance().synced_resolution_switch() ||
+ activeMode.matchesResolution(mDisplayModeController.getActiveMode(displayId));
- if (const auto oldResolution =
- mDisplayModeController.getActiveMode(displayId).modePtr->getResolution();
- oldResolution != activeMode.modePtr->getResolution()) {
- ConditionalLock lock(mStateLock, !FlagManager::getInstance().connected_display());
+ if (!FlagManager::getInstance().synced_resolution_switch()) {
+ if (const auto oldResolution =
+ mDisplayModeController.getActiveMode(displayId).modePtr->getResolution();
+ oldResolution != activeMode.modePtr->getResolution()) {
+ auto& state =
+ mCurrentState.displays.editValueFor(getPhysicalDisplayTokenLocked(displayId));
+ // We need to generate new sequenceId in order to recreate the display (and this
+ // way the framebuffer).
+ state.sequenceId = DisplayDeviceState{}.sequenceId;
+ state.physical->activeMode = activeMode.modePtr.get();
+ processDisplayChangesLocked();
- auto& state = mCurrentState.displays.editValueFor(getPhysicalDisplayTokenLocked(displayId));
- // We need to generate new sequenceId in order to recreate the display (and this
- // way the framebuffer).
- state.sequenceId = DisplayDeviceState{}.sequenceId;
- state.physical->activeMode = activeMode.modePtr.get();
- processDisplayChangesLocked();
-
- // processDisplayChangesLocked will update all necessary components so we're done here.
- return;
+ // The DisplayDevice has been destroyed, so abort the commit for the now dead
+ // FrameTargeter.
+ return false;
+ }
}
mDisplayModeController.finalizeModeChange(displayId, activeMode.modePtr->getId(),
@@ -1441,9 +1496,12 @@
mScheduler->updatePhaseConfiguration(displayId, activeMode.fps);
- if (pendingModeOpt->emitEvent) {
- mScheduler->onDisplayModeChanged(displayId, activeMode);
+ // Skip for resolution changes, since the event was already emitted on setting the desired mode.
+ if (resolutionMatch && pendingModeOpt->emitEvent) {
+ mScheduler->onDisplayModeChanged(displayId, activeMode, /*clearContentRequirements*/ true);
}
+
+ return true;
}
void SurfaceFlinger::dropModeRequest(PhysicalDisplayId displayId) {
@@ -1491,8 +1549,9 @@
to_string(displayModePtrOpt->get()->getVsyncRate()).c_str(),
to_string(displayId).c_str());
- if ((!FlagManager::getInstance().connected_display() || !desiredModeOpt->force) &&
- mDisplayModeController.getActiveMode(displayId) == desiredModeOpt->mode) {
+ const auto activeMode = mDisplayModeController.getActiveMode(displayId);
+
+ if (!desiredModeOpt->force && desiredModeOpt->mode == activeMode) {
applyActiveMode(displayId);
continue;
}
@@ -1513,8 +1572,24 @@
constraints.seamlessRequired = false;
hal::VsyncPeriodChangeTimeline outTimeline;
- if (!mDisplayModeController.initiateModeChange(displayId, std::move(*desiredModeOpt),
- constraints, outTimeline)) {
+ // When initiating a resolution change, wait until the commit that resizes the display.
+ if (FlagManager::getInstance().synced_resolution_switch() &&
+ !activeMode.matchesResolution(desiredModeOpt->mode)) {
+ const auto display = getDisplayDeviceLocked(displayId);
+ if (display->getSize() != desiredModeOpt->mode.modePtr->getResolution()) {
+ continue;
+ }
+ }
+
+ const auto error =
+ mDisplayModeController.initiateModeChange(displayId, std::move(*desiredModeOpt),
+ constraints, outTimeline);
+ if (error != display::DisplayModeController::ModeChangeResult::Changed) {
+ dropModeRequest(displayId);
+ if (FlagManager::getInstance().display_config_error_hal() &&
+ error == display::DisplayModeController::ModeChangeResult::Rejected) {
+ mScheduler->onDisplayModeRejected(displayId, desiredModeId);
+ }
continue;
}
@@ -1655,19 +1730,22 @@
outProperties->combinations.emplace_back(outCombination);
}
outProperties->supportMixedColorSpaces = aidlProperties.supportMixedColorSpaces;
- if (aidlProperties.lutProperties.has_value()) {
+ if (aidlProperties.lutProperties) {
std::vector<gui::LutProperties> outLutProperties;
- for (const auto& properties : aidlProperties.lutProperties.value()) {
- gui::LutProperties currentProperties;
- currentProperties.dimension =
- static_cast<gui::LutProperties::Dimension>(properties->dimension);
- currentProperties.size = properties->size;
- currentProperties.samplingKeys.reserve(properties->samplingKeys.size());
- std::transform(properties->samplingKeys.cbegin(), properties->samplingKeys.cend(),
- std::back_inserter(currentProperties.samplingKeys), [](const auto& val) {
- return static_cast<gui::LutProperties::SamplingKey>(val);
- });
- outLutProperties.push_back(std::move(currentProperties));
+ for (auto properties : *aidlProperties.lutProperties) {
+ if (!properties) {
+ gui::LutProperties currentProperties;
+ currentProperties.dimension =
+ static_cast<gui::LutProperties::Dimension>(properties->dimension);
+ currentProperties.size = properties->size;
+ currentProperties.samplingKeys.reserve(properties->samplingKeys.size());
+ std::transform(properties->samplingKeys.cbegin(), properties->samplingKeys.cend(),
+ std::back_inserter(currentProperties.samplingKeys),
+ [](const auto& val) {
+ return static_cast<gui::LutProperties::SamplingKey>(val);
+ });
+ outLutProperties.push_back(std::move(currentProperties));
+ }
}
outProperties->lutProperties.emplace(outLutProperties.begin(), outLutProperties.end());
}
@@ -1825,6 +1903,24 @@
}));
}
+status_t SurfaceFlinger::getMaxLayerPictureProfiles(const sp<IBinder>& displayToken,
+ int32_t* outMaxProfiles) {
+ const char* const whence = __func__;
+ auto future = mScheduler->schedule([=, this]() FTL_FAKE_GUARD(mStateLock) {
+ const ssize_t index = mCurrentState.displays.indexOfKey(displayToken);
+ if (index < 0) {
+ ALOGE("%s: Invalid display token %p", whence, displayToken.get());
+ return 0;
+ }
+ const DisplayDeviceState& state = mCurrentState.displays.valueAt(index);
+ return state.maxLayerPictureProfiles > 0 ? state.maxLayerPictureProfiles
+ : state.hasPictureProcessing ? 1
+ : 0;
+ });
+ *outMaxProfiles = future.get();
+ return NO_ERROR;
+}
+
status_t SurfaceFlinger::overrideHdrTypes(const sp<IBinder>& displayToken,
const std::vector<ui::Hdr>& hdrTypes) {
Mutex::Autolock lock(mStateLock);
@@ -2220,12 +2316,12 @@
void SurfaceFlinger::onComposerHalHotplugEvent(hal::HWDisplayId hwcDisplayId,
DisplayHotplugEvent event) {
if (event == DisplayHotplugEvent::CONNECTED || event == DisplayHotplugEvent::DISCONNECTED) {
- hal::Connection connection = (event == DisplayHotplugEvent::CONNECTED)
- ? hal::Connection::CONNECTED
- : hal::Connection::DISCONNECTED;
+ const HWComposer::HotplugEvent hotplugEvent = event == DisplayHotplugEvent::CONNECTED
+ ? HWComposer::HotplugEvent::Connected
+ : HWComposer::HotplugEvent::Disconnected;
{
std::lock_guard<std::mutex> lock(mHotplugMutex);
- mPendingHotplugEvents.push_back(HotplugEvent{hwcDisplayId, connection});
+ mPendingHotplugEvents.push_back(HotplugEvent{hwcDisplayId, hotplugEvent});
}
if (mScheduler) {
@@ -2235,12 +2331,23 @@
return;
}
- if (FlagManager::getInstance().hotplug2()) {
- // TODO(b/311403559): use enum type instead of int
+ if (event < DisplayHotplugEvent::ERROR_LINK_UNSTABLE) {
+ // This needs to be kept in sync with DisplayHotplugEvent to prevent passing new errors.
const auto errorCode = static_cast<int32_t>(event);
- ALOGD("%s: Hotplug error %d for hwcDisplayId %" PRIu64, __func__, errorCode, hwcDisplayId);
- mScheduler->dispatchHotplugError(errorCode);
+ ALOGW("%s: Unknown hotplug error %d for hwcDisplayId %" PRIu64, __func__, errorCode,
+ hwcDisplayId);
+ return;
}
+
+ if (event == DisplayHotplugEvent::ERROR_LINK_UNSTABLE &&
+ !FlagManager::getInstance().display_config_error_hal()) {
+ return;
+ }
+
+ // TODO(b/311403559): use enum type instead of int
+ const auto errorCode = static_cast<int32_t>(event);
+ ALOGD("%s: Hotplug error %d for hwcDisplayId %" PRIu64, __func__, errorCode, hwcDisplayId);
+ mScheduler->dispatchHotplugError(errorCode);
}
void SurfaceFlinger::onComposerHalVsyncPeriodTimingChanged(
@@ -2376,9 +2483,11 @@
}
bool SurfaceFlinger::updateLayerSnapshots(VsyncId vsyncId, nsecs_t frameTimeNs,
- bool flushTransactions, bool& outTransactionsAreEmpty) {
+ bool flushTransactions, bool& outTransactionsAreEmpty)
+ EXCLUDES(mStateLock) {
using Changes = frontend::RequestedLayerState::Changes;
SFTRACE_CALL();
+ SFTRACE_NAME_FOR_TRACK(WorkloadTracer::TRACK_NAME, "Transaction Handling");
frontend::Update update;
if (flushTransactions) {
SFTRACE_NAME("TransactionHandler:flushTransactions");
@@ -2405,8 +2514,20 @@
mDestroyedHandles.clear();
}
+ size_t addedLayers = update.newLayers.size();
mLayerLifecycleManager.addLayers(std::move(update.newLayers));
update.transactions = mTransactionHandler.flushTransactions();
+ ftl::Flags<adpf::Workload> committedWorkload;
+ for (auto& transaction : update.transactions) {
+ committedWorkload |= transaction.workloadHint;
+ }
+ SFTRACE_INSTANT_FOR_TRACK(WorkloadTracer::TRACK_NAME,
+ ftl::Concat("Layers: +", addedLayers, " -",
+ update.destroyedHandles.size(),
+ " txns:", update.transactions.size())
+ .c_str());
+
+ mPowerAdvisor->setCommittedWorkload(committedWorkload);
if (mTransactionTracing) {
mTransactionTracing->addCommittedTransactions(ftl::to_underlying(vsyncId), frameTimeNs,
update, mFrontEndDisplayInfos,
@@ -2522,17 +2643,13 @@
frontend::LayerSnapshot* snapshot = mLayerSnapshotBuilder.getSnapshot(it->second->sequence);
gui::GameMode gameMode = (snapshot) ? snapshot->gameMode : gui::GameMode::Unsupported;
mLayersWithQueuedFrames.emplace(it->second, gameMode);
- mLayersIdsWithQueuedFrames.emplace(it->second->sequence);
}
updateLayerHistory(latchTime);
mLayerSnapshotBuilder.forEachSnapshot([&](const frontend::LayerSnapshot& snapshot) {
- // update output dirty region if we have a queued buffer that is visible or a snapshot
- // recently became invisible
- // TODO(b/360050020) investigate if we need to update dirty region when layer color changes
- if ((snapshot.isVisible &&
- (mLayersIdsWithQueuedFrames.find(snapshot.path.id) !=
- mLayersIdsWithQueuedFrames.end())) ||
+ // update output's dirty region if a snapshot is visible and its
+ // content is dirty or if a snapshot recently became invisible
+ if ((snapshot.isVisible && snapshot.contentDirty) ||
(!snapshot.isVisible && snapshot.changes.test(Changes::Visibility))) {
Region visibleReg;
visibleReg.set(snapshot.transformedBoundsWithoutTransparentRegion);
@@ -2545,7 +2662,7 @@
}
{
- SFTRACE_NAME("LLM:commitChanges");
+ SFTRACE_NAME("LayerLifecycleManager:commitChanges");
mLayerLifecycleManager.commitChanges();
}
@@ -2564,7 +2681,7 @@
}
bool SurfaceFlinger::commit(PhysicalDisplayId pacesetterId,
- const scheduler::FrameTargets& frameTargets) {
+ const scheduler::FrameTargets& frameTargets) EXCLUDES(mStateLock) {
const scheduler::FrameTarget& pacesetterFrameTarget = *frameTargets.get(pacesetterId)->get();
const VsyncId vsyncId = pacesetterFrameTarget.vsyncId();
@@ -2586,11 +2703,14 @@
}
{
- ConditionalLock lock(mStateLock, FlagManager::getInstance().connected_display());
+ Mutex::Autolock lock(mStateLock);
for (const auto [displayId, _] : frameTargets) {
if (mDisplayModeController.isModeSetPending(displayId)) {
- finalizeDisplayModeChange(displayId);
+ if (!finalizeDisplayModeChange(displayId)) {
+ mScheduler->scheduleFrame();
+ return false;
+ }
}
}
}
@@ -2608,7 +2728,7 @@
return false;
}
}
-
+ SFTRACE_NAME_FOR_TRACK(WorkloadTracer::TRACK_NAME, "Commit");
const Period vsyncPeriod = mScheduler->getVsyncSchedule()->period();
// Save this once per commit + composite to ensure consistency
@@ -2682,6 +2802,7 @@
// Hold mStateLock as chooseRefreshRateForContent promotes wp<Layer> to sp<Layer>
// and may eventually call to ~Layer() if it holds the last reference
{
+ SFTRACE_NAME_FOR_TRACK(WorkloadTracer::TRACK_NAME, "Refresh Rate Selection");
bool updateAttachedChoreographer = mUpdateAttachedChoreographer;
mUpdateAttachedChoreographer = false;
@@ -2689,13 +2810,6 @@
mScheduler->chooseRefreshRateForContent(&mLayerHierarchyBuilder.getHierarchy(),
updateAttachedChoreographer);
- if (FlagManager::getInstance().connected_display()) {
- initiateDisplayModeChanges();
- }
- }
-
- if (!FlagManager::getInstance().connected_display()) {
- ftl::FakeGuard guard(mStateLock);
initiateDisplayModeChanges();
}
@@ -2715,6 +2829,8 @@
CompositeResultsPerDisplay SurfaceFlinger::composite(
PhysicalDisplayId pacesetterId, const scheduler::FrameTargeters& frameTargeters) {
+ SFTRACE_ASYNC_FOR_TRACK_BEGIN(WorkloadTracer::TRACK_NAME, "Composition",
+ WorkloadTracer::COMPOSITION_TRACE_COOKIE);
const scheduler::FrameTarget& pacesetterTarget =
frameTargeters.get(pacesetterId)->get()->target();
@@ -2726,12 +2842,45 @@
const auto& displays = FTL_FAKE_GUARD(mStateLock, mDisplays);
refreshArgs.outputs.reserve(displays.size());
+ // Track layer stacks of physical displays that might be added to CompositionEngine
+ // output. Layer stacks are not tracked in Display when we iterate through
+ // frameTargeters. Cross-referencing layer stacks allows us to filter out displays
+ // by ID with duplicate layer stacks before adding them to CompositionEngine output.
+ ui::DisplayMap<DisplayId, ui::LayerStack> physicalDisplayLayerStacks;
+ for (auto& [_, display] : displays) {
+ const auto id = PhysicalDisplayId::tryCast(display->getId());
+ if (id && frameTargeters.contains(*id)) {
+ physicalDisplayLayerStacks.try_emplace(*id, display->getLayerStack());
+ }
+ }
+
+ // Tracks layer stacks of displays that are added to CompositionEngine output.
+ ui::DisplayMap<ui::LayerStack, ftl::Unit> outputLayerStacks;
+ auto isUniqueOutputLayerStack = [&outputLayerStacks](DisplayId id, ui::LayerStack layerStack) {
+ if (FlagManager::getInstance().reject_dupe_layerstacks()) {
+ if (layerStack != ui::INVALID_LAYER_STACK && outputLayerStacks.contains(layerStack)) {
+ // TODO: remove log and DisplayId from params once reject_dupe_layerstacks flag is
+ // removed
+ ALOGD("Existing layer stack ID %d output to another display %" PRIu64
+ ", dropping display from outputs",
+ layerStack.id, id.value);
+ return false;
+ }
+ }
+
+ outputLayerStacks.try_emplace(layerStack);
+ return true;
+ };
+
// Add outputs for physical displays.
for (const auto& [id, targeter] : frameTargeters) {
ftl::FakeGuard guard(mStateLock);
if (const auto display = getCompositionDisplayLocked(id)) {
- refreshArgs.outputs.push_back(display);
+ const auto layerStack = physicalDisplayLayerStacks.get(id)->get();
+ if (isUniqueOutputLayerStack(display->getId(), layerStack)) {
+ refreshArgs.outputs.push_back(display);
+ }
}
refreshArgs.frameTargets.try_emplace(id, &targeter->target());
@@ -2748,7 +2897,9 @@
if (!refreshRate.isValid() ||
mScheduler->isVsyncInPhase(pacesetterTarget.frameBeginTime(), refreshRate)) {
- refreshArgs.outputs.push_back(display->getCompositionDisplay());
+ if (isUniqueOutputLayerStack(display->getId(), display->getLayerStack())) {
+ refreshArgs.outputs.push_back(display->getCompositionDisplay());
+ }
}
}
}
@@ -2758,16 +2909,6 @@
compositionengine::Feature::kSnapshotLayerMetadata);
refreshArgs.bufferIdsToUncache = std::move(mBufferIdsToUncache);
-
- if (!FlagManager::getInstance().ce_fence_promise()) {
- refreshArgs.layersWithQueuedFrames.reserve(mLayersWithQueuedFrames.size());
- for (auto& [layer, _] : mLayersWithQueuedFrames) {
- if (const auto& layerFE = layer->getCompositionEngineLayerFE(
- {static_cast<uint32_t>(layer->sequence)}))
- refreshArgs.layersWithQueuedFrames.push_back(layerFE);
- }
- }
-
refreshArgs.outputColorSetting = mDisplayColorSetting;
refreshArgs.forceOutputColorMode = mForceColorMode;
@@ -2831,54 +2972,114 @@
layer->onPreComposition(refreshArgs.refreshStartTime);
}
- if (FlagManager::getInstance().ce_fence_promise()) {
- for (auto& [layer, layerFE] : layers) {
- attachReleaseFenceFutureToLayer(layer, layerFE,
- layerFE->mSnapshot->outputFilter.layerStack);
- }
+ for (auto& [layer, layerFE] : layers) {
+ attachReleaseFenceFutureToLayer(layer, layerFE,
+ layerFE->mSnapshot->outputFilter.layerStack);
+ }
- refreshArgs.layersWithQueuedFrames.reserve(mLayersWithQueuedFrames.size());
- for (auto& [layer, _] : mLayersWithQueuedFrames) {
- if (const auto& layerFE = layer->getCompositionEngineLayerFE(
- {static_cast<uint32_t>(layer->sequence)})) {
- refreshArgs.layersWithQueuedFrames.push_back(layerFE);
- // Some layers are not displayed and do not yet have a future release fence
- if (layerFE->getReleaseFencePromiseStatus() ==
- LayerFE::ReleaseFencePromiseStatus::UNINITIALIZED ||
- layerFE->getReleaseFencePromiseStatus() ==
- LayerFE::ReleaseFencePromiseStatus::FULFILLED) {
- // layerStack is invalid because layer is not on a display
- attachReleaseFenceFutureToLayer(layer.get(), layerFE.get(),
- ui::INVALID_LAYER_STACK);
- }
- }
- }
-
- mCompositionEngine->present(refreshArgs);
- moveSnapshotsFromCompositionArgs(refreshArgs, layers);
-
- for (auto& [layer, layerFE] : layers) {
- CompositionResult compositionResult{layerFE->stealCompositionResult()};
- if (compositionResult.lastClientCompositionFence) {
- layer->setWasClientComposed(compositionResult.lastClientCompositionFence);
- }
- }
-
- } else {
- mCompositionEngine->present(refreshArgs);
- moveSnapshotsFromCompositionArgs(refreshArgs, layers);
-
- for (auto [layer, layerFE] : layers) {
- CompositionResult compositionResult{layerFE->stealCompositionResult()};
- for (auto& [releaseFence, layerStack] : compositionResult.releaseFences) {
- layer->onLayerDisplayed(std::move(releaseFence), layerStack);
- }
- if (compositionResult.lastClientCompositionFence) {
- layer->setWasClientComposed(compositionResult.lastClientCompositionFence);
+ refreshArgs.layersWithQueuedFrames.reserve(mLayersWithQueuedFrames.size());
+ for (auto& [layer, _] : mLayersWithQueuedFrames) {
+ if (const auto& layerFE =
+ layer->getCompositionEngineLayerFE({static_cast<uint32_t>(layer->sequence)})) {
+ refreshArgs.layersWithQueuedFrames.push_back(layerFE);
+ // Some layers are not displayed and do not yet have a future release fence
+ if (layerFE->getReleaseFencePromiseStatus() ==
+ LayerFE::ReleaseFencePromiseStatus::UNINITIALIZED ||
+ layerFE->getReleaseFencePromiseStatus() ==
+ LayerFE::ReleaseFencePromiseStatus::FULFILLED) {
+ // layerStack is invalid because layer is not on a display
+ attachReleaseFenceFutureToLayer(layer.get(), layerFE.get(),
+ ui::INVALID_LAYER_STACK);
}
}
}
+ mCompositionEngine->present(refreshArgs);
+ ftl::Flags<adpf::Workload> compositedWorkload;
+ if (refreshArgs.updatingGeometryThisFrame || refreshArgs.updatingOutputGeometryThisFrame) {
+ compositedWorkload |= adpf::Workload::VISIBLE_REGION;
+ }
+ if (mFrontEndDisplayInfosChanged) {
+ compositedWorkload |= adpf::Workload::DISPLAY_CHANGES;
+ SFTRACE_INSTANT_FOR_TRACK(WorkloadTracer::TRACK_NAME, "Display Changes");
+ }
+
+ int index = 0;
+ ftl::StaticVector<char, WorkloadTracer::COMPOSITION_SUMMARY_SIZE> compositionSummary;
+ auto lastLayerStack = ui::INVALID_LAYER_STACK;
+
+ uint64_t prevOverrideBufferId = 0;
+ for (auto& [layer, layerFE] : layers) {
+ CompositionResult compositionResult{layerFE->stealCompositionResult()};
+ if (lastLayerStack != layerFE->mSnapshot->outputFilter.layerStack) {
+ if (lastLayerStack != ui::INVALID_LAYER_STACK) {
+ // add a space to separate displays
+ compositionSummary.push_back(' ');
+ }
+ lastLayerStack = layerFE->mSnapshot->outputFilter.layerStack;
+ }
+
+ // If there are N layers in a cached set they should all share the same buffer id.
+ // The first layer in the cached set will be not skipped and layers 1..N-1 will be skipped.
+ // We expect all layers in the cached set to be marked as composited by HWC.
+ // Here is a made up example of how it is visualized
+ //
+ // [b:rrc][s:cc]
+ //
+ // This should be interpreted to mean that there are 2 cached sets.
+ // So there are only 2 non skipped layers -- b and s.
+ // The layers rrc and cc are flattened into layers b and s respectively.
+ const LayerFE::HwcLayerDebugState &hwcState = layerFE->getLastHwcState();
+ if (hwcState.overrideBufferId != prevOverrideBufferId) {
+ // End the existing run.
+ if (prevOverrideBufferId) {
+ compositionSummary.push_back(']');
+ }
+ // Start a new run.
+ if (hwcState.overrideBufferId) {
+ compositionSummary.push_back('[');
+ }
+ }
+
+ compositionSummary.push_back(
+ layerFE->mSnapshot->classifyCompositionForDebug(hwcState));
+
+ if (hwcState.overrideBufferId && !hwcState.wasSkipped) {
+ compositionSummary.push_back(':');
+ }
+ prevOverrideBufferId = hwcState.overrideBufferId;
+
+ if (layerFE->mSnapshot->hasEffect()) {
+ compositedWorkload |= adpf::Workload::EFFECTS;
+ }
+
+ if (compositionResult.lastClientCompositionFence) {
+ layer->setWasClientComposed(compositionResult.lastClientCompositionFence);
+ }
+ if (com_android_graphics_libgui_flags_apply_picture_profiles()) {
+ mActivePictureTracker.onLayerComposed(*layer, *layerFE, compositionResult);
+ }
+ }
+ // End the last run.
+ if (prevOverrideBufferId) {
+ compositionSummary.push_back(']');
+ }
+
+ // Concisely describe the layers composited this frame using single chars. GPU composited layers
+ // are uppercase, DPU composited are lowercase. Special chars denote effects (blur, shadow,
+ // etc.). This provides a snapshot of the compositing workload.
+ SFTRACE_INSTANT_FOR_TRACK(WorkloadTracer::TRACK_NAME,
+ ftl::Concat("Layers: ", layers.size(), " ",
+ ftl::truncated<WorkloadTracer::COMPOSITION_SUMMARY_SIZE>(
+ std::string_view(compositionSummary.begin(),
+ compositionSummary.size())))
+ .c_str());
+
+ mPowerAdvisor->setCompositedWorkload(compositedWorkload);
+ moveSnapshotsFromCompositionArgs(refreshArgs, layers);
+ SFTRACE_ASYNC_FOR_TRACK_END(WorkloadTracer::TRACK_NAME,
+ WorkloadTracer::COMPOSITION_TRACE_COOKIE);
+ SFTRACE_NAME_FOR_TRACK(WorkloadTracer::TRACK_NAME, "Post Composition");
SFTRACE_NAME("postComposition");
mTimeStats->recordFrameDuration(pacesetterTarget.frameBeginTime().ns(), systemTime());
@@ -2948,7 +3149,6 @@
mScheduler->modulateVsync({}, &VsyncModulator::onDisplayRefresh, hasGpuUseOrReuse);
mLayersWithQueuedFrames.clear();
- mLayersIdsWithQueuedFrames.clear();
doActiveLayersTracingIfNeeded(true, mVisibleRegionsDirty, pacesetterTarget.frameBeginTime(),
vsyncId);
@@ -3088,12 +3288,40 @@
const TimePoint presentTime = TimePoint::now();
+ // The Uids of layer owners that are in buffer stuffing mode, and their elevated
+ // buffer counts. Messages to start recovery are sent exclusively to these Uids.
+ BufferStuffingMap bufferStuffedUids;
+
// Set presentation information before calling Layer::releasePendingBuffer, such that jank
// information from previous' frame classification is already available when sending jank info
// to clients, so they get jank classification as early as possible.
mFrameTimeline->setSfPresent(presentTime.ns(), pacesetterPresentFenceTime,
pacesetterGpuCompositionDoneFenceTime);
+ // Find and register any layers that are in buffer stuffing mode
+ const auto& presentFrames = mFrameTimeline->getPresentFrames();
+
+ for (const auto& frame : presentFrames) {
+ const auto& layer = mLayerLifecycleManager.getLayerFromId(frame->getLayerId());
+ if (!layer) continue;
+ uint32_t numberQueuedBuffers = layer->pendingBuffers ? layer->pendingBuffers->load() : 0;
+ int32_t jankType = frame->getJankType().value_or(JankType::None);
+ if (jankType & JankType::BufferStuffing &&
+ layer->flags & layer_state_t::eRecoverableFromBufferStuffing) {
+ auto [it, wasEmplaced] =
+ bufferStuffedUids.try_emplace(layer->ownerUid.val(), numberQueuedBuffers);
+ // Update with maximum number of queued buffers, allows clients drawing
+ // multiple windows to account for the most severely stuffed window
+ if (!wasEmplaced && it->second < numberQueuedBuffers) {
+ it->second = numberQueuedBuffers;
+ }
+ }
+ }
+
+ if (!bufferStuffedUids.empty()) {
+ mScheduler->addBufferStuffedUids(std::move(bufferStuffedUids));
+ }
+
// We use the CompositionEngine::getLastFrameRefreshTimestamp() which might
// be sampled a little later than when we started doing work for this frame,
// but that should be okay since CompositorTiming has snapping logic.
@@ -3105,12 +3333,12 @@
const auto schedule = mScheduler->getVsyncSchedule();
const TimePoint vsyncDeadline = schedule->vsyncDeadlineAfter(presentTime);
- const Period vsyncPeriod = schedule->period();
+ const Fps renderRate = pacesetterDisplay->refreshRateSelector().getActiveMode().fps;
const nsecs_t vsyncPhase =
mScheduler->getVsyncConfiguration().getCurrentConfigs().late.sfOffset;
- const CompositorTiming compositorTiming(vsyncDeadline.ns(), vsyncPeriod.ns(), vsyncPhase,
- presentLatency.ns());
+ const CompositorTiming compositorTiming(vsyncDeadline.ns(), renderRate.getPeriodNsecs(),
+ vsyncPhase, presentLatency.ns());
ui::DisplayMap<ui::LayerStack, const DisplayDevice*> layerStackToDisplay;
{
@@ -3130,13 +3358,8 @@
auto optDisplay = layerStackToDisplay.get(layerStack);
if (optDisplay && !optDisplay->get()->isVirtual()) {
auto fence = getHwComposer().getPresentFence(optDisplay->get()->getPhysicalId());
- if (FlagManager::getInstance().ce_fence_promise()) {
- layer->prepareReleaseCallbacks(ftl::yield<FenceResult>(fence),
- ui::INVALID_LAYER_STACK);
- } else {
- layer->onLayerDisplayed(ftl::yield<FenceResult>(fence).share(),
- ui::INVALID_LAYER_STACK);
- }
+ layer->prepareReleaseCallbacks(ftl::yield<FenceResult>(fence),
+ ui::INVALID_LAYER_STACK);
}
}
layer->releasePendingBuffer(presentTime.ns());
@@ -3150,9 +3373,23 @@
layer->releasePendingBuffer(presentTime.ns());
}
+ for (const auto& layerEvent : mLayerEvents) {
+ auto result =
+ stats::stats_write(stats::SURFACE_CONTROL_EVENT,
+ static_cast<int32_t>(layerEvent.uid),
+ static_cast<int64_t>(layerEvent.timeSinceLastEvent.count()),
+ static_cast<int32_t>(layerEvent.dataspace));
+ if (result < 0) {
+ ALOGW("Failed to report layer event with error: %d", result);
+ }
+ }
+ mLayerEvents.clear();
+
std::vector<std::pair<std::shared_ptr<compositionengine::Display>, sp<HdrLayerInfoReporter>>>
hdrInfoListeners;
- bool haveNewListeners = false;
+ bool haveNewHdrInfoListeners = false;
+ ActivePictureTracker::Listeners activePictureListenersToAdd;
+ ActivePictureTracker::Listeners activePictureListenersToRemove;
{
Mutex::Autolock lock(mStateLock);
if (mFpsReporter) {
@@ -3162,6 +3399,7 @@
if (mTunnelModeEnabledReporter) {
mTunnelModeEnabledReporter->updateTunnelModeStatus();
}
+
hdrInfoListeners.reserve(mHdrLayerInfoListeners.size());
for (const auto& [displayId, reporter] : mHdrLayerInfoListeners) {
if (reporter && reporter->hasListeners()) {
@@ -3170,11 +3408,14 @@
}
}
}
- haveNewListeners = mAddingHDRLayerInfoListener; // grab this with state lock
+ haveNewHdrInfoListeners = mAddingHDRLayerInfoListener; // grab this with state lock
mAddingHDRLayerInfoListener = false;
+
+ std::swap(activePictureListenersToAdd, mActivePictureListenersToAdd);
+ std::swap(activePictureListenersToRemove, mActivePictureListenersToRemove);
}
- if (haveNewListeners || mHdrLayerInfoChanged) {
+ if (haveNewHdrInfoListeners || mHdrLayerInfoChanged) {
for (auto& [compositionDisplay, listener] : hdrInfoListeners) {
HdrLayerInfoReporter::HdrLayerInfo info;
int32_t maxArea = 0;
@@ -3192,7 +3433,15 @@
snapshot.desiredHdrSdrRatio < 1.f
? std::numeric_limits<float>::infinity()
: snapshot.desiredHdrSdrRatio;
- info.mergeDesiredRatio(desiredHdrSdrRatio);
+
+ float desiredRatio = desiredHdrSdrRatio;
+ if (FlagManager::getInstance().begone_bright_hlg() &&
+ desiredHdrSdrRatio ==
+ std::numeric_limits<float>::infinity()) {
+ desiredRatio = getIdealizedMaxHeadroom(snapshot.dataspace);
+ }
+
+ info.mergeDesiredRatio(desiredRatio);
info.numberOfHdrLayers++;
const auto displayFrame = outputLayer->getState().displayFrame;
const int32_t area =
@@ -3224,9 +3473,15 @@
listener->dispatchHdrLayerInfo(info);
}
}
-
mHdrLayerInfoChanged = false;
+ if (com_android_graphics_libgui_flags_apply_picture_profiles()) {
+ // Track, update and notify changes to active pictures - layers that are undergoing
+ // picture processing
+ mActivePictureTracker.updateAndNotifyListeners(activePictureListenersToAdd,
+ activePictureListenersToRemove);
+ }
+
mTransactionCallbackInvoker.sendCallbacks(false /* onCommitOnly */);
mTransactionCallbackInvoker.clearCompletedTransactions();
@@ -3234,13 +3489,7 @@
mTimeStats->setPresentFenceGlobal(pacesetterPresentFenceTime);
for (auto&& [id, presentFence] : presentFences) {
- ftl::FakeGuard guard(mStateLock);
- const bool isInternalDisplay =
- mPhysicalDisplays.get(id).transform(&PhysicalDisplay::isInternal).value_or(false);
-
- if (isInternalDisplay) {
- mScheduler->addPresentFence(id, std::move(presentFence));
- }
+ mScheduler->addPresentFence(id, std::move(presentFence));
}
const bool hasPacesetterDisplay =
@@ -3421,6 +3670,9 @@
DisplayModes newModes;
for (const auto& hwcMode : hwcModes) {
const auto id = nextModeId++;
+ OutputType hdrOutputType = FlagManager::getInstance().connected_display_hdr()
+ ? hwcMode.hdrOutputType
+ : OutputType::INVALID;
newModes.try_emplace(id,
DisplayMode::Builder(hwcMode.hwcId)
.setId(id)
@@ -3431,6 +3683,7 @@
.setDpiX(hwcMode.dpiX)
.setDpiY(hwcMode.dpiY)
.setGroup(hwcMode.configGroup)
+ .setHdrOutputType(hdrOutputType)
.build());
}
@@ -3461,21 +3714,19 @@
events = std::move(mPendingHotplugEvents);
}
- for (const auto [hwcDisplayId, connection] : events) {
- if (auto info = getHwComposer().onHotplug(hwcDisplayId, connection)) {
+ for (const auto [hwcDisplayId, event] : events) {
+ if (auto info = getHwComposer().onHotplug(hwcDisplayId, event)) {
const auto displayId = info->id;
const ftl::Concat displayString("display ", displayId.value, "(HAL ID ", hwcDisplayId,
')');
- if (connection == hal::Connection::CONNECTED) {
+ if (event == HWComposer::HotplugEvent::Connected) {
const auto activeModeIdOpt =
processHotplugConnect(displayId, hwcDisplayId, std::move(*info),
displayString.c_str());
if (!activeModeIdOpt) {
- if (FlagManager::getInstance().hotplug2()) {
- mScheduler->dispatchHotplugError(
- static_cast<int32_t>(DisplayHotplugEvent::ERROR_UNKNOWN));
- }
+ mScheduler->dispatchHotplugError(
+ static_cast<int32_t>(DisplayHotplugEvent::ERROR_UNKNOWN));
getHwComposer().disconnectDisplay(displayId);
continue;
}
@@ -3526,6 +3777,7 @@
if (const auto displayOpt = mPhysicalDisplays.get(displayId)) {
const auto& display = displayOpt->get();
const auto& snapshot = display.snapshot();
+ const uint8_t port = snapshot.port();
std::optional<DeviceProductInfo> deviceProductInfo;
if (getHwComposer().updatesDeviceProductInfoOnHotplugReconnect()) {
@@ -3534,14 +3786,17 @@
deviceProductInfo = snapshot.deviceProductInfo();
}
+ // Use the cached port via snapshot because we are updating an existing
+ // display on reconnect.
const auto it =
- mPhysicalDisplays.try_replace(displayId, display.token(), displayId,
+ mPhysicalDisplays.try_replace(displayId, display.token(), displayId, port,
snapshot.connectionType(), std::move(displayModes),
std::move(colorModes), std::move(deviceProductInfo));
auto& state = mCurrentState.displays.editValueFor(it->second.token());
state.sequenceId = DisplayDeviceState{}.sequenceId; // Generate new sequenceId.
state.physical->activeMode = std::move(activeMode);
+ state.physical->port = port;
ALOGI("Reconnecting %s", displayString);
return activeModeId;
}
@@ -3550,13 +3805,14 @@
const ui::DisplayConnectionType connectionType =
getHwComposer().getDisplayConnectionType(displayId);
- mPhysicalDisplays.try_emplace(displayId, token, displayId, connectionType,
+ mPhysicalDisplays.try_emplace(displayId, token, displayId, info.port, connectionType,
std::move(displayModes), std::move(colorModes),
std::move(info.deviceProductInfo));
DisplayDeviceState state;
state.physical = {.id = displayId,
.hwcDisplayId = hwcDisplayId,
+ .port = info.port,
.activeMode = std::move(activeMode)};
if (mIsHdcpViaNegVsync) {
state.isSecure = connectionType == ui::DisplayConnectionType::Internal;
@@ -3566,7 +3822,9 @@
}
state.isProtected = true;
state.displayName = std::move(info.name);
-
+ state.maxLayerPictureProfiles = getHwComposer().getMaxLayerPictureProfiles(displayId);
+ state.hasPictureProcessing =
+ getHwComposer().hasDisplayCapability(displayId, DisplayCapability::PICTURE_PROCESSING);
mCurrentState.displays.add(token, state);
ALOGI("Connecting %s", displayString);
return activeModeId;
@@ -3674,6 +3932,26 @@
return display;
}
+void SurfaceFlinger::incRefreshableDisplays() {
+ if (FlagManager::getInstance().no_vsyncs_on_screen_off()) {
+ mRefreshableDisplays++;
+ if (mRefreshableDisplays == 1) {
+ ftl::FakeGuard guard(kMainThreadContext);
+ mScheduler->omitVsyncDispatching(false);
+ }
+ }
+}
+
+void SurfaceFlinger::decRefreshableDisplays() {
+ if (FlagManager::getInstance().no_vsyncs_on_screen_off()) {
+ mRefreshableDisplays--;
+ if (mRefreshableDisplays == 0) {
+ ftl::FakeGuard guard(kMainThreadContext);
+ mScheduler->omitVsyncDispatching(true);
+ }
+ }
+}
+
void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
const DisplayDeviceState& state) {
ui::Size resolution(0, 0);
@@ -3701,12 +3979,14 @@
if (const auto& physical = state.physical) {
builder.setId(physical->id);
} else {
- builder.setId(acquireVirtualDisplay(resolution, pixelFormat));
+ builder.setId(acquireVirtualDisplay(resolution, pixelFormat, state.uniqueId));
}
builder.setPixels(resolution);
builder.setIsSecure(state.isSecure);
builder.setIsProtected(state.isProtected);
+ builder.setHasPictureProcessing(state.hasPictureProcessing);
+ builder.setMaxLayerPictureProfiles(state.maxLayerPictureProfiles);
builder.setPowerAdvisor(mPowerAdvisor.get());
builder.setName(state.displayName);
auto compositionDisplay = getCompositionEngine().createDisplay(builder.build());
@@ -3753,9 +4033,6 @@
displaySurface, producer);
if (mScheduler && !display->isVirtual()) {
- // TODO(b/241285876): Annotate `processDisplayAdded` instead.
- ftl::FakeGuard guard(kMainThreadContext);
-
// For hotplug reconnect, renew the registration since display modes have been reloaded.
mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector(),
mActiveDisplayId);
@@ -3765,6 +4042,10 @@
display->adjustRefreshRate(mScheduler->getPacesetterRefreshRate());
}
+ if (display->isRefreshable()) {
+ incRefreshableDisplays();
+ }
+
mDisplays.try_emplace(displayToken, std::move(display));
// For an external display, loadDisplayModes already attempted to select the same mode
@@ -3799,6 +4080,10 @@
} else {
mScheduler->unregisterDisplay(display->getPhysicalId(), mActiveDisplayId);
}
+
+ if (display->isRefreshable()) {
+ decRefreshableDisplays();
+ }
}
mDisplays.erase(displayToken);
@@ -3833,13 +4118,17 @@
if (display->isVirtual()) {
releaseVirtualDisplay(display->getVirtualId());
}
+
+ if (display->isRefreshable()) {
+ decRefreshableDisplays();
+ }
}
mDisplays.erase(displayToken);
if (const auto& physical = currentState.physical) {
getHwComposer().allocatePhysicalDisplay(physical->hwcDisplayId, physical->id,
- /*physicalSize=*/std::nullopt);
+ physical->port, /*physicalSize=*/std::nullopt);
}
processDisplayAdded(displayToken, currentState);
@@ -3865,6 +4154,35 @@
if (currentState.flags != drawingState.flags) {
display->setFlags(currentState.flags);
}
+
+ const auto updateDisplaySize = [&]() {
+ if (currentState.width != drawingState.width ||
+ currentState.height != drawingState.height) {
+ const ui::Size resolution = ui::Size(currentState.width, currentState.height);
+
+ // Resize the framebuffer. For a virtual display, always do so. For a physical
+ // display, only do so if it has a pending modeset for the matching resolution.
+ if (!currentState.physical ||
+ (FlagManager::getInstance().synced_resolution_switch() &&
+ mDisplayModeController.getDesiredMode(display->getPhysicalId())
+ .transform([resolution](const auto& request) {
+ return resolution == request.mode.modePtr->getResolution();
+ })
+ .value_or(false))) {
+ display->setDisplaySize(resolution);
+ }
+
+ if (display->getId() == mActiveDisplayId) {
+ onActiveDisplaySizeChanged(*display);
+ }
+ }
+ };
+
+ if (FlagManager::getInstance().synced_resolution_switch()) {
+ // Update display size first, as display projection below depends on it.
+ updateDisplaySize();
+ }
+
if ((currentState.orientation != drawingState.orientation) ||
(currentState.layerStackSpaceRect != drawingState.layerStackSpaceRect) ||
(currentState.orientedDisplaySpaceRect != drawingState.orientedDisplaySpaceRect)) {
@@ -3876,13 +4194,9 @@
ui::Transform::toRotationFlags(display->getOrientation());
}
}
- if (currentState.width != drawingState.width ||
- currentState.height != drawingState.height) {
- display->setDisplaySize(currentState.width, currentState.height);
- if (display->getId() == mActiveDisplayId) {
- onActiveDisplaySizeChanged(*display);
- }
+ if (!FlagManager::getInstance().synced_resolution_switch()) {
+ updateDisplaySize();
}
}
}
@@ -3997,7 +4311,8 @@
inputWindowCommands =
std::move(mInputWindowCommands),
inputFlinger = mInputFlinger, this,
- visibleWindowsChanged, vsyncId, frameTime]() {
+ visibleWindowsChanged, vsyncId,
+ frameTime]() mutable {
SFTRACE_NAME("BackgroundExecutor::updateInputFlinger");
if (updateWindowInfo) {
mWindowInfosListenerInvoker
@@ -4276,7 +4591,7 @@
scheduleNotifyExpectedPresentHint(displayId);
}
-void SurfaceFlinger::onCommitNotComposited(PhysicalDisplayId pacesetterDisplayId) {
+void SurfaceFlinger::onCommitNotComposited() {
if (FlagManager::getInstance().commit_not_composited()) {
mFrameTimeline->onCommitNotComposited();
}
@@ -4373,27 +4688,6 @@
status_t SurfaceFlinger::addClientLayer(LayerCreationArgs& args, const sp<IBinder>& handle,
const sp<Layer>& layer, const wp<Layer>& parent,
uint32_t* outTransformHint) {
- if (mNumLayers >= MAX_LAYERS) {
- static std::atomic<nsecs_t> lasttime{0};
- nsecs_t now = systemTime();
- if (lasttime != 0 && ns2s(now - lasttime.load()) < 10) {
- ALOGE("AddClientLayer already dumped 10s before");
- return NO_MEMORY;
- } else {
- lasttime = now;
- }
-
- ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(),
- MAX_LAYERS);
- static_cast<void>(mScheduler->schedule([&]() FTL_FAKE_GUARD(kMainThreadContext) {
- ALOGE("Dumping on-screen layers.");
- mLayerHierarchyBuilder.dumpLayerSample(mLayerHierarchyBuilder.getHierarchy());
- ALOGE("Dumping off-screen layers.");
- mLayerHierarchyBuilder.dumpLayerSample(mLayerHierarchyBuilder.getOffscreenHierarchy());
- }));
- return NO_MEMORY;
- }
-
if (outTransformHint) {
*outTransformHint = mActiveDisplayTransformHint;
}
@@ -4598,16 +4892,18 @@
// For tests only
bool SurfaceFlinger::flushTransactionQueues() {
mTransactionHandler.collectTransactions();
- std::vector<TransactionState> transactions = mTransactionHandler.flushTransactions();
+ std::vector<QueuedTransactionState> transactions = mTransactionHandler.flushTransactions();
return applyTransactions(transactions);
}
-bool SurfaceFlinger::applyTransactions(std::vector<TransactionState>& transactions) {
+bool SurfaceFlinger::applyTransactions(std::vector<QueuedTransactionState>& transactions)
+ EXCLUDES(mStateLock) {
Mutex::Autolock lock(mStateLock);
return applyTransactionsLocked(transactions);
}
-bool SurfaceFlinger::applyTransactionsLocked(std::vector<TransactionState>& transactions) {
+bool SurfaceFlinger::applyTransactionsLocked(std::vector<QueuedTransactionState>& transactions)
+ REQUIRES(mStateLock) {
bool needsTraversal = false;
// Now apply all transactions.
for (auto& transaction : transactions) {
@@ -4697,8 +4993,15 @@
const int originPid = ipc->getCallingPid();
const int originUid = ipc->getCallingUid();
uint32_t permissions = LayerStatePermissions::getTransactionPermissions(originPid, originUid);
+ ftl::Flags<adpf::Workload> queuedWorkload;
for (auto& composerState : states) {
composerState.state.sanitize(permissions);
+ if (composerState.state.what & layer_state_t::COMPOSITION_EFFECTS) {
+ queuedWorkload |= adpf::Workload::EFFECTS;
+ }
+ if (composerState.state.what & layer_state_t::VISIBLE_REGION_CHANGES) {
+ queuedWorkload |= adpf::Workload::VISIBLE_REGION;
+ }
}
for (DisplayState& display : displays) {
@@ -4721,6 +5024,10 @@
flags &= ~(eEarlyWakeupStart | eEarlyWakeupEnd);
}
}
+ if (flags & eEarlyWakeupStart) {
+ queuedWorkload |= adpf::Workload::WAKEUP;
+ }
+ mPowerAdvisor->setQueuedWorkload(queuedWorkload);
const int64_t postTime = systemTime();
@@ -4768,22 +5075,23 @@
}
}
- TransactionState state{frameTimelineInfo,
- resolvedStates,
- displays,
- flags,
- applyToken,
- std::move(inputWindowCommands),
- desiredPresentTime,
- isAutoTimestamp,
- std::move(uncacheBufferIds),
- postTime,
- hasListenerCallbacks,
- listenerCallbacks,
- originPid,
- originUid,
- transactionId,
- mergedTransactionIds};
+ QueuedTransactionState state{frameTimelineInfo,
+ resolvedStates,
+ displays,
+ flags,
+ applyToken,
+ std::move(inputWindowCommands),
+ desiredPresentTime,
+ isAutoTimestamp,
+ std::move(uncacheBufferIds),
+ postTime,
+ hasListenerCallbacks,
+ listenerCallbacks,
+ originPid,
+ originUid,
+ transactionId,
+ mergedTransactionIds};
+ state.workloadHint = queuedWorkload;
if (mTransactionTracing) {
mTransactionTracing->addQueuedTransaction(state);
@@ -4812,15 +5120,13 @@
return NO_ERROR;
}
-bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelineInfo,
- std::vector<ResolvedComposerState>& states,
- Vector<DisplayState>& displays, uint32_t flags,
- const InputWindowCommands& inputWindowCommands,
- const int64_t desiredPresentTime, bool isAutoTimestamp,
- const std::vector<uint64_t>& uncacheBufferIds,
- const int64_t postTime, bool hasListenerCallbacks,
- const std::vector<ListenerCallbacks>& listenerCallbacks,
- int originPid, int originUid, uint64_t transactionId) {
+bool SurfaceFlinger::applyTransactionState(
+ const FrameTimelineInfo& frameTimelineInfo, std::vector<ResolvedComposerState>& states,
+ Vector<DisplayState>& displays, uint32_t flags,
+ const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime,
+ bool isAutoTimestamp, const std::vector<uint64_t>& uncacheBufferIds, const int64_t postTime,
+ bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks,
+ int originPid, int originUid, uint64_t transactionId) REQUIRES(mStateLock) {
uint32_t transactionFlags = 0;
// start and end registration for listeners w/ no surface so they can get their callback. Note
@@ -4868,7 +5174,7 @@
}
bool SurfaceFlinger::applyAndCommitDisplayTransactionStatesLocked(
- std::vector<TransactionState>& transactions) {
+ std::vector<QueuedTransactionState>& transactions) {
bool needsTraversal = false;
uint32_t transactionFlags = 0;
for (auto& transaction : transactions) {
@@ -4972,7 +5278,7 @@
ResolvedComposerState& composerState,
int64_t desiredPresentTime,
bool isAutoTimestamp, int64_t postTime,
- uint64_t transactionId) {
+ uint64_t transactionId) REQUIRES(mStateLock) {
layer_state_t& s = composerState.state;
std::vector<ListenerCallbacks> filteredListeners;
@@ -5164,14 +5470,13 @@
mirrorArgs.addToRoot = true;
mirrorArgs.layerStackToMirror = layerStack;
result = createEffectLayer(mirrorArgs, &outResult.handle, &rootMirrorLayer);
+ if (result != NO_ERROR) {
+ return result;
+ }
outResult.layerId = rootMirrorLayer->sequence;
outResult.layerName = String16(rootMirrorLayer->getDebugName());
- result |= addClientLayer(mirrorArgs, outResult.handle, rootMirrorLayer /* layer */,
- nullptr /* parent */, nullptr /* outTransformHint */);
- }
-
- if (result != NO_ERROR) {
- return result;
+ addClientLayer(mirrorArgs, outResult.handle, rootMirrorLayer /* layer */,
+ nullptr /* parent */, nullptr /* outTransformHint */);
}
setTransactionFlags(eTransactionFlushNeeded);
@@ -5191,6 +5496,9 @@
[[fallthrough]];
case ISurfaceComposerClient::eFXSurfaceEffect: {
result = createBufferStateLayer(args, &outResult.handle, &layer);
+ if (result != NO_ERROR) {
+ return result;
+ }
std::atomic<int32_t>* pendingBufferCounter = layer->getPendingBufferCounter();
if (pendingBufferCounter) {
std::string counterName = layer->getPendingBufferCounterName();
@@ -5231,6 +5539,9 @@
status_t SurfaceFlinger::createBufferStateLayer(LayerCreationArgs& args, sp<IBinder>* handle,
sp<Layer>* outLayer) {
+ if (checkLayerLeaks() != NO_ERROR) {
+ return NO_MEMORY;
+ }
*outLayer = getFactory().createBufferStateLayer(args);
*handle = (*outLayer)->getHandle();
return NO_ERROR;
@@ -5238,11 +5549,38 @@
status_t SurfaceFlinger::createEffectLayer(const LayerCreationArgs& args, sp<IBinder>* handle,
sp<Layer>* outLayer) {
+ if (checkLayerLeaks() != NO_ERROR) {
+ return NO_MEMORY;
+ }
*outLayer = getFactory().createEffectLayer(args);
*handle = (*outLayer)->getHandle();
return NO_ERROR;
}
+status_t SurfaceFlinger::checkLayerLeaks() {
+ if (mNumLayers >= MAX_LAYERS) {
+ static std::atomic<nsecs_t> lasttime{0};
+ nsecs_t now = systemTime();
+ if (lasttime != 0 && ns2s(now - lasttime.load()) < 10) {
+ ALOGE("CreateLayer already dumped 10s before");
+ return NO_MEMORY;
+ } else {
+ lasttime = now;
+ }
+
+ ALOGE("CreateLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(),
+ MAX_LAYERS);
+ static_cast<void>(mScheduler->schedule([&]() FTL_FAKE_GUARD(kMainThreadContext) {
+ ALOGE("Dumping on-screen layers.");
+ mLayerHierarchyBuilder.dumpLayerSample(mLayerHierarchyBuilder.getHierarchy());
+ ALOGE("Dumping off-screen layers.");
+ mLayerHierarchyBuilder.dumpLayerSample(mLayerHierarchyBuilder.getOffscreenHierarchy());
+ }));
+ return NO_MEMORY;
+ }
+ return NO_ERROR;
+}
+
void SurfaceFlinger::onHandleDestroyed(sp<Layer>& layer, uint32_t layerId) {
{
// Used to remove stalled transactions which uses an internal lock.
@@ -5262,7 +5600,7 @@
}
void SurfaceFlinger::initializeDisplays() {
- TransactionState state;
+ QueuedTransactionState state;
state.inputWindowCommands = mInputWindowCommands;
const nsecs_t now = systemTime();
state.desiredPresentTime = now;
@@ -5277,7 +5615,7 @@
state.displays.push(DisplayState(display.token(), ui::LayerStack::fromValue(layerStack++)));
}
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back(state);
{
@@ -5331,7 +5669,15 @@
activeDisplay->isPoweredOn(),
"Trying to change power mode on inactive display without powering off active display");
+ const bool couldRefresh = display->isRefreshable();
display->setPowerMode(mode);
+ const bool canRefresh = display->isRefreshable();
+
+ if (couldRefresh && !canRefresh) {
+ decRefreshableDisplays();
+ } else if (!couldRefresh && canRefresh) {
+ incRefreshableDisplays();
+ }
const auto activeMode = display->refreshRateSelector().getActiveMode().modePtr;
if (currentMode == hal::PowerMode::OFF) {
@@ -5665,6 +6011,14 @@
utils::Dumper::Section section(dumper,
ftl::Concat("Virtual Display ", displayId.value).str());
display->dump(dumper);
+
+ if (const auto virtualIdOpt = VirtualDisplayId::tryCast(displayId)) {
+ std::lock_guard lock(mVirtualDisplaysMutex);
+ const auto virtualSnapshotIt = mVirtualDisplays.find(virtualIdOpt.value());
+ if (virtualSnapshotIt != mVirtualDisplays.end()) {
+ virtualSnapshotIt->second.dump(dumper);
+ }
+ }
}
}
}
@@ -6196,7 +6550,7 @@
}
// Numbers from 1000 to 1045 are currently used for backdoors. The code
// in onTransact verifies that the user is root, and has access to use SF.
- if (code >= 1000 && code <= 1045) {
+ if (code >= 1000 && code <= 1046) {
ALOGV("Accessing SurfaceFlinger through backdoor code: %u", code);
return OK;
}
@@ -6463,8 +6817,9 @@
return getDefaultDisplayDevice()->getDisplayToken().promote();
}
- if (const auto id = DisplayId::fromValue<PhysicalDisplayId>(value)) {
- return getPhysicalDisplayToken(*id);
+ if (const auto token =
+ getPhysicalDisplayToken(PhysicalDisplayId::fromValue(value))) {
+ return token;
}
ALOGE("Invalid physical display ID");
@@ -6562,10 +6917,10 @@
case 1040: {
auto future = mScheduler->schedule([&] {
n = data.readInt32();
- std::optional<PhysicalDisplayId> inputId = std::nullopt;
+ PhysicalDisplayId inputId;
if (uint64_t inputDisplayId; data.readUint64(&inputDisplayId) == NO_ERROR) {
- inputId = DisplayId::fromValue<PhysicalDisplayId>(inputDisplayId);
- if (!inputId || getPhysicalDisplayToken(*inputId)) {
+ inputId = PhysicalDisplayId::fromValue(inputDisplayId);
+ if (!getPhysicalDisplayToken(inputId)) {
ALOGE("No display with id: %" PRIu64, inputDisplayId);
return NAME_NOT_FOUND;
}
@@ -6574,7 +6929,7 @@
Mutex::Autolock lock(mStateLock);
mLayerCachingEnabled = n != 0;
for (const auto& [_, display] : mDisplays) {
- if (!inputId || *inputId == display->getPhysicalId()) {
+ if (inputId == display->getPhysicalId()) {
display->enableLayerCaching(mLayerCachingEnabled);
}
}
@@ -6657,11 +7012,10 @@
int64_t arg1 = data.readInt64();
int64_t arg2 = data.readInt64();
// Enable mirroring for one display
- const auto display1id = DisplayId::fromValue(arg1);
auto mirrorRoot = SurfaceComposerClient::getDefault()->mirrorDisplay(
- display1id.value());
- auto id2 = DisplayId::fromValue<PhysicalDisplayId>(arg2);
- const auto token2 = getPhysicalDisplayToken(*id2);
+ DisplayId::fromValue(arg1));
+ const auto token2 =
+ getPhysicalDisplayToken(PhysicalDisplayId::fromValue(arg2));
ui::LayerStack layerStack;
{
Mutex::Autolock lock(mStateLock);
@@ -6729,6 +7083,15 @@
}
return err;
}
+ // Introduce jank to HWC
+ case 1046: {
+ int32_t jankDelayMs = 0;
+ if (data.readInt32(&jankDelayMs) != NO_ERROR) {
+ return BAD_VALUE;
+ }
+ mScheduler->setDebugPresentDelay(TimePoint::fromNs(ms2ns(jankDelayMs)));
+ return NO_ERROR;
+ }
}
}
return err;
@@ -6844,7 +7207,7 @@
struct sched_param param = {0};
int sched_policy;
- if (enabled) {
+ if (enabled && !FlagManager::getInstance().disable_sched_fifo_sf()) {
sched_policy = SCHED_FIFO;
param.sched_priority = kFifoPriority;
} else {
@@ -6884,14 +7247,13 @@
namespace {
-ui::Dataspace pickBestDataspace(ui::Dataspace requestedDataspace,
- const compositionengine::impl::OutputCompositionState& state,
+ui::Dataspace pickBestDataspace(ui::Dataspace requestedDataspace, ui::ColorMode colorMode,
bool capturingHdrLayers, bool hintForSeamlessTransition) {
if (requestedDataspace != ui::Dataspace::UNKNOWN) {
return requestedDataspace;
}
- const auto dataspaceForColorMode = ui::pickDataspaceFor(state.colorMode);
+ const auto dataspaceForColorMode = ui::pickDataspaceFor(colorMode);
// TODO: Enable once HDR screenshots are ready.
if constexpr (/* DISABLES CODE */ (false)) {
@@ -6940,9 +7302,13 @@
}
wp<const DisplayDevice> displayWeak;
+ DisplayId displayId;
ui::LayerStack layerStack;
ui::Size reqSize(args.width, args.height);
std::unordered_set<uint32_t> excludeLayerIds;
+ Rect layerStackSpaceRect;
+ bool displayIsSecure;
+
{
Mutex::Autolock lock(mStateLock);
sp<DisplayDevice> display = getDisplayDeviceLocked(args.displayToken);
@@ -6952,11 +7318,14 @@
return;
}
displayWeak = display;
+ displayId = display->getId();
layerStack = display->getLayerStack();
+ displayIsSecure = display->isSecure();
+ layerStackSpaceRect = display->getLayerStackSpaceRect();
// set the requested width/height to the logical display layer stack rect size by default
if (args.width == 0 || args.height == 0) {
- reqSize = display->getLayerStackSpaceRect().getSize();
+ reqSize = layerStackSpaceRect.getSize();
}
for (const auto& handle : captureArgs.excludeHandles) {
@@ -6975,19 +7344,21 @@
getLayerSnapshotsForScreenshots(layerStack, captureArgs.uid,
std::move(excludeLayerIds));
- ftl::Flags<RenderArea::Options> options;
- if (captureArgs.captureSecureLayers) options |= RenderArea::Options::CAPTURE_SECURE_LAYERS;
- if (captureArgs.hintForSeamlessTransition)
- options |= RenderArea::Options::HINT_FOR_SEAMLESS_TRANSITION;
- captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type<DisplayRenderAreaBuilder>,
- gui::aidl_utils::fromARect(captureArgs.sourceCrop),
- reqSize,
- static_cast<ui::Dataspace>(captureArgs.dataspace),
- displayWeak, options),
- getLayerSnapshotsFn, reqSize,
+ ScreenshotArgs screenshotArgs;
+ screenshotArgs.captureTypeVariant = displayWeak;
+ screenshotArgs.displayId = displayId;
+ screenshotArgs.sourceCrop = gui::aidl_utils::fromARect(captureArgs.sourceCrop);
+ if (screenshotArgs.sourceCrop.isEmpty()) {
+ screenshotArgs.sourceCrop = layerStackSpaceRect;
+ }
+ screenshotArgs.reqSize = reqSize;
+ screenshotArgs.dataspace = static_cast<ui::Dataspace>(captureArgs.dataspace);
+ screenshotArgs.isSecure = captureArgs.captureSecureLayers && displayIsSecure;
+ screenshotArgs.seamlessTransition = captureArgs.hintForSeamlessTransition;
+
+ captureScreenCommon(screenshotArgs, getLayerSnapshotsFn, reqSize,
static_cast<ui::PixelFormat>(captureArgs.pixelFormat),
- captureArgs.allowProtected, captureArgs.grayscale,
- captureArgs.attachGainmap, captureListener);
+ captureArgs.allowProtected, captureArgs.grayscale, captureListener);
}
void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args,
@@ -6995,6 +7366,9 @@
ui::LayerStack layerStack;
wp<const DisplayDevice> displayWeak;
ui::Size size;
+ Rect layerStackSpaceRect;
+ bool displayIsSecure;
+
{
Mutex::Autolock lock(mStateLock);
@@ -7007,7 +7381,9 @@
displayWeak = display;
layerStack = display->getLayerStack();
+ layerStackSpaceRect = display->getLayerStackSpaceRect();
size = display->getLayerStackSpaceRect().getSize();
+ displayIsSecure = display->isSecure();
}
size.width *= args.frameScaleX;
@@ -7036,15 +7412,18 @@
constexpr bool kAllowProtected = false;
constexpr bool kGrayscale = false;
- ftl::Flags<RenderArea::Options> options;
- if (args.hintForSeamlessTransition)
- options |= RenderArea::Options::HINT_FOR_SEAMLESS_TRANSITION;
- captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type<DisplayRenderAreaBuilder>,
- Rect(), size,
- static_cast<ui::Dataspace>(args.dataspace),
- displayWeak, options),
- getLayerSnapshotsFn, size, static_cast<ui::PixelFormat>(args.pixelFormat),
- kAllowProtected, kGrayscale, args.attachGainmap, captureListener);
+ ScreenshotArgs screenshotArgs;
+ screenshotArgs.captureTypeVariant = displayWeak;
+ screenshotArgs.displayId = displayId;
+ screenshotArgs.sourceCrop = layerStackSpaceRect;
+ screenshotArgs.reqSize = size;
+ screenshotArgs.dataspace = static_cast<ui::Dataspace>(args.dataspace);
+ screenshotArgs.isSecure = args.captureSecureLayers && displayIsSecure;
+ screenshotArgs.seamlessTransition = args.hintForSeamlessTransition;
+
+ captureScreenCommon(screenshotArgs, getLayerSnapshotsFn, size,
+ static_cast<ui::PixelFormat>(args.pixelFormat), kAllowProtected, kGrayscale,
+ captureListener);
}
ScreenCaptureResults SurfaceFlinger::captureLayersSync(const LayerCaptureArgs& args) {
@@ -7146,17 +7525,18 @@
return;
}
- ftl::Flags<RenderArea::Options> options;
- if (captureArgs.captureSecureLayers) options |= RenderArea::Options::CAPTURE_SECURE_LAYERS;
- if (captureArgs.hintForSeamlessTransition)
- options |= RenderArea::Options::HINT_FOR_SEAMLESS_TRANSITION;
- captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type<LayerRenderAreaBuilder>, crop,
- reqSize, dataspace, parent, args.childrenOnly,
- options),
- getLayerSnapshotsFn, reqSize,
+ ScreenshotArgs screenshotArgs;
+ screenshotArgs.captureTypeVariant = parent->getSequence();
+ screenshotArgs.childrenOnly = args.childrenOnly;
+ screenshotArgs.sourceCrop = crop;
+ screenshotArgs.reqSize = reqSize;
+ screenshotArgs.dataspace = static_cast<ui::Dataspace>(captureArgs.dataspace);
+ screenshotArgs.isSecure = captureArgs.captureSecureLayers;
+ screenshotArgs.seamlessTransition = captureArgs.hintForSeamlessTransition;
+
+ captureScreenCommon(screenshotArgs, getLayerSnapshotsFn, reqSize,
static_cast<ui::PixelFormat>(captureArgs.pixelFormat),
- captureArgs.allowProtected, captureArgs.grayscale,
- captureArgs.attachGainmap, captureListener);
+ captureArgs.allowProtected, captureArgs.grayscale, captureListener);
}
// Creates a Future release fence for a layer and keeps track of it in a list to
@@ -7172,9 +7552,10 @@
// typically a layer with DRM contents, or have the GRALLOC_USAGE_PROTECTED set on the buffer.
// A protected layer has no implication on whether it's secure, which is explicitly set by
// application to avoid being screenshot or drawn via unsecure display.
-bool SurfaceFlinger::layersHasProtectedLayer(const std::vector<sp<LayerFE>>& layers) const {
+bool SurfaceFlinger::layersHasProtectedLayer(
+ const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const {
bool protectedLayerFound = false;
- for (auto& layerFE : layers) {
+ for (auto& [_, layerFE] : layers) {
protectedLayerFound |=
(layerFE->mSnapshot->isVisible && layerFE->mSnapshot->hasProtectedContent);
if (protectedLayerFound) {
@@ -7184,30 +7565,38 @@
return protectedLayerFound;
}
-// Getting layer snapshots and display should take place on main thread.
-// Accessing display requires mStateLock, and contention for this lock
-// is reduced when grabbed from the main thread, thus also reducing
-// risk of deadlocks.
-std::optional<SurfaceFlinger::OutputCompositionState> SurfaceFlinger::getSnapshotsFromMainThread(
- RenderAreaBuilderVariant& renderAreaBuilder, GetLayerSnapshotsFunction getLayerSnapshotsFn,
- std::vector<sp<LayerFE>>& layerFEs) {
+// Getting layer snapshots and accessing display state should take place on
+// main thread. Accessing display requires mStateLock, and contention for
+// this lock is reduced when grabbed from the main thread, thus also reducing
+// risk of deadlocks. Returns false if no display is found.
+bool SurfaceFlinger::getSnapshotsFromMainThread(
+ ScreenshotArgs& args, GetLayerSnapshotsFunction getLayerSnapshotsFn,
+ std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) {
return mScheduler
- ->schedule([=, this, &renderAreaBuilder, &layerFEs]() REQUIRES(kMainThreadContext) {
+ ->schedule([=, this, &args, &layers]() REQUIRES(kMainThreadContext) {
+ SFTRACE_NAME_FOR_TRACK(WorkloadTracer::TRACK_NAME, "Screenshot");
+ mPowerAdvisor->setScreenshotWorkload();
SFTRACE_NAME("getSnapshotsFromMainThread");
- auto layers = getLayerSnapshotsFn();
- for (auto& [layer, layerFE] : layers) {
- attachReleaseFenceFutureToLayer(layer, layerFE.get(), ui::INVALID_LAYER_STACK);
+ layers = getLayerSnapshotsFn();
+ // Non-threaded RenderEngine eventually returns to the main thread a 2nd time
+ // to complete the screenshot. Release fences should only be added during the 2nd
+ // hop to main thread in order to avoid potential deadlocks from waiting for the
+ // the future fence to fire.
+ if (mRenderEngine->isThreaded()) {
+ for (auto& [layer, layerFE] : layers) {
+ attachReleaseFenceFutureToLayer(layer, layerFE.get(),
+ ui::INVALID_LAYER_STACK);
+ }
}
- layerFEs = extractLayerFEs(layers);
- return getDisplayStateFromRenderAreaBuilder(renderAreaBuilder);
+ return getDisplayStateOnMainThread(args);
})
.get();
}
-void SurfaceFlinger::captureScreenCommon(RenderAreaBuilderVariant renderAreaBuilder,
+void SurfaceFlinger::captureScreenCommon(ScreenshotArgs& args,
GetLayerSnapshotsFunction getLayerSnapshotsFn,
ui::Size bufferSize, ui::PixelFormat reqPixelFormat,
- bool allowProtected, bool grayscale, bool attachGainmap,
+ bool allowProtected, bool grayscale,
const sp<IScreenCaptureListener>& captureListener) {
SFTRACE_CALL();
@@ -7219,105 +7608,119 @@
return;
}
- if (FlagManager::getInstance().single_hop_screenshot() &&
- FlagManager::getInstance().ce_fence_promise() && mRenderEngine->isThreaded()) {
- std::vector<sp<LayerFE>> layerFEs;
- auto displayState =
- getSnapshotsFromMainThread(renderAreaBuilder, getLayerSnapshotsFn, layerFEs);
-
- const bool supportsProtected = getRenderEngine().supportsProtectedContent();
- bool hasProtectedLayer = false;
- if (allowProtected && supportsProtected) {
- hasProtectedLayer = layersHasProtectedLayer(layerFEs);
- }
- const bool isProtected = hasProtectedLayer && allowProtected && supportsProtected;
- const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER |
- GRALLOC_USAGE_HW_TEXTURE |
- (isProtected ? GRALLOC_USAGE_PROTECTED
- : GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
- sp<GraphicBuffer> buffer =
- getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(),
- static_cast<android_pixel_format>(reqPixelFormat),
- 1 /* layerCount */, usage, "screenshot");
-
- const status_t bufferStatus = buffer->initCheck();
- if (bufferStatus != OK) {
- // Animations may end up being really janky, but don't crash here.
- // Otherwise an irreponsible process may cause an SF crash by allocating
- // too much.
- ALOGE("%s: Buffer failed to allocate: %d", __func__, bufferStatus);
- invokeScreenCaptureError(bufferStatus, captureListener);
- return;
- }
- const std::shared_ptr<renderengine::ExternalTexture> texture = std::make_shared<
- renderengine::impl::ExternalTexture>(buffer, getRenderEngine(),
- renderengine::impl::ExternalTexture::Usage::
- WRITEABLE);
- auto futureFence = captureScreenshot(renderAreaBuilder, texture, false /* regionSampling */,
- grayscale, isProtected, attachGainmap, captureListener,
- displayState, layerFEs);
- futureFence.get();
-
- } else {
- const bool supportsProtected = getRenderEngine().supportsProtectedContent();
- bool hasProtectedLayer = false;
- if (allowProtected && supportsProtected) {
- auto layers = mScheduler->schedule([=]() { return getLayerSnapshotsFn(); }).get();
- hasProtectedLayer = layersHasProtectedLayer(extractLayerFEs(layers));
- }
- const bool isProtected = hasProtectedLayer && allowProtected && supportsProtected;
- const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER |
- GRALLOC_USAGE_HW_TEXTURE |
- (isProtected ? GRALLOC_USAGE_PROTECTED
- : GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
- sp<GraphicBuffer> buffer =
- getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(),
- static_cast<android_pixel_format>(reqPixelFormat),
- 1 /* layerCount */, usage, "screenshot");
-
- const status_t bufferStatus = buffer->initCheck();
- if (bufferStatus != OK) {
- // Animations may end up being really janky, but don't crash here.
- // Otherwise an irreponsible process may cause an SF crash by allocating
- // too much.
- ALOGE("%s: Buffer failed to allocate: %d", __func__, bufferStatus);
- invokeScreenCaptureError(bufferStatus, captureListener);
- return;
- }
- const std::shared_ptr<renderengine::ExternalTexture> texture = std::make_shared<
- renderengine::impl::ExternalTexture>(buffer, getRenderEngine(),
- renderengine::impl::ExternalTexture::Usage::
- WRITEABLE);
- auto futureFence = captureScreenshotLegacy(renderAreaBuilder, getLayerSnapshotsFn, texture,
- false /* regionSampling */, grayscale,
- isProtected, attachGainmap, captureListener);
- futureFence.get();
+ std::vector<std::pair<Layer*, sp<LayerFE>>> layers;
+ bool hasDisplayState = getSnapshotsFromMainThread(args, getLayerSnapshotsFn, layers);
+ if (!hasDisplayState) {
+ ALOGD("Display state not found");
+ invokeScreenCaptureError(NO_MEMORY, captureListener);
}
+
+ const bool hasHdrLayer = std::any_of(layers.cbegin(), layers.cend(), [this](const auto& layer) {
+ return isHdrLayer(*(layer.second->mSnapshot.get()));
+ });
+
+ const bool supportsProtected = getRenderEngine().supportsProtectedContent();
+ bool hasProtectedLayer = false;
+ if (allowProtected && supportsProtected) {
+ hasProtectedLayer = layersHasProtectedLayer(layers);
+ }
+ const bool isProtected = hasProtectedLayer && allowProtected && supportsProtected;
+ const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER |
+ GRALLOC_USAGE_HW_TEXTURE |
+ (isProtected ? GRALLOC_USAGE_PROTECTED
+ : GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+ sp<GraphicBuffer> buffer =
+ getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(),
+ static_cast<android_pixel_format>(reqPixelFormat),
+ 1 /* layerCount */, usage, "screenshot");
+
+ const status_t bufferStatus = buffer->initCheck();
+ if (bufferStatus != OK) {
+ // Animations may end up being really janky, but don't crash here.
+ // Otherwise an irreponsible process may cause an SF crash by allocating
+ // too much.
+ ALOGE("%s: Buffer failed to allocate: %d", __func__, bufferStatus);
+ invokeScreenCaptureError(bufferStatus, captureListener);
+ return;
+ }
+ const std::shared_ptr<renderengine::ExternalTexture> texture = std::make_shared<
+ renderengine::impl::ExternalTexture>(buffer, getRenderEngine(),
+ renderengine::impl::ExternalTexture::Usage::
+ WRITEABLE);
+
+ std::shared_ptr<renderengine::impl::ExternalTexture> hdrTexture;
+ std::shared_ptr<renderengine::impl::ExternalTexture> gainmapTexture;
+
+ if (hasHdrLayer && !args.seamlessTransition &&
+ FlagManager::getInstance().true_hdr_screenshots()) {
+ const auto hdrBuffer =
+ getFactory().createGraphicBuffer(buffer->getWidth(), buffer->getHeight(),
+ HAL_PIXEL_FORMAT_RGBA_FP16, 1 /* layerCount */,
+ buffer->getUsage(), "screenshot-hdr");
+ const auto gainmapBuffer =
+ getFactory().createGraphicBuffer(buffer->getWidth(), buffer->getHeight(),
+ buffer->getPixelFormat(), 1 /* layerCount */,
+ buffer->getUsage(), "screenshot-gainmap");
+
+ const status_t hdrBufferStatus = hdrBuffer->initCheck();
+ const status_t gainmapBufferStatus = gainmapBuffer->initCheck();
+
+ if (hdrBufferStatus != OK || gainmapBufferStatus != -OK) {
+ if (hdrBufferStatus != OK) {
+ ALOGW("%s: Buffer failed to allocate for hdr: %d. Screenshoting SDR instead.",
+ __func__, hdrBufferStatus);
+ } else {
+ ALOGW("%s: Buffer failed to allocate for gainmap: %d. Screenshoting SDR instead.",
+ __func__, gainmapBufferStatus);
+ }
+ } else {
+ hdrTexture = std::make_shared<
+ renderengine::impl::ExternalTexture>(hdrBuffer, getRenderEngine(),
+ renderengine::impl::ExternalTexture::
+ Usage::WRITEABLE);
+ gainmapTexture = std::make_shared<
+ renderengine::impl::ExternalTexture>(gainmapBuffer, getRenderEngine(),
+ renderengine::impl::ExternalTexture::
+ Usage::WRITEABLE);
+ }
+ }
+
+ auto futureFence =
+ captureScreenshot(args, texture, false /* regionSampling */, grayscale, isProtected,
+ captureListener, layers, hdrTexture, gainmapTexture);
+ futureFence.get();
}
-std::optional<SurfaceFlinger::OutputCompositionState>
-SurfaceFlinger::getDisplayStateFromRenderAreaBuilder(RenderAreaBuilderVariant& renderAreaBuilder) {
+// Returns true if display is found and args was populated with display state
+// data. Otherwise, returns false.
+bool SurfaceFlinger::getDisplayStateOnMainThread(ScreenshotArgs& args) {
sp<const DisplayDevice> display = nullptr;
{
Mutex::Autolock lock(mStateLock);
- if (auto* layerRenderAreaBuilder =
- std::get_if<LayerRenderAreaBuilder>(&renderAreaBuilder)) {
+ // Screenshot initiated through captureLayers
+ if (auto* layerSequence = std::get_if<int32_t>(&args.captureTypeVariant)) {
// LayerSnapshotBuilder should only be accessed from the main thread.
const frontend::LayerSnapshot* snapshot =
- mLayerSnapshotBuilder.getSnapshot(layerRenderAreaBuilder->layer->getSequence());
+ mLayerSnapshotBuilder.getSnapshot(*layerSequence);
if (!snapshot) {
- ALOGW("Couldn't find layer snapshot for %d",
- layerRenderAreaBuilder->layer->getSequence());
+ ALOGW("Couldn't find layer snapshot for %d", *layerSequence);
} else {
- layerRenderAreaBuilder->setLayerSnapshot(*snapshot);
+ if (!args.childrenOnly) {
+ args.transform = snapshot->localTransform.inverse();
+ }
+ if (args.sourceCrop.isEmpty()) {
+ args.sourceCrop = snapshot->bufferSize;
+ }
display = findDisplay(
[layerStack = snapshot->outputFilter.layerStack](const auto& display) {
return display.getLayerStack() == layerStack;
});
}
- } else if (auto* displayRenderAreaBuilder =
- std::get_if<DisplayRenderAreaBuilder>(&renderAreaBuilder)) {
- display = displayRenderAreaBuilder->displayWeak.promote();
+
+ // Screenshot initiated through captureDisplay
+ } else if (auto* displayWeak =
+ std::get_if<wp<const DisplayDevice>>(&args.captureTypeVariant)) {
+ display = displayWeak->promote();
}
if (display == nullptr) {
@@ -7325,124 +7728,66 @@
}
if (display != nullptr) {
- return std::optional{display->getCompositionDisplay()->getState()};
+ const auto& state = display->getCompositionDisplay()->getState();
+ args.displayBrightnessNits = state.displayBrightnessNits;
+ args.sdrWhitePointNits = state.sdrWhitePointNits;
+ args.renderIntent = state.renderIntent;
+ args.colorMode = state.colorMode;
+ return true;
}
}
- return std::nullopt;
-}
-
-std::vector<sp<LayerFE>> SurfaceFlinger::extractLayerFEs(
- const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const {
- std::vector<sp<LayerFE>> layerFEs;
- layerFEs.reserve(layers.size());
- for (const auto& [_, layerFE] : layers) {
- layerFEs.push_back(layerFE);
- }
- return layerFEs;
+ return false;
}
ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot(
- const RenderAreaBuilderVariant& renderAreaBuilder,
- const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
- bool grayscale, bool isProtected, bool attachGainmap,
+ ScreenshotArgs& args, const std::shared_ptr<renderengine::ExternalTexture>& buffer,
+ bool regionSampling, bool grayscale, bool isProtected,
const sp<IScreenCaptureListener>& captureListener,
- std::optional<OutputCompositionState>& displayState, std::vector<sp<LayerFE>>& layerFEs) {
+ const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers,
+ const std::shared_ptr<renderengine::ExternalTexture>& hdrBuffer,
+ const std::shared_ptr<renderengine::ExternalTexture>& gainmapBuffer) {
SFTRACE_CALL();
ScreenCaptureResults captureResults;
- std::unique_ptr<const RenderArea> renderArea =
- std::visit([](auto&& arg) -> std::unique_ptr<RenderArea> { return arg.build(); },
- renderAreaBuilder);
+ ftl::SharedFuture<FenceResult> renderFuture;
- if (!renderArea) {
- ALOGW("Skipping screen capture because of invalid render area.");
- if (captureListener) {
- captureResults.fenceResult = base::unexpected(NO_MEMORY);
- captureListener->onScreenCaptureCompleted(captureResults);
- }
- return ftl::yield<FenceResult>(base::unexpected(NO_ERROR)).share();
- }
- float displayBrightnessNits = displayState.value().displayBrightnessNits;
- float sdrWhitePointNits = displayState.value().sdrWhitePointNits;
+ float hdrSdrRatio = args.displayBrightnessNits / args.sdrWhitePointNits;
- // Empty vector needed to pass into renderScreenImpl for legacy path
- std::vector<std::pair<Layer*, sp<android::LayerFE>>> layers;
- ftl::SharedFuture<FenceResult> renderFuture =
- renderScreenImpl(renderArea.get(), buffer, regionSampling, grayscale, isProtected,
- attachGainmap, captureResults, displayState, layers, layerFEs);
+ if (hdrBuffer && gainmapBuffer) {
+ ftl::SharedFuture<FenceResult> hdrRenderFuture =
+ renderScreenImpl(args, hdrBuffer, regionSampling, grayscale, isProtected,
+ captureResults, layers);
+ captureResults.buffer = buffer->getBuffer();
+ captureResults.optionalGainMap = gainmapBuffer->getBuffer();
- if (captureResults.capturedHdrLayers && attachGainmap &&
- FlagManager::getInstance().true_hdr_screenshots()) {
- sp<GraphicBuffer> hdrBuffer =
- getFactory().createGraphicBuffer(buffer->getWidth(), buffer->getHeight(),
- HAL_PIXEL_FORMAT_RGBA_FP16, 1 /* layerCount */,
- buffer->getUsage(), "screenshot-hdr");
- sp<GraphicBuffer> gainmapBuffer =
- getFactory().createGraphicBuffer(buffer->getWidth(), buffer->getHeight(),
- buffer->getPixelFormat(), 1 /* layerCount */,
- buffer->getUsage(), "screenshot-gainmap");
+ renderFuture =
+ ftl::Future(std::move(hdrRenderFuture))
+ .then([&, hdrSdrRatio, dataspace = captureResults.capturedDataspace, buffer,
+ hdrBuffer, gainmapBuffer](FenceResult fenceResult) -> FenceResult {
+ if (!fenceResult.ok()) {
+ return fenceResult;
+ }
- const status_t bufferStatus = hdrBuffer->initCheck();
- const status_t gainmapBufferStatus = gainmapBuffer->initCheck();
-
- if (bufferStatus != OK) {
- ALOGW("%s: Buffer failed to allocate for hdr: %d. Screenshoting SDR instead.", __func__,
- bufferStatus);
- } else if (gainmapBufferStatus != OK) {
- ALOGW("%s: Buffer failed to allocate for gainmap: %d. Screenshoting SDR instead.",
- __func__, gainmapBufferStatus);
- } else {
- captureResults.optionalGainMap = gainmapBuffer;
- const auto hdrTexture = std::make_shared<
- renderengine::impl::ExternalTexture>(hdrBuffer, getRenderEngine(),
- renderengine::impl::ExternalTexture::
- Usage::WRITEABLE);
- const auto gainmapTexture = std::make_shared<
- renderengine::impl::ExternalTexture>(gainmapBuffer, getRenderEngine(),
- renderengine::impl::ExternalTexture::
- Usage::WRITEABLE);
- ScreenCaptureResults unusedResults;
- ftl::SharedFuture<FenceResult> hdrRenderFuture =
- renderScreenImpl(renderArea.get(), hdrTexture, regionSampling, grayscale,
- isProtected, attachGainmap, unusedResults, displayState,
- layers, layerFEs);
-
- renderFuture =
- ftl::Future(std::move(renderFuture))
- .then([&, hdrRenderFuture = std::move(hdrRenderFuture),
- displayBrightnessNits, sdrWhitePointNits,
- dataspace = captureResults.capturedDataspace, buffer, hdrTexture,
- gainmapTexture](FenceResult fenceResult) -> FenceResult {
- if (!fenceResult.ok()) {
- return fenceResult;
- }
-
- auto hdrFenceResult = hdrRenderFuture.get();
-
- if (!hdrFenceResult.ok()) {
- return hdrFenceResult;
- }
-
- return getRenderEngine()
- .drawGainmap(buffer, fenceResult.value()->get(), hdrTexture,
- hdrFenceResult.value()->get(),
- displayBrightnessNits / sdrWhitePointNits,
- static_cast<ui::Dataspace>(dataspace),
- gainmapTexture)
- .get();
- })
- .share();
- };
+ return getRenderEngine()
+ .tonemapAndDrawGainmap(hdrBuffer, fenceResult.value()->get(),
+ hdrSdrRatio,
+ static_cast<ui::Dataspace>(dataspace),
+ buffer, gainmapBuffer)
+ .get();
+ })
+ .share();
+ } else {
+ renderFuture = renderScreenImpl(args, buffer, regionSampling, grayscale, isProtected,
+ captureResults, layers);
}
if (captureListener) {
// Defer blocking on renderFuture back to the Binder thread.
return ftl::Future(std::move(renderFuture))
.then([captureListener, captureResults = std::move(captureResults),
- displayBrightnessNits,
- sdrWhitePointNits](FenceResult fenceResult) mutable -> FenceResult {
+ hdrSdrRatio](FenceResult fenceResult) mutable -> FenceResult {
captureResults.fenceResult = std::move(fenceResult);
- captureResults.hdrSdrRatio = displayBrightnessNits / sdrWhitePointNits;
+ captureResults.hdrSdrRatio = hdrSdrRatio;
captureListener->onScreenCaptureCompleted(captureResults);
return base::unexpected(NO_ERROR);
})
@@ -7451,157 +7796,81 @@
return renderFuture;
}
-ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshotLegacy(
- RenderAreaBuilderVariant renderAreaBuilder, GetLayerSnapshotsFunction getLayerSnapshotsFn,
- const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
- bool grayscale, bool isProtected, bool attachGainmap,
- const sp<IScreenCaptureListener>& captureListener) {
- SFTRACE_CALL();
-
- auto takeScreenshotFn = [=, this, renderAreaBuilder = std::move(renderAreaBuilder)]() REQUIRES(
- kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> {
- auto layers = getLayerSnapshotsFn();
- if (FlagManager::getInstance().ce_fence_promise()) {
- for (auto& [layer, layerFE] : layers) {
- attachReleaseFenceFutureToLayer(layer, layerFE.get(), ui::INVALID_LAYER_STACK);
- }
- }
- auto displayState = getDisplayStateFromRenderAreaBuilder(renderAreaBuilder);
-
- ScreenCaptureResults captureResults;
- std::unique_ptr<const RenderArea> renderArea =
- std::visit([](auto&& arg) -> std::unique_ptr<RenderArea> { return arg.build(); },
- renderAreaBuilder);
-
- if (!renderArea) {
- ALOGW("Skipping screen capture because of invalid render area.");
- if (captureListener) {
- captureResults.fenceResult = base::unexpected(NO_MEMORY);
- captureListener->onScreenCaptureCompleted(captureResults);
- }
- return ftl::yield<FenceResult>(base::unexpected(NO_ERROR)).share();
- }
-
- auto layerFEs = extractLayerFEs(layers);
- ftl::SharedFuture<FenceResult> renderFuture =
- renderScreenImpl(renderArea.get(), buffer, regionSampling, grayscale, isProtected,
- attachGainmap, captureResults, displayState, layers, layerFEs);
-
- if (captureListener) {
- // Defer blocking on renderFuture back to the Binder thread.
- return ftl::Future(std::move(renderFuture))
- .then([captureListener, captureResults = std::move(captureResults)](
- FenceResult fenceResult) mutable -> FenceResult {
- captureResults.fenceResult = std::move(fenceResult);
- captureListener->onScreenCaptureCompleted(captureResults);
- return base::unexpected(NO_ERROR);
- })
- .share();
- }
- return renderFuture;
- };
-
- // TODO(b/294936197): Run takeScreenshotsFn() in a binder thread to reduce the number
- // of calls on the main thread.
- auto future =
- mScheduler->schedule(FTL_FAKE_GUARD(kMainThreadContext, std::move(takeScreenshotFn)));
-
- // Flatten nested futures.
- auto chain = ftl::Future(std::move(future)).then([](ftl::SharedFuture<FenceResult> future) {
- return future;
- });
-
- return chain.share();
-}
-
ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
- const RenderArea* renderArea, const std::shared_ptr<renderengine::ExternalTexture>& buffer,
- bool regionSampling, bool grayscale, bool isProtected, bool attachGainmap,
- ScreenCaptureResults& captureResults, std::optional<OutputCompositionState>& displayState,
- std::vector<std::pair<Layer*, sp<LayerFE>>>& layers, std::vector<sp<LayerFE>>& layerFEs) {
+ ScreenshotArgs& args, const std::shared_ptr<renderengine::ExternalTexture>& buffer,
+ bool regionSampling, bool grayscale, bool isProtected, ScreenCaptureResults& captureResults,
+ const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) {
SFTRACE_CALL();
- for (auto& layerFE : layerFEs) {
+ for (auto& [_, layerFE] : layers) {
frontend::LayerSnapshot* snapshot = layerFE->mSnapshot.get();
captureResults.capturedSecureLayers |= (snapshot->isVisible && snapshot->isSecure);
captureResults.capturedHdrLayers |= isHdrLayer(*snapshot);
layerFE->mSnapshot->geomLayerTransform =
- renderArea->getTransform() * layerFE->mSnapshot->geomLayerTransform;
+ args.transform * layerFE->mSnapshot->geomLayerTransform;
layerFE->mSnapshot->geomInverseLayerTransform =
layerFE->mSnapshot->geomLayerTransform.inverse();
}
- auto capturedBuffer = buffer;
+ const bool enableLocalTonemapping =
+ FlagManager::getInstance().local_tonemap_screenshots() && !args.seamlessTransition;
- auto requestedDataspace = renderArea->getReqDataSpace();
- auto parent = renderArea->getParentLayer();
- auto renderIntent = RenderIntent::TONE_MAP_COLORIMETRIC;
- auto sdrWhitePointNits = DisplayDevice::sDefaultMaxLumiance;
- auto displayBrightnessNits = DisplayDevice::sDefaultMaxLumiance;
+ captureResults.capturedDataspace =
+ pickBestDataspace(args.dataspace, args.colorMode, captureResults.capturedHdrLayers,
+ args.seamlessTransition);
- captureResults.capturedDataspace = requestedDataspace;
-
- const bool enableLocalTonemapping = FlagManager::getInstance().local_tonemap_screenshots() &&
- !renderArea->getHintForSeamlessTransition();
-
- if (displayState) {
- const auto& state = displayState.value();
- captureResults.capturedDataspace =
- pickBestDataspace(requestedDataspace, state, captureResults.capturedHdrLayers,
- renderArea->getHintForSeamlessTransition());
- sdrWhitePointNits = state.sdrWhitePointNits;
-
- if (!captureResults.capturedHdrLayers) {
- displayBrightnessNits = sdrWhitePointNits;
- } else {
- displayBrightnessNits = state.displayBrightnessNits;
- if (!enableLocalTonemapping) {
- // Only clamp the display brightness if this is not a seamless transition.
- // Otherwise for seamless transitions it's important to match the current
- // display state as the buffer will be shown under these same conditions, and we
- // want to avoid any flickers
- if (sdrWhitePointNits > 1.0f && !renderArea->getHintForSeamlessTransition()) {
- // Restrict the amount of HDR "headroom" in the screenshot to avoid
- // over-dimming the SDR portion. 2.0 chosen by experimentation
- constexpr float kMaxScreenshotHeadroom = 2.0f;
- displayBrightnessNits = std::min(sdrWhitePointNits * kMaxScreenshotHeadroom,
- displayBrightnessNits);
- }
- }
+ // Only clamp the display brightness if this is not a seamless transition.
+ // Otherwise for seamless transitions it's important to match the current
+ // display state as the buffer will be shown under these same conditions, and we
+ // want to avoid any flickers.
+ if (captureResults.capturedHdrLayers) {
+ if (!enableLocalTonemapping && args.sdrWhitePointNits > 1.0f && !args.seamlessTransition) {
+ // Restrict the amount of HDR "headroom" in the screenshot to avoid
+ // over-dimming the SDR portion. 2.0 chosen by experimentation
+ constexpr float kMaxScreenshotHeadroom = 2.0f;
+ // TODO: Aim to update displayBrightnessNits earlier in screenshot
+ // path so ScreenshotArgs can be passed as const
+ args.displayBrightnessNits = std::min(args.sdrWhitePointNits * kMaxScreenshotHeadroom,
+ args.displayBrightnessNits);
}
-
- // Screenshots leaving the device should be colorimetric
- if (requestedDataspace == ui::Dataspace::UNKNOWN &&
- renderArea->getHintForSeamlessTransition()) {
- renderIntent = state.renderIntent;
- }
+ } else {
+ args.displayBrightnessNits = args.sdrWhitePointNits;
}
+ auto renderIntent = RenderIntent::TONE_MAP_COLORIMETRIC;
+ // Screenshots leaving the device should be colorimetric
+ if (args.dataspace == ui::Dataspace::UNKNOWN && args.seamlessTransition) {
+ renderIntent = args.renderIntent;
+ }
+
+ auto capturedBuffer = buffer;
captureResults.buffer = capturedBuffer->getBuffer();
ui::LayerStack layerStack{ui::DEFAULT_LAYER_STACK};
- if (!layerFEs.empty()) {
- const sp<LayerFE>& layerFE = layerFEs.back();
+ if (!layers.empty()) {
+ const sp<LayerFE>& layerFE = layers.back().second;
layerStack = layerFE->getCompositionState()->outputFilter.layerStack;
}
- auto copyLayerFEs = [&layerFEs]() {
- std::vector<sp<compositionengine::LayerFE>> ceLayerFEs;
- ceLayerFEs.reserve(layerFEs.size());
- for (const auto& layerFE : layerFEs) {
- ceLayerFEs.push_back(layerFE);
- }
- return ceLayerFEs;
- };
-
auto present = [this, buffer = capturedBuffer, dataspace = captureResults.capturedDataspace,
- sdrWhitePointNits, displayBrightnessNits, grayscale, isProtected,
- layerFEs = copyLayerFEs(), layerStack, regionSampling,
- renderArea = std::move(renderArea), renderIntent,
+ grayscale, isProtected, layers, layerStack, regionSampling, args, renderIntent,
enableLocalTonemapping]() -> FenceResult {
std::unique_ptr<compositionengine::CompositionEngine> compositionEngine =
mFactory.createCompositionEngine();
compositionEngine->setRenderEngine(mRenderEngine.get());
+ compositionEngine->setHwComposer(mHWComposer.get());
+
+ std::vector<sp<compositionengine::LayerFE>> layerFEs;
+ layerFEs.reserve(layers.size());
+ for (auto& [layer, layerFE] : layers) {
+ // Release fences were not yet added for non-threaded render engine. To avoid
+ // deadlocks between main thread and binder threads waiting for the future fence
+ // result, fences should be added to layers in the same hop onto the main thread.
+ if (!mRenderEngine->isThreaded()) {
+ attachReleaseFenceFutureToLayer(layer, layerFE.get(), ui::INVALID_LAYER_STACK);
+ }
+ layerFEs.push_back(layerFE);
+ }
compositionengine::Output::ColorProfile colorProfile{.dataspace = dataspace,
.renderIntent = renderIntent};
@@ -7610,9 +7879,10 @@
if (enableLocalTonemapping) {
// Boost the whole scene so that SDR white is at 1.0 while still communicating the hdr
// sdr ratio via display brightness / sdrWhite nits.
- targetBrightness = sdrWhitePointNits / displayBrightnessNits;
+ targetBrightness = args.sdrWhitePointNits / args.displayBrightnessNits;
} else if (dataspace == ui::Dataspace::BT2020_HLG) {
- const float maxBrightnessNits = displayBrightnessNits / sdrWhitePointNits * 203;
+ const float maxBrightnessNits =
+ args.displayBrightnessNits / args.sdrWhitePointNits * 203;
// With a low dimming ratio, don't fit the entire curve. Otherwise mixed content
// will appear way too bright.
if (maxBrightnessNits < 1000.f) {
@@ -7620,23 +7890,33 @@
}
}
+ // Capturing screenshots using layers have a clear capture fill (0 alpha).
+ // Capturing via display or displayId, which do not use args.layerSequence,
+ // has an opaque capture fill (1 alpha).
+ const float layerAlpha =
+ std::holds_alternative<int32_t>(args.captureTypeVariant) ? 0.0f : 1.0f;
+
// Screenshots leaving the device must not dim in gamma space.
- const bool dimInGammaSpaceForEnhancedScreenshots = mDimInGammaSpaceForEnhancedScreenshots &&
- renderArea->getHintForSeamlessTransition();
+ const bool dimInGammaSpaceForEnhancedScreenshots =
+ mDimInGammaSpaceForEnhancedScreenshots && args.seamlessTransition;
std::shared_ptr<ScreenCaptureOutput> output = createScreenCaptureOutput(
ScreenCaptureOutputArgs{.compositionEngine = *compositionEngine,
.colorProfile = colorProfile,
- .renderArea = *renderArea,
.layerStack = layerStack,
+ .sourceCrop = args.sourceCrop,
.buffer = std::move(buffer),
- .sdrWhitePointNits = sdrWhitePointNits,
- .displayBrightnessNits = displayBrightnessNits,
+ .displayId = args.displayId,
+ .reqBufferSize = args.reqSize,
+ .sdrWhitePointNits = args.sdrWhitePointNits,
+ .displayBrightnessNits = args.displayBrightnessNits,
.targetBrightness = targetBrightness,
+ .layerAlpha = layerAlpha,
.regionSampling = regionSampling,
.treat170mAsSrgb = mTreat170mAsSrgb,
.dimInGammaSpaceForEnhancedScreenshots =
dimInGammaSpaceForEnhancedScreenshots,
+ .isSecure = args.isSecure,
.isProtected = isProtected,
.enableLocalTonemapping = enableLocalTonemapping});
@@ -7660,36 +7940,9 @@
//
// TODO(b/196334700) Once we use RenderEngineThreaded everywhere we can always defer the call
// to CompositionEngine::present.
- ftl::SharedFuture<FenceResult> presentFuture;
- if (FlagManager::getInstance().single_hop_screenshot() &&
- FlagManager::getInstance().ce_fence_promise() && mRenderEngine->isThreaded()) {
- presentFuture = ftl::yield(present()).share();
- } else {
- presentFuture = mRenderEngine->isThreaded() ? ftl::defer(std::move(present)).share()
- : ftl::yield(present()).share();
- }
-
- if (!FlagManager::getInstance().ce_fence_promise()) {
- for (auto& [layer, layerFE] : layers) {
- layer->onLayerDisplayed(presentFuture, ui::INVALID_LAYER_STACK,
- [layerFE = std::move(layerFE)](FenceResult) {
- if (FlagManager::getInstance()
- .screenshot_fence_preservation()) {
- const auto compositionResult =
- layerFE->stealCompositionResult();
- const auto& fences = compositionResult.releaseFences;
- // CompositionEngine may choose to cull layers that
- // aren't visible, so pass a non-fence.
- return fences.empty() ? Fence::NO_FENCE
- : fences.back().first.get();
- } else {
- return layerFE->stealCompositionResult()
- .releaseFences.back()
- .first.get();
- }
- });
- }
- }
+ ftl::SharedFuture<FenceResult> presentFuture = mRenderEngine->isThreaded()
+ ? ftl::yield(present()).share()
+ : mScheduler->schedule(std::move(present)).share();
return presentFuture;
}
@@ -7752,8 +8005,8 @@
const scheduler::RefreshRateSelector::Policy currentPolicy = selector.getCurrentPolicy();
ALOGV("Setting desired display mode specs: %s", currentPolicy.toString().c_str());
- if (const bool isPacesetter =
- mScheduler->onDisplayModeChanged(displayId, selector.getActiveMode())) {
+ if (mScheduler->onDisplayModeChanged(displayId, selector.getActiveMode(),
+ /*clearContentRequirements*/ true)) {
mDisplayModeController.updateKernelIdleTimer(displayId);
}
@@ -8142,6 +8395,22 @@
}));
}
+void SurfaceFlinger::addActivePictureListener(const sp<gui::IActivePictureListener>& listener) {
+ Mutex::Autolock lock(mStateLock);
+ std::erase_if(mActivePictureListenersToRemove, [listener](const auto& otherListener) {
+ return IInterface::asBinder(listener) == IInterface::asBinder(otherListener);
+ });
+ mActivePictureListenersToAdd.push_back(listener);
+}
+
+void SurfaceFlinger::removeActivePictureListener(const sp<gui::IActivePictureListener>& listener) {
+ Mutex::Autolock lock(mStateLock);
+ std::erase_if(mActivePictureListenersToAdd, [listener](const auto& otherListener) {
+ return IInterface::asBinder(listener) == IInterface::asBinder(otherListener);
+ });
+ mActivePictureListenersToRemove.push_back(listener);
+}
+
std::shared_ptr<renderengine::ExternalTexture> SurfaceFlinger::getExternalTextureFromBufferData(
BufferData& bufferData, const char* layerName, uint64_t transactionId) {
if (bufferData.buffer &&
@@ -8518,8 +8787,8 @@
if (status != OK) {
return binderStatusFromStatusT(status);
}
- const auto id = DisplayId::fromValue<PhysicalDisplayId>(static_cast<uint64_t>(displayId));
- *outDisplay = mFlinger->getPhysicalDisplayToken(*id);
+ const PhysicalDisplayId id = PhysicalDisplayId::fromValue(static_cast<uint64_t>(displayId));
+ *outDisplay = mFlinger->getPhysicalDisplayToken(id);
return binder::Status::ok();
}
@@ -8641,6 +8910,14 @@
outInfo->activeDisplayModeId = info.activeDisplayModeId;
outInfo->renderFrameRate = info.renderFrameRate;
outInfo->hasArrSupport = info.hasArrSupport;
+ gui::FrameRateCategoryRate& frameRateCategoryRate = outInfo->frameRateCategoryRate;
+ frameRateCategoryRate.normal = info.frameRateCategoryRate.getNormal();
+ frameRateCategoryRate.high = info.frameRateCategoryRate.getHigh();
+ outInfo->supportedRefreshRates.clear();
+ outInfo->supportedRefreshRates.reserve(info.supportedRefreshRates.size());
+ for (float supportedRefreshRate : info.supportedRefreshRates) {
+ outInfo->supportedRefreshRates.push_back(supportedRefreshRate);
+ }
outInfo->supportedColorModes.clear();
outInfo->supportedColorModes.reserve(info.supportedColorModes.size());
@@ -8796,6 +9073,16 @@
return binder::Status::ok();
}
+binder::Status SurfaceComposerAIDL::getMaxLayerPictureProfiles(const sp<IBinder>& display,
+ int32_t* outMaxProfiles) {
+ status_t status = checkAccessPermission();
+ if (status != OK) {
+ return binderStatusFromStatusT(status);
+ }
+ mFlinger->getMaxLayerPictureProfiles(display, outMaxProfiles);
+ return binder::Status::ok();
+}
+
binder::Status SurfaceComposerAIDL::captureDisplay(
const DisplayCaptureArgs& args, const sp<IScreenCaptureListener>& captureListener) {
mFlinger->captureDisplay(args, captureListener);
@@ -9074,6 +9361,24 @@
return binderStatusFromStatusT(status);
}
+binder::Status SurfaceComposerAIDL::addActivePictureListener(
+ const sp<gui::IActivePictureListener>& listener) {
+ status_t status = checkObservePictureProfilesPermission();
+ if (status == OK) {
+ mFlinger->addActivePictureListener(listener);
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::removeActivePictureListener(
+ const sp<gui::IActivePictureListener>& listener) {
+ status_t status = checkObservePictureProfilesPermission();
+ if (status == OK) {
+ mFlinger->removeActivePictureListener(listener);
+ }
+ return binderStatusFromStatusT(status);
+}
+
binder::Status SurfaceComposerAIDL::notifyPowerBoost(int boostId) {
status_t status = checkAccessPermission();
if (status == OK) {
@@ -9144,26 +9449,46 @@
}
binder::Status SurfaceComposerAIDL::enableRefreshRateOverlay(bool active) {
+ status_t status = checkAccessPermission();
+ if (status != OK) {
+ return binderStatusFromStatusT(status);
+ }
mFlinger->sfdo_enableRefreshRateOverlay(active);
return binder::Status::ok();
}
binder::Status SurfaceComposerAIDL::setDebugFlash(int delay) {
+ status_t status = checkAccessPermission();
+ if (status != OK) {
+ return binderStatusFromStatusT(status);
+ }
mFlinger->sfdo_setDebugFlash(delay);
return binder::Status::ok();
}
binder::Status SurfaceComposerAIDL::scheduleComposite() {
+ status_t status = checkAccessPermission();
+ if (status != OK) {
+ return binderStatusFromStatusT(status);
+ }
mFlinger->sfdo_scheduleComposite();
return binder::Status::ok();
}
binder::Status SurfaceComposerAIDL::scheduleCommit() {
+ status_t status = checkAccessPermission();
+ if (status != OK) {
+ return binderStatusFromStatusT(status);
+ }
mFlinger->sfdo_scheduleCommit();
return binder::Status::ok();
}
binder::Status SurfaceComposerAIDL::forceClientComposition(bool enabled) {
+ status_t status = checkAccessPermission();
+ if (status != OK) {
+ return binderStatusFromStatusT(status);
+ }
mFlinger->sfdo_forceClientComposition(enabled);
return binder::Status::ok();
}
@@ -9329,6 +9654,17 @@
return OK;
}
+status_t SurfaceComposerAIDL::checkObservePictureProfilesPermission() {
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+ if (!PermissionCache::checkPermission(sObservePictureProfiles, pid, uid)) {
+ ALOGE("Permission Denial: can't manage picture profiles pid=%d, uid=%d", pid, uid);
+ return PERMISSION_DENIED;
+ }
+ return OK;
+}
+
void SurfaceFlinger::forceFutureUpdate(int delayInMs) {
static_cast<void>(mScheduler->scheduleDelayed([&]() { scheduleRepaint(); }, ms2ns(delayInMs)));
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index db0e15e..3f454ba 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -24,9 +24,11 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/thread_annotations.h>
+#include <android/gui/ActivePicture.h>
#include <android/gui/BnSurfaceComposer.h>
#include <android/gui/DisplayStatInfo.h>
#include <android/gui/DisplayState.h>
+#include <android/gui/IActivePictureListener.h>
#include <android/gui/IJankListener.h>
#include <android/gui/ISurfaceComposerClient.h>
#include <common/trace.h>
@@ -57,6 +59,7 @@
#include <utils/threads.h>
#include <compositionengine/OutputColorSetting.h>
+#include <compositionengine/impl/OutputCompositionState.h>
#include <scheduler/Fps.h>
#include <scheduler/PresentLatencyTracker.h>
#include <scheduler/Time.h>
@@ -66,11 +69,13 @@
#include <ui/FenceResult.h>
#include <common/FlagManager.h>
+#include "ActivePictureTracker.h"
#include "Display/DisplayModeController.h"
#include "Display/PhysicalDisplay.h"
+#include "Display/VirtualDisplaySnapshot.h"
#include "DisplayDevice.h"
#include "DisplayHardware/HWC2.h"
-#include "DisplayHardware/PowerAdvisor.h"
+#include "DisplayHardware/HWComposer.h"
#include "DisplayIdGenerator.h"
#include "Effects/Daltonizer.h"
#include "FrontEnd/DisplayInfo.h"
@@ -81,6 +86,8 @@
#include "FrontEnd/TransactionHandler.h"
#include "LayerVector.h"
#include "MutexUtils.h"
+#include "PowerAdvisor/PowerAdvisor.h"
+#include "QueuedTransactionState.h"
#include "Scheduler/ISchedulerCallback.h"
#include "Scheduler/RefreshRateSelector.h"
#include "Scheduler/Scheduler.h"
@@ -89,18 +96,15 @@
#include "Tracing/LayerTracing.h"
#include "Tracing/TransactionTracing.h"
#include "TransactionCallbackInvoker.h"
-#include "TransactionState.h"
#include "Utils/OnceFuture.h"
+#include <algorithm>
#include <atomic>
#include <cstdint>
#include <functional>
-#include <map>
#include <memory>
#include <mutex>
#include <optional>
-#include <queue>
-#include <set>
#include <string>
#include <thread>
#include <type_traits>
@@ -123,13 +127,11 @@
class FpsReporter;
class TunnelModeEnabledReporter;
class HdrLayerInfoReporter;
-class HWComposer;
class IGraphicBufferProducer;
class Layer;
class MessageBase;
class RefreshRateOverlay;
class RegionSamplingThread;
-class RenderArea;
class TimeStats;
class FrameTracer;
class ScreenCapturer;
@@ -194,9 +196,6 @@
Always,
};
-struct DisplayRenderAreaBuilder;
-struct LayerRenderAreaBuilder;
-
using DisplayColorSetting = compositionengine::OutputColorSetting;
class SurfaceFlinger : public BnSurfaceComposer,
@@ -347,9 +346,6 @@
// We're reference counted, never destroy SurfaceFlinger directly
virtual ~SurfaceFlinger();
- virtual void processDisplayAdded(const wp<IBinder>& displayToken, const DisplayDeviceState&)
- REQUIRES(mStateLock);
-
virtual std::shared_ptr<renderengine::ExternalTexture> getExternalTextureFromBufferData(
BufferData& bufferData, const char* layerName, uint64_t transactionId);
@@ -371,9 +367,7 @@
friend class Layer;
friend class RefreshRateOverlay;
friend class RegionSamplingThread;
- friend class LayerRenderArea;
friend class SurfaceComposerAIDL;
- friend class DisplayRenderArea;
// For unit tests
friend class TestableSurfaceFlinger;
@@ -382,7 +376,6 @@
using TransactionSchedule = scheduler::TransactionSchedule;
using GetLayerSnapshotsFunction = std::function<std::vector<std::pair<Layer*, sp<LayerFE>>>()>;
- using RenderAreaBuilderVariant = std::variant<DisplayRenderAreaBuilder, LayerRenderAreaBuilder>;
using DumpArgs = Vector<String16>;
using Dumper = std::function<void(const DumpArgs&, bool asProto, std::string&)>;
@@ -590,6 +583,7 @@
status_t getHdrOutputConversionSupport(bool* outSupport) const;
void setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on);
void setGameContentType(const sp<IBinder>& displayToken, bool on);
+ status_t getMaxLayerPictureProfiles(const sp<IBinder>& displayToken, int32_t* outMaxProfiles);
void setPowerMode(const sp<IBinder>& displayToken, int mode);
status_t overrideHdrTypes(const sp<IBinder>& displayToken,
const std::vector<ui::Hdr>& hdrTypes);
@@ -659,6 +653,10 @@
void updateHdcpLevels(hal::HWDisplayId hwcDisplayId, int32_t connectedLevel, int32_t maxLevel);
+ void addActivePictureListener(const sp<gui::IActivePictureListener>& listener);
+
+ void removeActivePictureListener(const sp<gui::IActivePictureListener>& listener);
+
// IBinder::DeathRecipient overrides:
void binderDied(const wp<IBinder>& who) override;
@@ -691,7 +689,7 @@
void onChoreographerAttached() override;
void onExpectedPresentTimePosted(TimePoint expectedPresentTime, ftl::NonNull<DisplayModePtr>,
Fps renderRate) override;
- void onCommitNotComposited(PhysicalDisplayId pacesetterDisplayId) override
+ void onCommitNotComposited() override
REQUIRES(kMainThreadContext);
void vrrDisplayIdle(bool idle) override;
@@ -720,7 +718,11 @@
Fps maxFps);
void initiateDisplayModeChanges() REQUIRES(kMainThreadContext) REQUIRES(mStateLock);
- void finalizeDisplayModeChange(PhysicalDisplayId) REQUIRES(kMainThreadContext)
+
+ // Returns whether the commit stage should proceed. The return value is ignored when finalizing
+ // immediate mode changes, which happen toward the end of the commit stage.
+ // TODO: b/355427258 - Remove the return value once the `synced_resolution_switch` flag is live.
+ bool finalizeDisplayModeChange(PhysicalDisplayId) REQUIRES(kMainThreadContext)
REQUIRES(mStateLock);
void dropModeRequest(PhysicalDisplayId) REQUIRES(kMainThreadContext);
@@ -787,8 +789,9 @@
// For test only
bool flushTransactionQueues() REQUIRES(kMainThreadContext);
- bool applyTransactions(std::vector<TransactionState>&) REQUIRES(kMainThreadContext);
- bool applyAndCommitDisplayTransactionStatesLocked(std::vector<TransactionState>& transactions)
+ bool applyTransactions(std::vector<QueuedTransactionState>&) REQUIRES(kMainThreadContext);
+ bool applyAndCommitDisplayTransactionStatesLocked(
+ std::vector<QueuedTransactionState>& transactions)
REQUIRES(kMainThreadContext, mStateLock);
// Returns true if there is at least one transaction that needs to be flushed
@@ -817,7 +820,7 @@
static LatchUnsignaledConfig getLatchUnsignaledConfig();
bool shouldLatchUnsignaled(const layer_state_t&, size_t numStates, bool firstTransaction) const;
- bool applyTransactionsLocked(std::vector<TransactionState>& transactions)
+ bool applyTransactionsLocked(std::vector<QueuedTransactionState>& transactions)
REQUIRES(mStateLock, kMainThreadContext);
uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock);
uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands)
@@ -835,6 +838,9 @@
status_t createEffectLayer(const LayerCreationArgs& args, sp<IBinder>* outHandle,
sp<Layer>* outLayer);
+ // Checks if there are layer leaks before creating layer
+ status_t checkLayerLeaks();
+
status_t mirrorLayer(const LayerCreationArgs& args, const sp<IBinder>& mirrorFromHandle,
gui::CreateSurfaceResult& outResult);
@@ -851,47 +857,81 @@
void attachReleaseFenceFutureToLayer(Layer* layer, LayerFE* layerFE, ui::LayerStack layerStack);
// Checks if a protected layer exists in a list of layers.
- bool layersHasProtectedLayer(const std::vector<sp<LayerFE>>& layers) const;
+ bool layersHasProtectedLayer(const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const;
using OutputCompositionState = compositionengine::impl::OutputCompositionState;
- std::optional<OutputCompositionState> getSnapshotsFromMainThread(
- RenderAreaBuilderVariant& renderAreaBuilder,
- GetLayerSnapshotsFunction getLayerSnapshotsFn, std::vector<sp<LayerFE>>& layerFEs);
+ /*
+ * Parameters used across screenshot methods.
+ */
+ struct ScreenshotArgs {
+ // Contains the sequence ID of the parent layer if the screenshot is
+ // initiated though captureLayers(), or the display that the render
+ // result will be on if initiated through captureDisplay()
+ std::variant<int32_t, wp<const DisplayDevice>> captureTypeVariant;
- void captureScreenCommon(RenderAreaBuilderVariant, GetLayerSnapshotsFunction,
- ui::Size bufferSize, ui::PixelFormat, bool allowProtected,
- bool grayscale, bool attachGainmap, const sp<IScreenCaptureListener>&);
+ // Display ID of the display the result will be on
+ std::optional<DisplayId> displayId{std::nullopt};
- std::optional<OutputCompositionState> getDisplayStateFromRenderAreaBuilder(
- RenderAreaBuilderVariant& renderAreaBuilder) REQUIRES(kMainThreadContext);
+ // If true, transform is inverted from the parent layer snapshot
+ bool childrenOnly{false};
- // Legacy layer raw pointer is not safe to access outside the main thread.
- // Creates a new vector consisting only of LayerFEs, which can be safely
- // accessed outside the main thread.
- std::vector<sp<LayerFE>> extractLayerFEs(
- const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const;
+ // Source crop of the render area
+ Rect sourceCrop;
+
+ // Transform to be applied on the layers to transform them
+ // into the logical render area
+ ui::Transform transform;
+
+ // Size of the physical render area
+ ui::Size reqSize;
+
+ // Composition dataspace of the render area
+ ui::Dataspace dataspace;
+
+ // If false, the secure layer is blacked out or skipped
+ // when rendered to an insecure render area
+ bool isSecure{false};
+
+ // If true, the render result may be used for system animations
+ // that must preserve the exact colors of the display
+ bool seamlessTransition{false};
+
+ // Current display brightness of the output composition state
+ float displayBrightnessNits{-1.f};
+
+ // SDR white point of the output composition state
+ float sdrWhitePointNits{-1.f};
+
+ // Current active color mode of the output composition state
+ ui::ColorMode colorMode{ui::ColorMode::NATIVE};
+
+ // Current active render intent of the output composition state
+ ui::RenderIntent renderIntent{ui::RenderIntent::COLORIMETRIC};
+ };
+
+ bool getSnapshotsFromMainThread(ScreenshotArgs& args,
+ GetLayerSnapshotsFunction getLayerSnapshotsFn,
+ std::vector<std::pair<Layer*, sp<LayerFE>>>& layers);
+
+ void captureScreenCommon(ScreenshotArgs& args, GetLayerSnapshotsFunction, ui::Size bufferSize,
+ ui::PixelFormat, bool allowProtected, bool grayscale,
+ const sp<IScreenCaptureListener>&);
+
+ bool getDisplayStateOnMainThread(ScreenshotArgs& args) REQUIRES(kMainThreadContext);
ftl::SharedFuture<FenceResult> captureScreenshot(
- const RenderAreaBuilderVariant& renderAreaBuilder,
- const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
- bool grayscale, bool isProtected, bool attachGainmap,
+ ScreenshotArgs& args, const std::shared_ptr<renderengine::ExternalTexture>& buffer,
+ bool regionSampling, bool grayscale, bool isProtected,
const sp<IScreenCaptureListener>& captureListener,
- std::optional<OutputCompositionState>& displayState,
- std::vector<sp<LayerFE>>& layerFEs);
-
- ftl::SharedFuture<FenceResult> captureScreenshotLegacy(
- RenderAreaBuilderVariant, GetLayerSnapshotsFunction,
- const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling,
- bool grayscale, bool isProtected, bool attachGainmap,
- const sp<IScreenCaptureListener>&);
+ const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers,
+ const std::shared_ptr<renderengine::ExternalTexture>& hdrBuffer = nullptr,
+ const std::shared_ptr<renderengine::ExternalTexture>& gainmapBuffer = nullptr);
ftl::SharedFuture<FenceResult> renderScreenImpl(
- const RenderArea*, const std::shared_ptr<renderengine::ExternalTexture>&,
- bool regionSampling, bool grayscale, bool isProtected, bool attachGainmap,
- ScreenCaptureResults&, std::optional<OutputCompositionState>& displayState,
- std::vector<std::pair<Layer*, sp<LayerFE>>>& layers,
- std::vector<sp<LayerFE>>& layerFEs);
+ ScreenshotArgs& args, const std::shared_ptr<renderengine::ExternalTexture>&,
+ bool regionSampling, bool grayscale, bool isProtected, ScreenCaptureResults&,
+ const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers);
void readPersistentProperties();
@@ -1039,6 +1079,8 @@
const sp<compositionengine::DisplaySurface>& displaySurface,
const sp<IGraphicBufferProducer>& producer) REQUIRES(mStateLock);
void processDisplayChangesLocked() REQUIRES(mStateLock, kMainThreadContext);
+ void processDisplayAdded(const wp<IBinder>& displayToken, const DisplayDeviceState&)
+ REQUIRES(mStateLock, kMainThreadContext);
void processDisplayRemoved(const wp<IBinder>& displayToken)
REQUIRES(mStateLock, kMainThreadContext);
void processDisplayChanged(const wp<IBinder>& displayToken,
@@ -1078,8 +1120,20 @@
void enableHalVirtualDisplays(bool);
// Virtual display lifecycle for ID generation and HAL allocation.
- VirtualDisplayId acquireVirtualDisplay(ui::Size, ui::PixelFormat) REQUIRES(mStateLock);
+ VirtualDisplayId acquireVirtualDisplay(ui::Size, ui::PixelFormat, const std::string& uniqueId)
+ REQUIRES(mStateLock);
+ template <typename ID>
+ void acquireVirtualDisplaySnapshot(ID displayId, const std::string& uniqueId) {
+ std::lock_guard lock(mVirtualDisplaysMutex);
+ const bool emplace_success =
+ mVirtualDisplays.try_emplace(displayId, displayId, uniqueId).second;
+ if (!emplace_success) {
+ ALOGW("%s: Virtual display snapshot with the same ID already exists", __func__);
+ }
+ }
+
void releaseVirtualDisplay(VirtualDisplayId);
+ void releaseVirtualDisplaySnapshot(VirtualDisplayId displayId);
// Returns a display other than `mActiveDisplayId` that can be activated, if any.
sp<DisplayDevice> getActivatableDisplay() const REQUIRES(mStateLock, kMainThreadContext);
@@ -1221,6 +1275,14 @@
bool mHdrLayerInfoChanged = false;
+ struct LayerEvent {
+ uid_t uid;
+ int32_t layerId;
+ ui::Dataspace dataspace;
+ std::chrono::milliseconds timeSinceLastEvent;
+ };
+ std::vector<LayerEvent> mLayerEvents;
+
// Used to ensure we omit a callback when HDR layer info listener is newly added but the
// scene hasn't changed
bool mAddingHDRLayerInfoListener = false;
@@ -1245,7 +1307,6 @@
// latched.
std::unordered_set<std::pair<sp<Layer>, gui::GameMode>, LayerIntHash> mLayersWithQueuedFrames;
std::unordered_set<sp<Layer>, SpHash<Layer>> mLayersWithBuffersRemoved;
- std::unordered_set<uint32_t> mLayersIdsWithQueuedFrames;
// Sorted list of layers that were composed during previous frame. This is used to
// avoid an expensive traversal of the layer hierarchy when there are no
@@ -1257,7 +1318,7 @@
struct HotplugEvent {
hal::HWDisplayId hwcDisplayId;
- hal::Connection connection = hal::Connection::INVALID;
+ HWComposer::HotplugEvent event;
};
bool mIsHdcpViaNegVsync = false;
@@ -1273,6 +1334,10 @@
display::PhysicalDisplays mPhysicalDisplays GUARDED_BY(mStateLock);
+ mutable std::mutex mVirtualDisplaysMutex;
+ ftl::SmallMap<VirtualDisplayId, const display::VirtualDisplaySnapshot, 2> mVirtualDisplays
+ GUARDED_BY(mVirtualDisplaysMutex);
+
// The inner or outer display for foldables, while unfolded or folded, respectively.
std::atomic<PhysicalDisplayId> mActiveDisplayId;
@@ -1339,6 +1404,7 @@
std::atomic<int> mNumTrustedPresentationListeners = 0;
std::unique_ptr<compositionengine::CompositionEngine> mCompositionEngine;
+ std::unique_ptr<HWComposer> mHWComposer;
CompositionCoveragePerDisplay mCompositionCoverage;
@@ -1365,7 +1431,7 @@
sp<os::IInputFlinger> mInputFlinger;
InputWindowCommands mInputWindowCommands;
- std::unique_ptr<Hwc2::PowerAdvisor> mPowerAdvisor;
+ std::unique_ptr<adpf::PowerAdvisor> mPowerAdvisor;
void enableRefreshRateOverlay(bool enable) REQUIRES(mStateLock, kMainThreadContext);
@@ -1374,11 +1440,17 @@
// Flag used to set override desired display mode from backdoor
bool mDebugDisplayModeSetByBackdoor = false;
+ // Tracks the number of maximum queued buffers by layer owner Uid.
+ using BufferStuffingMap = ftl::SmallMap<uid_t, uint32_t, 10>;
BufferCountTracker mBufferCountTracker;
std::unordered_map<DisplayId, sp<HdrLayerInfoReporter>> mHdrLayerInfoListeners
GUARDED_BY(mStateLock);
+ ActivePictureTracker mActivePictureTracker GUARDED_BY(kMainThreadContext);
+ ActivePictureTracker::Listeners mActivePictureListenersToAdd GUARDED_BY(mStateLock);
+ ActivePictureTracker::Listeners mActivePictureListenersToRemove GUARDED_BY(mStateLock);
+
std::atomic<ui::Transform::RotationFlags> mActiveDisplayTransformHint;
// Must only be accessed on the main thread.
@@ -1415,6 +1487,11 @@
// Whether a display should be turned on when initialized
bool mSkipPowerOnForQuiescent;
+ // used for omitting vsync callbacks to apps when the display is not updatable
+ int mRefreshableDisplays GUARDED_BY(mStateLock) = 0;
+ void incRefreshableDisplays() REQUIRES(mStateLock);
+ void decRefreshableDisplays() REQUIRES(mStateLock);
+
frontend::LayerLifecycleManager mLayerLifecycleManager GUARDED_BY(kMainThreadContext);
frontend::LayerHierarchyBuilder mLayerHierarchyBuilder GUARDED_BY(kMainThreadContext);
frontend::LayerSnapshotBuilder mLayerSnapshotBuilder GUARDED_BY(kMainThreadContext);
@@ -1519,6 +1596,8 @@
binder::Status getHdrOutputConversionSupport(bool* outSupport) override;
binder::Status setAutoLowLatencyMode(const sp<IBinder>& display, bool on) override;
binder::Status setGameContentType(const sp<IBinder>& display, bool on) override;
+ binder::Status getMaxLayerPictureProfiles(const sp<IBinder>& display,
+ int32_t* outMaxProfiles) override;
binder::Status captureDisplay(const DisplayCaptureArgs&,
const sp<IScreenCaptureListener>&) override;
binder::Status captureDisplayById(int64_t, const CaptureArgs&,
@@ -1607,12 +1686,15 @@
binder::Status flushJankData(int32_t layerId) override;
binder::Status removeJankListener(int32_t layerId, const sp<gui::IJankListener>& listener,
int64_t afterVsync) override;
+ binder::Status addActivePictureListener(const sp<gui::IActivePictureListener>& listener);
+ binder::Status removeActivePictureListener(const sp<gui::IActivePictureListener>& listener);
private:
static const constexpr bool kUsePermissionCache = true;
status_t checkAccessPermission(bool usePermissionCache = kUsePermissionCache);
status_t checkControlDisplayBrightnessPermission();
status_t checkReadFrameBufferPermission();
+ status_t checkObservePictureProfilesPermission();
static void getDynamicDisplayInfoInternal(ui::DynamicDisplayInfo& info,
gui::DynamicDisplayInfo*& outInfo);
diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
index f39a4d2..2676ca6 100644
--- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
+++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
@@ -20,8 +20,8 @@
#include "FrontEnd/LayerCreationArgs.h"
#include "LayerProtoHelper.h"
+#include "QueuedTransactionState.h"
#include "TransactionProtoParser.h"
-#include "TransactionState.h"
#include "gui/LayerState.h"
namespace android::surfaceflinger {
@@ -51,7 +51,8 @@
~FakeExternalTexture() = default;
};
-perfetto::protos::TransactionState TransactionProtoParser::toProto(const TransactionState& t) {
+perfetto::protos::TransactionState TransactionProtoParser::toProto(
+ const QueuedTransactionState& t) {
perfetto::protos::TransactionState proto;
proto.set_pid(t.originPid);
proto.set_uid(t.originUid);
@@ -300,9 +301,9 @@
return proto;
}
-TransactionState TransactionProtoParser::fromProto(
+QueuedTransactionState TransactionProtoParser::fromProto(
const perfetto::protos::TransactionState& proto) {
- TransactionState t;
+ QueuedTransactionState t;
t.originPid = proto.pid();
t.originUid = proto.uid();
t.frameTimelineInfo.vsyncId = proto.vsync_id();
diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.h b/services/surfaceflinger/Tracing/TransactionProtoParser.h
index b3ab71c..a02e231 100644
--- a/services/surfaceflinger/Tracing/TransactionProtoParser.h
+++ b/services/surfaceflinger/Tracing/TransactionProtoParser.h
@@ -21,7 +21,7 @@
#include "FrontEnd/DisplayInfo.h"
#include "FrontEnd/LayerCreationArgs.h"
-#include "TransactionState.h"
+#include "QueuedTransactionState.h"
namespace android::surfaceflinger {
@@ -44,14 +44,14 @@
TransactionProtoParser(std::unique_ptr<FlingerDataMapper> provider)
: mMapper(std::move(provider)) {}
- perfetto::protos::TransactionState toProto(const TransactionState&);
+ perfetto::protos::TransactionState toProto(const QueuedTransactionState&);
perfetto::protos::TransactionState toProto(
const std::map<uint32_t /* layerId */, TracingLayerState>&);
perfetto::protos::LayerCreationArgs toProto(const LayerCreationArgs& args);
perfetto::protos::LayerState toProto(const ResolvedComposerState&);
static perfetto::protos::DisplayInfo toProto(const frontend::DisplayInfo&, uint32_t layerStack);
- TransactionState fromProto(const perfetto::protos::TransactionState&);
+ QueuedTransactionState fromProto(const perfetto::protos::TransactionState&);
void mergeFromProto(const perfetto::protos::LayerState&, TracingLayerState& outState);
void fromProto(const perfetto::protos::LayerCreationArgs&, LayerCreationArgs& outArgs);
std::unique_ptr<FlingerDataMapper> mMapper;
diff --git a/services/surfaceflinger/Tracing/TransactionTracing.cpp b/services/surfaceflinger/Tracing/TransactionTracing.cpp
index bc9f809..1cd7517 100644
--- a/services/surfaceflinger/Tracing/TransactionTracing.cpp
+++ b/services/surfaceflinger/Tracing/TransactionTracing.cpp
@@ -166,7 +166,7 @@
mBuffer.dump(result);
}
-void TransactionTracing::addQueuedTransaction(const TransactionState& transaction) {
+void TransactionTracing::addQueuedTransaction(const QueuedTransactionState& transaction) {
perfetto::protos::TransactionState* state =
new perfetto::protos::TransactionState(mProtoParser.toProto(transaction));
mTransactionQueue.push(state);
diff --git a/services/surfaceflinger/Tracing/TransactionTracing.h b/services/surfaceflinger/Tracing/TransactionTracing.h
index 7a0fb5e..d784168 100644
--- a/services/surfaceflinger/Tracing/TransactionTracing.h
+++ b/services/surfaceflinger/Tracing/TransactionTracing.h
@@ -134,7 +134,7 @@
// Flush event from perfetto data source
void onFlush(Mode mode);
- void addQueuedTransaction(const TransactionState&);
+ void addQueuedTransaction(const QueuedTransactionState&);
void addCommittedTransactions(int64_t vsyncId, nsecs_t commitTime, frontend::Update& update,
const frontend::DisplayInfos&, bool displayInfoChanged);
status_t writeToFile(const std::string& filename = FILE_PATH);
diff --git a/services/surfaceflinger/Tracing/tools/Android.bp b/services/surfaceflinger/Tracing/tools/Android.bp
index 63c1b37..d2ffcc0 100644
--- a/services/surfaceflinger/Tracing/tools/Android.bp
+++ b/services/surfaceflinger/Tracing/tools/Android.bp
@@ -27,6 +27,7 @@
defaults: [
"libsurfaceflinger_mocks_defaults",
"librenderengine_deps",
+ "poweradvisor_deps",
"surfaceflinger_defaults",
"libsurfaceflinger_common_deps",
],
diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
index 1dba175..5cf4244 100644
--- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
+++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
@@ -31,8 +31,8 @@
#include "FrontEnd/LayerCreationArgs.h"
#include "FrontEnd/RequestedLayerState.h"
#include "LayerProtoHelper.h"
+#include "QueuedTransactionState.h"
#include "Tracing/LayerTracing.h"
-#include "TransactionState.h"
#include "cutils/properties.h"
#include "LayerTraceGenerator.h"
@@ -95,11 +95,11 @@
addedLayers.emplace_back(std::make_unique<frontend::RequestedLayerState>(args));
}
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.reserve((size_t)entry.transactions_size());
for (int j = 0; j < entry.transactions_size(); j++) {
// apply transactions
- TransactionState transaction = parser.fromProto(entry.transactions(j));
+ QueuedTransactionState transaction = parser.fromProto(entry.transactions(j));
for (auto& resolvedComposerState : transaction.states) {
if (resolvedComposerState.state.what & layer_state_t::eInputInfoChanged) {
if (!resolvedComposerState.state.windowInfoHandle->getInfo()->inputConfig.test(
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp
index c6856ae..b22ec66 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.cpp
+++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp
@@ -28,7 +28,6 @@
#include "Utils/FenceUtils.h"
#include <binder/IInterface.h>
-#include <common/FlagManager.h>
#include <common/trace.h>
#include <utils/RefBase.h>
@@ -127,14 +126,8 @@
if (surfaceControl) {
sp<Fence> prevFence = nullptr;
- if (FlagManager::getInstance().ce_fence_promise()) {
- for (auto& future : handle->previousReleaseFences) {
- mergeFence(handle->name.c_str(), future.get().value_or(Fence::NO_FENCE), prevFence);
- }
- } else {
- for (const auto& future : handle->previousSharedReleaseFences) {
- mergeFence(handle->name.c_str(), future.get().value_or(Fence::NO_FENCE), prevFence);
- }
+ for (auto& future : handle->previousReleaseFences) {
+ mergeFence(handle->name.c_str(), future.get().value_or(Fence::NO_FENCE), prevFence);
}
handle->previousReleaseFence = prevFence;
@@ -151,7 +144,7 @@
eventStats, handle->previousReleaseCallbackId);
if (handle->bufferReleaseChannel &&
handle->previousReleaseCallbackId != ReleaseCallbackId::INVALID_ID) {
- mBufferReleases.emplace_back(handle->bufferReleaseChannel,
+ mBufferReleases.emplace_back(handle->name, handle->bufferReleaseChannel,
handle->previousReleaseCallbackId,
handle->previousReleaseFence,
handle->currentMaxAcquiredBufferCount);
@@ -166,8 +159,13 @@
void TransactionCallbackInvoker::sendCallbacks(bool onCommitOnly) {
for (const auto& bufferRelease : mBufferReleases) {
- bufferRelease.channel->writeReleaseFence(bufferRelease.callbackId, bufferRelease.fence,
- bufferRelease.currentMaxAcquiredBufferCount);
+ status_t status = bufferRelease.channel
+ ->writeReleaseFence(bufferRelease.callbackId, bufferRelease.fence,
+ bufferRelease.currentMaxAcquiredBufferCount);
+ if (status != OK) {
+ ALOGE("[%s] writeReleaseFence failed. error %d (%s)", bufferRelease.layerName.c_str(),
+ -status, strerror(-status));
+ }
}
mBufferReleases.clear();
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h
index 14a7487..178ddbb 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.h
+++ b/services/surfaceflinger/TransactionCallbackInvoker.h
@@ -43,7 +43,6 @@
std::string name;
sp<Fence> previousReleaseFence;
std::vector<ftl::Future<FenceResult>> previousReleaseFences;
- std::vector<ftl::SharedFuture<FenceResult>> previousSharedReleaseFences;
std::variant<nsecs_t, sp<Fence>> acquireTimeOrFence = -1;
nsecs_t latchTime = -1;
std::optional<uint32_t> transformHint = std::nullopt;
@@ -84,6 +83,7 @@
mCompletedTransactions;
struct BufferRelease {
+ std::string layerName;
std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint> channel;
ReleaseCallbackId callbackId;
sp<Fence> fence;
diff --git a/services/surfaceflinger/common/Android.bp b/services/surfaceflinger/common/Android.bp
index f9c99bf..8786f6e 100644
--- a/services/surfaceflinger/common/Android.bp
+++ b/services/surfaceflinger/common/Android.bp
@@ -38,6 +38,7 @@
],
static_libs: [
"libsurfaceflingerflags",
+ "aconfig_hardware_flags_c_lib",
"android.os.flags-aconfig-cc",
"android.server.display.flags-aconfig-cc",
"libguiflags_no_apex",
@@ -51,6 +52,7 @@
],
static_libs: [
"libsurfaceflingerflags_test",
+ "aconfig_hardware_flags_c_lib",
"android.os.flags-aconfig-cc-test",
"android.server.display.flags-aconfig-cc",
"libguiflags_no_apex",
@@ -67,6 +69,7 @@
static_libs: [
"libsurfaceflinger_common",
"libsurfaceflingerflags",
+ "aconfig_hardware_flags_c_lib",
"android.os.flags-aconfig-cc",
"android.server.display.flags-aconfig-cc",
"libguiflags_no_apex",
@@ -83,6 +86,7 @@
static_libs: [
"libsurfaceflinger_common_test",
"libsurfaceflingerflags_test",
+ "aconfig_hardware_flags_c_lib",
"android.os.flags-aconfig-cc-test",
"android.server.display.flags-aconfig-cc",
"libguiflags_no_apex",
diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp
index 12d6138..abde524 100644
--- a/services/surfaceflinger/common/FlagManager.cpp
+++ b/services/surfaceflinger/common/FlagManager.cpp
@@ -27,6 +27,7 @@
#include <cinttypes>
#include <android_os.h>
+#include <android_hardware_flags.h>
#include <com_android_graphics_libgui_flags.h>
#include <com_android_graphics_surfaceflinger_flags.h>
#include <com_android_server_display_feature_flags.h>
@@ -89,9 +90,9 @@
mBootCompleted = true;
}
-void FlagManager::dumpFlag(std::string& result, bool readonly, const char* name,
+void FlagManager::dumpFlag(std::string& result, bool aconfig, const char* name,
std::function<bool()> getter) const {
- if (readonly || mBootCompleted) {
+ if (aconfig || mBootCompleted) {
base::StringAppendF(&result, "%s: %s\n", name, getter() ? "true" : "false");
} else {
base::StringAppendF(&result, "%s: in progress (still booting)\n", name);
@@ -99,67 +100,91 @@
}
void FlagManager::dump(std::string& result) const {
-#define DUMP_FLAG_INTERVAL(name, readonly) \
- dumpFlag(result, (readonly), #name, std::bind(&FlagManager::name, this))
-#define DUMP_SERVER_FLAG(name) DUMP_FLAG_INTERVAL(name, false)
-#define DUMP_READ_ONLY_FLAG(name) DUMP_FLAG_INTERVAL(name, true)
+#define DUMP_FLAG_INTERNAL(name, aconfig) \
+ dumpFlag(result, (aconfig), #name, std::bind(&FlagManager::name, this))
+#define DUMP_LEGACY_SERVER_FLAG(name) DUMP_FLAG_INTERNAL(name, false)
+#define DUMP_ACONFIG_FLAG(name) DUMP_FLAG_INTERNAL(name, true)
+#define DUMP_SYSPROP_FLAG(name) \
+ dumpFlag(result, (true), "debug.sf." #name, std::bind(&FlagManager::name, this))
base::StringAppendF(&result, "FlagManager values: \n");
- /// Legacy server flags ///
- DUMP_SERVER_FLAG(use_adpf_cpu_hint);
- DUMP_SERVER_FLAG(use_skia_tracing);
+ /// Sysprop flags ///
+ DUMP_SYSPROP_FLAG(disable_sched_fifo_sf);
+ DUMP_SYSPROP_FLAG(disable_sched_fifo_sf_binder);
+ DUMP_SYSPROP_FLAG(disable_sched_fifo_sf_sched);
+ DUMP_SYSPROP_FLAG(disable_sched_fifo_re);
+ DUMP_SYSPROP_FLAG(disable_sched_fifo_composer);
+ DUMP_SYSPROP_FLAG(disable_sched_fifo_composer_callback);
- /// Trunk stable server flags ///
- DUMP_SERVER_FLAG(refresh_rate_overlay_on_external_display);
- DUMP_SERVER_FLAG(adpf_gpu_sf);
- DUMP_SERVER_FLAG(adpf_use_fmq_channel);
+ /// Legacy server flags ///
+ DUMP_LEGACY_SERVER_FLAG(use_adpf_cpu_hint);
+ DUMP_LEGACY_SERVER_FLAG(use_skia_tracing);
+
+ /// Trunk stable server (R/W) flags ///
+ DUMP_ACONFIG_FLAG(adpf_gpu_sf);
+ DUMP_ACONFIG_FLAG(adpf_native_session_manager);
+ DUMP_ACONFIG_FLAG(adpf_use_fmq_channel);
+ DUMP_ACONFIG_FLAG(graphite_renderengine_preview_rollout);
+ DUMP_ACONFIG_FLAG(increase_missed_frame_jank_threshold);
+ DUMP_ACONFIG_FLAG(refresh_rate_overlay_on_external_display);
+ DUMP_ACONFIG_FLAG(vsync_predictor_recovery);
/// Trunk stable readonly flags ///
- DUMP_READ_ONLY_FLAG(connected_display);
- DUMP_READ_ONLY_FLAG(enable_small_area_detection);
- DUMP_READ_ONLY_FLAG(frame_rate_category_mrr);
- DUMP_READ_ONLY_FLAG(misc1);
- DUMP_READ_ONLY_FLAG(vrr_config);
- DUMP_READ_ONLY_FLAG(hotplug2);
- DUMP_READ_ONLY_FLAG(hdcp_level_hal);
- DUMP_READ_ONLY_FLAG(multithreaded_present);
- DUMP_READ_ONLY_FLAG(add_sf_skipped_frames_to_trace);
- DUMP_READ_ONLY_FLAG(use_known_refresh_rate_for_fps_consistency);
- DUMP_READ_ONLY_FLAG(cache_when_source_crop_layer_only_moved);
- DUMP_READ_ONLY_FLAG(enable_fro_dependent_features);
- DUMP_READ_ONLY_FLAG(display_protected);
- DUMP_READ_ONLY_FLAG(fp16_client_target);
- DUMP_READ_ONLY_FLAG(game_default_frame_rate);
- DUMP_READ_ONLY_FLAG(enable_layer_command_batching);
- DUMP_READ_ONLY_FLAG(screenshot_fence_preservation);
- DUMP_READ_ONLY_FLAG(vulkan_renderengine);
- DUMP_READ_ONLY_FLAG(renderable_buffer_usage);
- DUMP_READ_ONLY_FLAG(vrr_bugfix_24q4);
- DUMP_READ_ONLY_FLAG(vrr_bugfix_dropped_frame);
- DUMP_READ_ONLY_FLAG(restore_blur_step);
- DUMP_READ_ONLY_FLAG(dont_skip_on_early_ro);
- DUMP_READ_ONLY_FLAG(protected_if_client);
- DUMP_READ_ONLY_FLAG(ce_fence_promise);
- DUMP_READ_ONLY_FLAG(idle_screen_refresh_rate_timeout);
- DUMP_READ_ONLY_FLAG(graphite_renderengine);
- DUMP_READ_ONLY_FLAG(filter_frames_before_trace_starts);
- DUMP_READ_ONLY_FLAG(latch_unsignaled_with_auto_refresh_changed);
- DUMP_READ_ONLY_FLAG(deprecate_vsync_sf);
- DUMP_READ_ONLY_FLAG(allow_n_vsyncs_in_targeter);
- DUMP_READ_ONLY_FLAG(detached_mirror);
- DUMP_READ_ONLY_FLAG(commit_not_composited);
- DUMP_READ_ONLY_FLAG(correct_dpi_with_display_size);
- DUMP_READ_ONLY_FLAG(local_tonemap_screenshots);
- DUMP_READ_ONLY_FLAG(override_trusted_overlay);
- DUMP_READ_ONLY_FLAG(flush_buffer_slots_to_uncache);
- DUMP_READ_ONLY_FLAG(force_compile_graphite_renderengine);
- DUMP_READ_ONLY_FLAG(single_hop_screenshot);
- DUMP_READ_ONLY_FLAG(trace_frame_rate_override);
- DUMP_READ_ONLY_FLAG(true_hdr_screenshots);
+ /// IMPORTANT - please keep alphabetize to reduce merge conflicts
+ DUMP_ACONFIG_FLAG(add_sf_skipped_frames_to_trace);
+ DUMP_ACONFIG_FLAG(adpf_fmq_sf);
+ DUMP_ACONFIG_FLAG(allow_n_vsyncs_in_targeter);
+ DUMP_ACONFIG_FLAG(arr_setframerate_gte_enum);
+ DUMP_ACONFIG_FLAG(begone_bright_hlg);
+ DUMP_ACONFIG_FLAG(cache_when_source_crop_layer_only_moved);
+ DUMP_ACONFIG_FLAG(commit_not_composited);
+ DUMP_ACONFIG_FLAG(connected_display);
+ DUMP_ACONFIG_FLAG(connected_display_hdr);
+ DUMP_ACONFIG_FLAG(correct_dpi_with_display_size);
+ DUMP_ACONFIG_FLAG(deprecate_frame_tracker);
+ DUMP_ACONFIG_FLAG(deprecate_vsync_sf);
+ DUMP_ACONFIG_FLAG(detached_mirror);
+ DUMP_ACONFIG_FLAG(display_config_error_hal);
+ DUMP_ACONFIG_FLAG(display_protected);
+ DUMP_ACONFIG_FLAG(dont_skip_on_early_ro);
+ DUMP_ACONFIG_FLAG(enable_fro_dependent_features);
+ DUMP_ACONFIG_FLAG(enable_layer_command_batching);
+ DUMP_ACONFIG_FLAG(enable_small_area_detection);
+ DUMP_ACONFIG_FLAG(filter_frames_before_trace_starts);
+ DUMP_ACONFIG_FLAG(flush_buffer_slots_to_uncache);
+ DUMP_ACONFIG_FLAG(force_compile_graphite_renderengine);
+ DUMP_ACONFIG_FLAG(fp16_client_target);
+ DUMP_ACONFIG_FLAG(frame_rate_category_mrr);
+ DUMP_ACONFIG_FLAG(game_default_frame_rate);
+ DUMP_ACONFIG_FLAG(graphite_renderengine);
+ DUMP_ACONFIG_FLAG(hdcp_level_hal);
+ DUMP_ACONFIG_FLAG(idle_screen_refresh_rate_timeout);
+ DUMP_ACONFIG_FLAG(latch_unsignaled_with_auto_refresh_changed);
+ DUMP_ACONFIG_FLAG(local_tonemap_screenshots);
+ DUMP_ACONFIG_FLAG(misc1);
+ DUMP_ACONFIG_FLAG(multithreaded_present);
+ DUMP_ACONFIG_FLAG(no_vsyncs_on_screen_off);
+ DUMP_ACONFIG_FLAG(override_trusted_overlay);
+ DUMP_ACONFIG_FLAG(protected_if_client);
+ DUMP_ACONFIG_FLAG(reject_dupe_layerstacks);
+ DUMP_ACONFIG_FLAG(renderable_buffer_usage);
+ DUMP_ACONFIG_FLAG(restore_blur_step);
+ DUMP_ACONFIG_FLAG(skip_invisible_windows_in_input);
+ DUMP_ACONFIG_FLAG(stable_edid_ids);
+ DUMP_ACONFIG_FLAG(synced_resolution_switch);
+ DUMP_ACONFIG_FLAG(trace_frame_rate_override);
+ DUMP_ACONFIG_FLAG(true_hdr_screenshots);
+ DUMP_ACONFIG_FLAG(use_known_refresh_rate_for_fps_consistency);
+ DUMP_ACONFIG_FLAG(vrr_bugfix_24q4);
+ DUMP_ACONFIG_FLAG(vrr_bugfix_dropped_frame);
+ DUMP_ACONFIG_FLAG(vrr_config);
+ DUMP_ACONFIG_FLAG(vulkan_renderengine);
+ DUMP_ACONFIG_FLAG(window_blur_kawase2);
+ /// IMPORTANT - please keep alphabetize to reduce merge conflicts
-#undef DUMP_READ_ONLY_FLAG
-#undef DUMP_SERVER_FLAG
+#undef DUMP_ACONFIG_FLAG
+#undef DUMP_LEGACY_SERVER_FLAG
#undef DUMP_FLAG_INTERVAL
}
@@ -173,6 +198,12 @@
const auto res = parseBool(value.c_str());
return res.has_value() && res.value();
}
+#define FLAG_MANAGER_SYSPROP_FLAG(name, defaultVal) \
+ bool FlagManager::name() const { \
+ static const bool kFlagValue = \
+ base::GetBoolProperty("debug.sf." #name, /* default value*/ defaultVal); \
+ return kFlagValue; \
+ }
#define FLAG_MANAGER_LEGACY_SERVER_FLAG(name, syspropOverride, serverFlagName) \
bool FlagManager::name() const { \
@@ -184,35 +215,32 @@
return getServerConfigurableFlag(serverFlagName); \
}
-#define FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, checkForBootCompleted, owner) \
- bool FlagManager::name() const { \
- if (checkForBootCompleted) { \
- LOG_ALWAYS_FATAL_IF(!mBootCompleted, \
- "Can't read %s before boot completed as it is server writable", \
- __func__); \
- } \
- static const std::optional<bool> debugOverride = getBoolProperty(syspropOverride); \
- static const bool value = getFlagValue([] { return owner ::name(); }, debugOverride); \
- if (mUnitTestMode) { \
- /* \
- * When testing, we don't want to rely on the cached `value` or the debugOverride. \
- */ \
- return owner ::name(); \
- } \
- return value; \
+#define FLAG_MANAGER_ACONFIG_INTERNAL(name, syspropOverride, owner) \
+ bool FlagManager::name() const { \
+ static const std::optional<bool> debugOverride = getBoolProperty(syspropOverride); \
+ static const bool value = getFlagValue([] { return owner ::name(); }, debugOverride); \
+ if (mUnitTestMode) { \
+ /* \
+ * When testing, we don't want to rely on the cached `value` or the debugOverride. \
+ */ \
+ return owner ::name(); \
+ } \
+ return value; \
}
-#define FLAG_MANAGER_SERVER_FLAG(name, syspropOverride) \
- FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, true, flags)
+#define FLAG_MANAGER_ACONFIG_FLAG(name, syspropOverride) \
+ FLAG_MANAGER_ACONFIG_INTERNAL(name, syspropOverride, flags)
-#define FLAG_MANAGER_READ_ONLY_FLAG(name, syspropOverride) \
- FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, false, flags)
+#define FLAG_MANAGER_ACONFIG_FLAG_IMPORTED(name, syspropOverride, owner) \
+ FLAG_MANAGER_ACONFIG_INTERNAL(name, syspropOverride, owner)
-#define FLAG_MANAGER_SERVER_FLAG_IMPORTED(name, syspropOverride, owner) \
- FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, true, owner)
-
-#define FLAG_MANAGER_READ_ONLY_FLAG_IMPORTED(name, syspropOverride, owner) \
- FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, false, owner)
+/// Debug sysprop flags - default value is always false ///
+FLAG_MANAGER_SYSPROP_FLAG(disable_sched_fifo_sf, /* default */ false)
+FLAG_MANAGER_SYSPROP_FLAG(disable_sched_fifo_sf_binder, /* default */ false)
+FLAG_MANAGER_SYSPROP_FLAG(disable_sched_fifo_sf_sched, /* default */ false)
+FLAG_MANAGER_SYSPROP_FLAG(disable_sched_fifo_re, /* default */ false)
+FLAG_MANAGER_SYSPROP_FLAG(disable_sched_fifo_composer, /* default */ false)
+FLAG_MANAGER_SYSPROP_FLAG(disable_sched_fifo_composer_callback, /* default */ false)
/// Legacy server flags ///
FLAG_MANAGER_LEGACY_SERVER_FLAG(test_flag, "", "")
@@ -222,59 +250,72 @@
"SkiaTracingFeature__use_skia_tracing")
/// Trunk stable readonly flags ///
-FLAG_MANAGER_READ_ONLY_FLAG(connected_display, "")
-FLAG_MANAGER_READ_ONLY_FLAG(enable_small_area_detection, "")
-FLAG_MANAGER_READ_ONLY_FLAG(frame_rate_category_mrr, "debug.sf.frame_rate_category_mrr")
-FLAG_MANAGER_READ_ONLY_FLAG(misc1, "")
-FLAG_MANAGER_READ_ONLY_FLAG(vrr_config, "debug.sf.enable_vrr_config")
-FLAG_MANAGER_READ_ONLY_FLAG(hotplug2, "")
-FLAG_MANAGER_READ_ONLY_FLAG(hdcp_level_hal, "")
-FLAG_MANAGER_READ_ONLY_FLAG(multithreaded_present, "debug.sf.multithreaded_present")
-FLAG_MANAGER_READ_ONLY_FLAG(add_sf_skipped_frames_to_trace, "")
-FLAG_MANAGER_READ_ONLY_FLAG(use_known_refresh_rate_for_fps_consistency, "")
-FLAG_MANAGER_READ_ONLY_FLAG(cache_when_source_crop_layer_only_moved,
- "debug.sf.cache_source_crop_only_moved")
-FLAG_MANAGER_READ_ONLY_FLAG(enable_fro_dependent_features, "")
-FLAG_MANAGER_READ_ONLY_FLAG(display_protected, "")
-FLAG_MANAGER_READ_ONLY_FLAG(fp16_client_target, "debug.sf.fp16_client_target")
-FLAG_MANAGER_READ_ONLY_FLAG(game_default_frame_rate, "")
-FLAG_MANAGER_READ_ONLY_FLAG(enable_layer_command_batching, "debug.sf.enable_layer_command_batching")
-FLAG_MANAGER_READ_ONLY_FLAG(screenshot_fence_preservation, "debug.sf.screenshot_fence_preservation")
-FLAG_MANAGER_READ_ONLY_FLAG(vulkan_renderengine, "debug.renderengine.vulkan")
-FLAG_MANAGER_READ_ONLY_FLAG(renderable_buffer_usage, "")
-FLAG_MANAGER_READ_ONLY_FLAG(restore_blur_step, "debug.renderengine.restore_blur_step")
-FLAG_MANAGER_READ_ONLY_FLAG(dont_skip_on_early_ro, "")
-FLAG_MANAGER_READ_ONLY_FLAG(protected_if_client, "")
-FLAG_MANAGER_READ_ONLY_FLAG(vrr_bugfix_24q4, "");
-FLAG_MANAGER_READ_ONLY_FLAG(vrr_bugfix_dropped_frame, "")
-FLAG_MANAGER_READ_ONLY_FLAG(ce_fence_promise, "");
-FLAG_MANAGER_READ_ONLY_FLAG(graphite_renderengine, "debug.renderengine.graphite")
-FLAG_MANAGER_READ_ONLY_FLAG(filter_frames_before_trace_starts, "")
-FLAG_MANAGER_READ_ONLY_FLAG(latch_unsignaled_with_auto_refresh_changed, "");
-FLAG_MANAGER_READ_ONLY_FLAG(deprecate_vsync_sf, "");
-FLAG_MANAGER_READ_ONLY_FLAG(allow_n_vsyncs_in_targeter, "");
-FLAG_MANAGER_READ_ONLY_FLAG(detached_mirror, "");
-FLAG_MANAGER_READ_ONLY_FLAG(commit_not_composited, "");
-FLAG_MANAGER_READ_ONLY_FLAG(correct_dpi_with_display_size, "");
-FLAG_MANAGER_READ_ONLY_FLAG(local_tonemap_screenshots, "debug.sf.local_tonemap_screenshots");
-FLAG_MANAGER_READ_ONLY_FLAG(override_trusted_overlay, "");
-FLAG_MANAGER_READ_ONLY_FLAG(flush_buffer_slots_to_uncache, "");
-FLAG_MANAGER_READ_ONLY_FLAG(force_compile_graphite_renderengine, "");
-FLAG_MANAGER_READ_ONLY_FLAG(single_hop_screenshot, "");
-FLAG_MANAGER_READ_ONLY_FLAG(true_hdr_screenshots, "debug.sf.true_hdr_screenshots");
+FLAG_MANAGER_ACONFIG_FLAG(adpf_fmq_sf, "")
+FLAG_MANAGER_ACONFIG_FLAG(arr_setframerate_gte_enum, "debug.sf.arr_setframerate_gte_enum")
+FLAG_MANAGER_ACONFIG_FLAG(connected_display, "")
+FLAG_MANAGER_ACONFIG_FLAG(enable_small_area_detection, "")
+FLAG_MANAGER_ACONFIG_FLAG(stable_edid_ids, "debug.sf.stable_edid_ids")
+FLAG_MANAGER_ACONFIG_FLAG(frame_rate_category_mrr, "debug.sf.frame_rate_category_mrr")
+FLAG_MANAGER_ACONFIG_FLAG(misc1, "")
+FLAG_MANAGER_ACONFIG_FLAG(vrr_config, "debug.sf.enable_vrr_config")
+FLAG_MANAGER_ACONFIG_FLAG(hdcp_level_hal, "")
+FLAG_MANAGER_ACONFIG_FLAG(multithreaded_present, "debug.sf.multithreaded_present")
+FLAG_MANAGER_ACONFIG_FLAG(add_sf_skipped_frames_to_trace, "")
+FLAG_MANAGER_ACONFIG_FLAG(use_known_refresh_rate_for_fps_consistency, "")
+FLAG_MANAGER_ACONFIG_FLAG(cache_when_source_crop_layer_only_moved,
+ "debug.sf.cache_source_crop_only_moved")
+FLAG_MANAGER_ACONFIG_FLAG(enable_fro_dependent_features, "")
+FLAG_MANAGER_ACONFIG_FLAG(display_protected, "")
+FLAG_MANAGER_ACONFIG_FLAG(fp16_client_target, "debug.sf.fp16_client_target")
+FLAG_MANAGER_ACONFIG_FLAG(game_default_frame_rate, "")
+FLAG_MANAGER_ACONFIG_FLAG(enable_layer_command_batching, "debug.sf.enable_layer_command_batching")
+FLAG_MANAGER_ACONFIG_FLAG(vulkan_renderengine, "debug.renderengine.vulkan")
+FLAG_MANAGER_ACONFIG_FLAG(renderable_buffer_usage, "")
+FLAG_MANAGER_ACONFIG_FLAG(restore_blur_step, "debug.renderengine.restore_blur_step")
+FLAG_MANAGER_ACONFIG_FLAG(dont_skip_on_early_ro, "")
+FLAG_MANAGER_ACONFIG_FLAG(no_vsyncs_on_screen_off, "debug.sf.no_vsyncs_on_screen_off")
+FLAG_MANAGER_ACONFIG_FLAG(protected_if_client, "")
+FLAG_MANAGER_ACONFIG_FLAG(vrr_bugfix_24q4, "");
+FLAG_MANAGER_ACONFIG_FLAG(vrr_bugfix_dropped_frame, "")
+FLAG_MANAGER_ACONFIG_FLAG(graphite_renderengine, "debug.renderengine.graphite")
+FLAG_MANAGER_ACONFIG_FLAG(filter_frames_before_trace_starts, "")
+FLAG_MANAGER_ACONFIG_FLAG(latch_unsignaled_with_auto_refresh_changed, "");
+FLAG_MANAGER_ACONFIG_FLAG(deprecate_vsync_sf, "");
+FLAG_MANAGER_ACONFIG_FLAG(allow_n_vsyncs_in_targeter, "");
+FLAG_MANAGER_ACONFIG_FLAG(detached_mirror, "");
+FLAG_MANAGER_ACONFIG_FLAG(commit_not_composited, "");
+FLAG_MANAGER_ACONFIG_FLAG(correct_dpi_with_display_size, "");
+FLAG_MANAGER_ACONFIG_FLAG(local_tonemap_screenshots, "debug.sf.local_tonemap_screenshots");
+FLAG_MANAGER_ACONFIG_FLAG(override_trusted_overlay, "");
+FLAG_MANAGER_ACONFIG_FLAG(flush_buffer_slots_to_uncache, "");
+FLAG_MANAGER_ACONFIG_FLAG(force_compile_graphite_renderengine, "");
+FLAG_MANAGER_ACONFIG_FLAG(true_hdr_screenshots, "debug.sf.true_hdr_screenshots");
+FLAG_MANAGER_ACONFIG_FLAG(display_config_error_hal, "");
+FLAG_MANAGER_ACONFIG_FLAG(connected_display_hdr, "debug.sf.connected_display_hdr");
+FLAG_MANAGER_ACONFIG_FLAG(deprecate_frame_tracker, "");
+FLAG_MANAGER_ACONFIG_FLAG(skip_invisible_windows_in_input, "");
+FLAG_MANAGER_ACONFIG_FLAG(begone_bright_hlg, "debug.sf.begone_bright_hlg");
+FLAG_MANAGER_ACONFIG_FLAG(window_blur_kawase2, "");
+FLAG_MANAGER_ACONFIG_FLAG(reject_dupe_layerstacks, "");
+FLAG_MANAGER_ACONFIG_FLAG(synced_resolution_switch, "");
-/// Trunk stable server flags ///
-FLAG_MANAGER_SERVER_FLAG(refresh_rate_overlay_on_external_display, "")
-FLAG_MANAGER_SERVER_FLAG(adpf_gpu_sf, "")
+/// Trunk stable server (R/W) flags ///
+FLAG_MANAGER_ACONFIG_FLAG(refresh_rate_overlay_on_external_display, "")
+FLAG_MANAGER_ACONFIG_FLAG(adpf_gpu_sf, "")
+FLAG_MANAGER_ACONFIG_FLAG(adpf_native_session_manager, "");
+FLAG_MANAGER_ACONFIG_FLAG(graphite_renderengine_preview_rollout, "");
+FLAG_MANAGER_ACONFIG_FLAG(increase_missed_frame_jank_threshold, "");
+FLAG_MANAGER_ACONFIG_FLAG(vsync_predictor_recovery, "");
-/// Trunk stable server flags from outside SurfaceFlinger ///
-FLAG_MANAGER_SERVER_FLAG_IMPORTED(adpf_use_fmq_channel, "", android::os)
+/// Trunk stable server (R/W) flags from outside SurfaceFlinger ///
+FLAG_MANAGER_ACONFIG_FLAG_IMPORTED(adpf_use_fmq_channel, "", android::os)
/// Trunk stable readonly flags from outside SurfaceFlinger ///
-FLAG_MANAGER_READ_ONLY_FLAG_IMPORTED(idle_screen_refresh_rate_timeout, "",
- com::android::server::display::feature::flags)
-FLAG_MANAGER_READ_ONLY_FLAG_IMPORTED(adpf_use_fmq_channel_fixed, "", android::os)
-FLAG_MANAGER_READ_ONLY_FLAG_IMPORTED(trace_frame_rate_override, "",
- com::android::graphics::libgui::flags);
-
+FLAG_MANAGER_ACONFIG_FLAG_IMPORTED(idle_screen_refresh_rate_timeout, "",
+ com::android::server::display::feature::flags)
+FLAG_MANAGER_ACONFIG_FLAG_IMPORTED(adpf_use_fmq_channel_fixed, "", android::os)
+FLAG_MANAGER_ACONFIG_FLAG_IMPORTED(trace_frame_rate_override, "",
+ com::android::graphics::libgui::flags);
+FLAG_MANAGER_ACONFIG_FLAG_IMPORTED(luts_api, "",
+ android::hardware::flags);
} // namespace android
diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h
index a1be194..6295c5b 100644
--- a/services/surfaceflinger/common/include/common/FlagManager.h
+++ b/services/surfaceflinger/common/include/common/FlagManager.h
@@ -42,59 +42,82 @@
void setUnitTestMode();
+ /// Debug sysprop flags ///
+ bool disable_sched_fifo_sf() const;
+ bool disable_sched_fifo_sf_binder() const;
+ bool disable_sched_fifo_sf_sched() const;
+ bool disable_sched_fifo_re() const;
+ bool disable_sched_fifo_composer() const;
+ bool disable_sched_fifo_composer_callback() const;
+
/// Legacy server flags ///
bool test_flag() const;
bool use_adpf_cpu_hint() const;
bool use_skia_tracing() const;
- /// Trunk stable server flags ///
- bool refresh_rate_overlay_on_external_display() const;
+ /// Trunk stable server (R/W) flags ///
bool adpf_gpu_sf() const;
+ bool adpf_native_session_manager() const;
bool adpf_use_fmq_channel() const;
bool adpf_use_fmq_channel_fixed() const;
+ bool graphite_renderengine_preview_rollout() const;
+ bool increase_missed_frame_jank_threshold() const;
+ bool refresh_rate_overlay_on_external_display() const;
+ bool vsync_predictor_recovery() const;
/// Trunk stable readonly flags ///
- bool connected_display() const;
- bool frame_rate_category_mrr() const;
- bool enable_small_area_detection() const;
- bool misc1() const;
- bool vrr_config() const;
- bool hotplug2() const;
- bool hdcp_level_hal() const;
- bool multithreaded_present() const;
+ /// IMPORTANT - please keep alphabetize to reduce merge conflicts
bool add_sf_skipped_frames_to_trace() const;
- bool use_known_refresh_rate_for_fps_consistency() const;
- bool cache_when_source_crop_layer_only_moved() const;
- bool enable_fro_dependent_features() const;
- bool display_protected() const;
- bool fp16_client_target() const;
- bool game_default_frame_rate() const;
- bool enable_layer_command_batching() const;
- bool screenshot_fence_preservation() const;
- bool vulkan_renderengine() const;
- bool vrr_bugfix_24q4() const;
- bool vrr_bugfix_dropped_frame() const;
- bool renderable_buffer_usage() const;
- bool restore_blur_step() const;
- bool dont_skip_on_early_ro() const;
- bool protected_if_client() const;
- bool ce_fence_promise() const;
- bool idle_screen_refresh_rate_timeout() const;
- bool graphite_renderengine() const;
- bool filter_frames_before_trace_starts() const;
- bool latch_unsignaled_with_auto_refresh_changed() const;
- bool deprecate_vsync_sf() const;
+ bool adpf_fmq_sf() const;
bool allow_n_vsyncs_in_targeter() const;
- bool detached_mirror() const;
+ bool arr_setframerate_gte_enum() const;
+ bool begone_bright_hlg() const;
+ bool cache_when_source_crop_layer_only_moved() const;
bool commit_not_composited() const;
+ bool connected_display() const;
+ bool connected_display_hdr() const;
bool correct_dpi_with_display_size() const;
- bool local_tonemap_screenshots() const;
- bool override_trusted_overlay() const;
+ bool deprecate_frame_tracker() const;
+ bool deprecate_vsync_sf() const;
+ bool detached_mirror() const;
+ bool display_config_error_hal() const;
+ bool display_protected() const;
+ bool dont_skip_on_early_ro() const;
+ bool enable_fro_dependent_features() const;
+ bool enable_layer_command_batching() const;
+ bool enable_small_area_detection() const;
+ bool filter_frames_before_trace_starts() const;
bool flush_buffer_slots_to_uncache() const;
bool force_compile_graphite_renderengine() const;
- bool single_hop_screenshot() const;
+ bool fp16_client_target() const;
+ bool frame_rate_category_mrr() const;
+ bool game_default_frame_rate() const;
+ bool graphite_renderengine() const;
+ bool hdcp_level_hal() const;
+ bool idle_screen_refresh_rate_timeout() const;
+ bool latch_unsignaled_with_auto_refresh_changed() const;
+ bool local_tonemap_screenshots() const;
+ bool luts_api() const;
+ bool misc1() const;
+ bool multithreaded_present() const;
+ bool no_vsyncs_on_screen_off() const;
+ bool override_trusted_overlay() const;
+ bool protected_if_client() const;
+ bool reject_dupe_layerstacks() const;
+ bool renderable_buffer_usage() const;
+ bool restore_blur_step() const;
+ bool skip_invisible_windows_in_input() const;
+ bool stable_edid_ids() const;
+ bool synced_resolution_switch() const;
bool trace_frame_rate_override() const;
bool true_hdr_screenshots() const;
+ bool use_known_refresh_rate_for_fps_consistency() const;
+ bool vrr_bugfix_24q4() const;
+ bool vrr_bugfix_dropped_frame() const;
+ bool vrr_config() const;
+ bool vulkan_renderengine() const;
+ bool window_blur_kawase2() const;
+ /// IMPORTANT - please keep alphabetize to reduce merge conflicts
protected:
// overridden for unit tests
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp b/services/surfaceflinger/common/include/common/WorkloadTracer.h
similarity index 62%
copy from services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp
copy to services/surfaceflinger/common/include/common/WorkloadTracer.h
index d383283..c4074f7 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp
+++ b/services/surfaceflinger/common/include/common/WorkloadTracer.h
@@ -1,3 +1,4 @@
+
/*
* Copyright 2024 The Android Open Source Project
*
@@ -14,12 +15,15 @@
* limitations under the License.
*/
-#include "mock/DisplayHardware/MockPowerHintSessionWrapper.h"
+#pragma once
-namespace android::Hwc2::mock {
+#include <ftl/flags.h>
+#include <stdint.h>
+namespace android::WorkloadTracer {
-// Explicit default instantiation is recommended.
-MockPowerHintSessionWrapper::MockPowerHintSessionWrapper()
- : power::PowerHintSessionWrapper(nullptr) {}
+static constexpr int32_t COMPOSITION_TRACE_COOKIE = 1;
+static constexpr int32_t POST_COMPOSITION_TRACE_COOKIE = 2;
+static constexpr size_t COMPOSITION_SUMMARY_SIZE = 64;
+static constexpr const char* TRACK_NAME = "CriticalWorkload";
-} // namespace android::Hwc2::mock
+} // namespace android::WorkloadTracer
\ No newline at end of file
diff --git a/services/surfaceflinger/common/include/common/trace.h b/services/surfaceflinger/common/include/common/trace.h
index dc5716b..9a7e97f 100644
--- a/services/surfaceflinger/common/include/common/trace.h
+++ b/services/surfaceflinger/common/include/common/trace.h
@@ -65,6 +65,8 @@
#define SFTRACE_NAME(name) ::android::ScopedTrace PASTE(___tracer, __LINE__)(name)
// SFTRACE_CALL is an SFTRACE_NAME that uses the current function name.
#define SFTRACE_CALL() SFTRACE_NAME(__FUNCTION__)
+#define SFTRACE_NAME_FOR_TRACK(trackName, name) \
+ ::android::ScopedTraceForTrack PASTE(___tracer, __LINE__)(trackName, name)
#define SFTRACE_FORMAT(fmt, ...) \
::android::ScopedTrace PASTE(___tracer, __LINE__)(fmt, ##__VA_ARGS__)
@@ -87,4 +89,21 @@
inline ~ScopedTrace() { SFTRACE_END(); }
};
+class ScopedTraceForTrack {
+public:
+ inline ScopedTraceForTrack(const char* trackName, const char* name)
+ : mCookie(getUniqueCookie()), mTrackName(trackName) {
+ SFTRACE_ASYNC_FOR_TRACK_BEGIN(mTrackName, name, mCookie);
+ }
+ inline ~ScopedTraceForTrack() { SFTRACE_ASYNC_FOR_TRACK_END(mTrackName, mCookie); }
+
+private:
+ static int32_t getUniqueCookie() {
+ static std::atomic<int32_t> sUniqueCookie = 1000;
+ return sUniqueCookie++;
+ }
+ int32_t mCookie;
+ const char* mTrackName;
+};
+
} // namespace android
diff --git a/services/surfaceflinger/fuzzer/Android.bp b/services/surfaceflinger/fuzzer/Android.bp
index ae502cf..1de6b4a 100644
--- a/services/surfaceflinger/fuzzer/Android.bp
+++ b/services/surfaceflinger/fuzzer/Android.bp
@@ -28,16 +28,18 @@
cc_defaults {
name: "surfaceflinger_fuzz_defaults",
static_libs: [
- "libc++fs",
"libsurfaceflinger_common",
],
srcs: [
+ ":libsurfaceflinger_backend_mock_sources",
+ ":libsurfaceflinger_mock_sources",
":libsurfaceflinger_sources",
],
defaults: [
"libsurfaceflinger_defaults",
],
header_libs: [
+ "libsurfaceflinger_backend_mock_headers",
"libsurfaceflinger_headers",
],
cflags: [
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index 6c8972f..73dfa9f 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -132,7 +132,8 @@
// Set the minimum policy of surfaceflinger node to be SCHED_FIFO.
// So any thread with policy/priority lower than {SCHED_FIFO, 1}, will run
// at least with SCHED_FIFO policy and priority 1.
- if (errorInPriorityModification == 0) {
+ if (errorInPriorityModification == 0 &&
+ !FlagManager::getInstance().disable_sched_fifo_sf_binder()) {
flinger->setMinSchedulerPolicy(SCHED_FIFO, newPriority);
}
@@ -150,7 +151,8 @@
// publish gui::ISurfaceComposer, the new AIDL interface
sp<SurfaceComposerAIDL> composerAIDL = sp<SurfaceComposerAIDL>::make(flinger);
- if (FlagManager::getInstance().misc1()) {
+ if (FlagManager::getInstance().misc1() &&
+ !FlagManager::getInstance().disable_sched_fifo_composer()) {
composerAIDL->setMinSchedulerPolicy(SCHED_FIFO, newPriority);
}
sm->addService(String16("SurfaceFlingerAIDL"), composerAIDL, false,
diff --git a/services/surfaceflinger/surfaceflinger.logtags b/services/surfaceflinger/surfaceflinger.logtags
index e68d9f5..6dbe0dd 100644
--- a/services/surfaceflinger/surfaceflinger.logtags
+++ b/services/surfaceflinger/surfaceflinger.logtags
@@ -31,7 +31,7 @@
# 6: Percent
# Default value for data of type int/long is 2 (bytes).
#
-# See system/core/logcat/event.logtags for the master copy of the tags.
+# See system/logging/logcat/event.logtags for the master copy of the tags.
# 60100 - 60199 reserved for surfaceflinger
diff --git a/services/surfaceflinger/surfaceflinger_flags_new.aconfig b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
index e40be51..d8f51fe 100644
--- a/services/surfaceflinger/surfaceflinger_flags_new.aconfig
+++ b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
@@ -4,6 +4,14 @@
container: "system"
flag {
+ name: "adpf_fmq_sf"
+ namespace: "game"
+ description: "Guards use of the ADPF FMQ system specifically for SurfaceFlinger"
+ bug: "315894228"
+ is_fixed_read_only: true
+} # adpf_fmq_sf
+
+flag {
name: "adpf_gpu_sf"
namespace: "game"
description: "Guards use of the sending ADPF GPU duration hint and load hints from SurfaceFlinger to Power HAL"
@@ -11,14 +19,47 @@
} # adpf_gpu_sf
flag {
+ name: "adpf_native_session_manager"
+ namespace: "game"
+ description: "Controls ADPF SessionManager being enabled in SF"
+ bug: "367803904"
+} # adpf_sessionmanager
+
+flag {
name: "arr_setframerate_api"
namespace: "core_graphics"
- description: "New setFrameRate API for Android 16"
+ description: "New SDK Surface#setFrameRate API and Surface.FrameRateParams for Android 16"
bug: "356987016"
is_fixed_read_only: true
+ is_exported: true
} # arr_setframerate_api
flag {
+ name: "arr_setframerate_gte_enum"
+ namespace: "core_graphics"
+ description: "Exposes GTE (greater than or equal to) enum for Android 16"
+ bug: "380949716"
+ is_fixed_read_only: true
+} # arr_setframerate_gte_enum
+
+flag {
+ name: "arr_surfacecontrol_setframerate_api"
+ namespace: "core_graphics"
+ description: "New SDK SurfaceControl.Transaction#setFrameRate API for Android 16"
+ bug: "356987016"
+ is_fixed_read_only: true
+ is_exported: true
+} # arr_surfacecontrol_setframerate_api
+
+flag {
+ name: "begone_bright_hlg"
+ namespace: "core_graphics"
+ description: "Caps HLG brightness relative to SDR"
+ bug: "362510107"
+ is_fixed_read_only: true
+} # begone_bright_hlg
+
+flag {
name: "ce_fence_promise"
namespace: "window_surfaces"
description: "Moves logic for buffer release fences into LayerFE"
@@ -41,6 +82,14 @@
} # commit_not_composited
flag {
+ name: "connected_display_hdr"
+ namespace: "core_graphics"
+ description: "enable connected display hdr capability"
+ bug: "374182788"
+ is_fixed_read_only: true
+} # connected_display_hdr
+
+flag {
name: "correct_dpi_with_display_size"
namespace: "core_graphics"
description: "indicate whether missing or likely incorrect dpi should be corrected using the display size."
@@ -52,6 +101,17 @@
} # correct_dpi_with_display_size
flag {
+ name: "deprecate_frame_tracker"
+ namespace: "core_graphics"
+ description: "Deprecate using FrameTracker to accumulate and provide FrameStats"
+ bug: "241394120"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+} # deprecate_frame_tracker
+
+flag {
name: "deprecate_vsync_sf"
namespace: "core_graphics"
description: "Depracate eVsyncSourceSurfaceFlinger and use vsync_app everywhere"
@@ -74,6 +134,14 @@
} # detached_mirror
flag {
+ name: "display_config_error_hal"
+ namespace: "core_graphics"
+ description: "Report HAL display configuration errors like modeset failure or link training failure"
+ bug: "374184110"
+ is_fixed_read_only: true
+} # display_config_error_hal
+
+flag {
name: "filter_frames_before_trace_starts"
namespace: "core_graphics"
description: "Do not trace FrameTimeline events for frames started before the trace started"
@@ -115,6 +183,20 @@
} # frame_rate_category_mrr
flag {
+ name: "graphite_renderengine_preview_rollout"
+ namespace: "core_graphics"
+ description: "R/W flag to enable Skia's Graphite Vulkan backend in RenderEngine, IF it is already compiled with force_compile_graphite_renderengine, AND the debug.renderengine.graphite_preview_optin sysprop is set to true."
+ bug: "293371537"
+} # graphite_renderengine_preview_rollout
+
+flag {
+ name: "increase_missed_frame_jank_threshold"
+ namespace: "core_graphics"
+ description: "Increase the jank threshold to 4 milliseconds"
+ bug: "342265411"
+} # increase_missed_frame_jank_threshold
+
+flag {
name: "latch_unsignaled_with_auto_refresh_changed"
namespace: "core_graphics"
description: "Ignore eAutoRefreshChanged with latch unsignaled"
@@ -134,6 +216,25 @@
} # local_tonemap_screenshots
flag {
+ name: "no_vsyncs_on_screen_off"
+ namespace: "core_graphics"
+ description: "Stop vsync / Choreographer callbacks to apps when the screen is off"
+ bug: "331636736"
+ is_fixed_read_only: true
+} # no_vsyncs_on_screen_off
+
+flag {
+ name: "reject_dupe_layerstacks"
+ namespace: "window_surfaces"
+ description: "Reject duplicate layerstacks for displays"
+ bug: "370358572"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+ } # reject_dupe_layerstacks
+
+flag {
name: "single_hop_screenshot"
namespace: "window_surfaces"
description: "Only access SF main thread once during a screenshot"
@@ -145,6 +246,32 @@
} # single_hop_screenshot
flag {
+ name: "skip_invisible_windows_in_input"
+ namespace: "window_surfaces"
+ description: "Only send visible windows to input list"
+ bug: "305254099"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+ } # skip_invisible_windows_in_input
+
+flag {
+ name: "stable_edid_ids"
+ namespace: "core_graphics"
+ description: "Guard use of the new stable EDID-based display IDs system."
+ bug: "352320847"
+ is_fixed_read_only: true
+} # stable_edid_ids
+
+flag {
+ name: "synced_resolution_switch"
+ namespace: "core_graphics"
+ description: "Synchronize resolution modeset with framebuffer resizing"
+ bug: "355427258"
+} # synced_resolution_switch
+
+flag {
name: "true_hdr_screenshots"
namespace: "core_graphics"
description: "Enables screenshotting display content in HDR, sans tone mapping"
@@ -193,4 +320,21 @@
}
} # vrr_bugfix_dropped_frame
+flag {
+ name: "vsync_predictor_recovery"
+ namespace: "core_graphics"
+ description: "Recover the vsync predictor from bad vsync model"
+ bug: "385059265"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+ } # vsync_predictor_recovery
+
+flag {
+ name: "window_blur_kawase2"
+ namespace: "core_graphics"
+ description: "Flag for using Kawase2 algorithm for window blur"
+ bug: "353826438"
+} # window_blur_kawase2
+
# IMPORTANT - please keep alphabetize to reduce merge conflicts
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index 4d5c0fd..b5f7a74 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -52,7 +52,7 @@
"LayerTypeTransaction_test.cpp",
"LayerUpdate_test.cpp",
"MirrorLayer_test.cpp",
- "MultiDisplayLayerBounds_test.cpp",
+ "MultiDisplay_test.cpp",
"RefreshRateOverlay_test.cpp",
"RelativeZ_test.cpp",
"ReleaseBufferCallback_test.cpp",
diff --git a/services/surfaceflinger/tests/AndroidTest.xml b/services/surfaceflinger/tests/AndroidTest.xml
index 000628f..ad43cdc 100644
--- a/services/surfaceflinger/tests/AndroidTest.xml
+++ b/services/surfaceflinger/tests/AndroidTest.xml
@@ -19,6 +19,9 @@
<option name="push" value="SurfaceFlinger_test->/data/local/tmp/SurfaceFlinger_test" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+ <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <option name="screen-always-on" value="on" />
+ </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" />
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
index e6fed63..7b6e4bf 100644
--- a/services/surfaceflinger/tests/Credentials_test.cpp
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -341,9 +341,9 @@
WindowInfosListenerUtils windowInfosListenerUtils;
std::string name = "Test Layer";
sp<IBinder> token = sp<BBinder>::make();
- WindowInfo windowInfo;
- windowInfo.name = name;
- windowInfo.token = token;
+ auto windowInfo = sp<gui::WindowInfoHandle>::make();
+ windowInfo->editInfo()->name = name;
+ windowInfo->editInfo()->token = token;
sp<SurfaceControl> surfaceControl =
mComposerClient->createSurface(String8(name.c_str()), 100, 100, PIXEL_FORMAT_RGBA_8888,
ISurfaceComposerClient::eFXSurfaceBufferState);
@@ -370,7 +370,8 @@
UIDFaker f(AID_SYSTEM);
auto windowIsPresentAndNotTrusted = [&](const std::vector<WindowInfo>& windowInfos) {
auto foundWindowInfo =
- WindowInfosListenerUtils::findMatchingWindowInfo(windowInfo, windowInfos);
+ WindowInfosListenerUtils::findMatchingWindowInfo(*windowInfo->getInfo(),
+ windowInfos);
if (!foundWindowInfo) {
return false;
}
@@ -386,7 +387,8 @@
Transaction().setTrustedOverlay(surfaceControl, true).apply(/*synchronous=*/true);
auto windowIsPresentAndTrusted = [&](const std::vector<WindowInfo>& windowInfos) {
auto foundWindowInfo =
- WindowInfosListenerUtils::findMatchingWindowInfo(windowInfo, windowInfos);
+ WindowInfosListenerUtils::findMatchingWindowInfo(*windowInfo->getInfo(),
+ windowInfos);
if (!foundWindowInfo) {
return false;
}
diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp
index b4496d3..5a82914 100644
--- a/services/surfaceflinger/tests/LayerCallback_test.cpp
+++ b/services/surfaceflinger/tests/LayerCallback_test.cpp
@@ -147,7 +147,7 @@
<< "Timeout waiting for vsync event";
DisplayEventReceiver::Event event;
while (mDisplayEventReceiver.getEvents(&event, 1) > 0) {
- if (event.header.type != DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
+ if (event.header.type != DisplayEventType::DISPLAY_EVENT_VSYNC) {
continue;
}
diff --git a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
index f247c9f..151611c 100644
--- a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
@@ -585,6 +585,83 @@
}
}
+TEST_P(LayerTypeAndRenderTypeTransactionTest, SetClientDrawnCornerRadius) {
+ sp<SurfaceControl> layer;
+ const uint8_t size = 64;
+ const uint8_t testArea = 4;
+ const float cornerRadius = 20.0f;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", size, size));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, size, size));
+
+ Transaction()
+ .setClientDrawnCornerRadius(layer, cornerRadius)
+ .setCornerRadius(layer, cornerRadius)
+ .setCrop(layer, Rect(size, size))
+ .apply();
+
+ {
+ const uint8_t bottom = size - 1;
+ const uint8_t right = size - 1;
+ auto shot = getScreenCapture();
+ // Solid corners
+ shot->expectColor(Rect(0, 0, testArea, testArea), Color::RED);
+ shot->expectColor(Rect(size - testArea, 0, right, testArea), Color::RED);
+ shot->expectColor(Rect(0, bottom - testArea, testArea, bottom), Color::RED);
+ shot->expectColor(Rect(size - testArea, bottom - testArea, right, bottom), Color::RED);
+ // Solid center
+ shot->expectColor(Rect(size / 2 - testArea / 2, size / 2 - testArea / 2,
+ size / 2 + testArea / 2, size / 2 + testArea / 2),
+ Color::RED);
+ }
+}
+
+// Test if ParentCornerRadiusTakesPrecedence if the parent's client drawn corner radius crop
+// is fully contained by the child corner radius crop.
+TEST_P(LayerTypeAndRenderTypeTransactionTest, ParentCornerRadiusPrecedenceClientDrawnCornerRadius) {
+ sp<SurfaceControl> parent;
+ sp<SurfaceControl> child;
+ const uint32_t size = 64;
+ const uint32_t parentSize = size * 3;
+ const Rect parentCrop(size, size, size, size);
+ const uint32_t testLength = 4;
+ const float cornerRadius = 20.0f;
+ ASSERT_NO_FATAL_FAILURE(parent = createLayer("parent", parentSize, parentSize));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(parent, Color::RED, parentSize, parentSize));
+ ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size));
+
+ Transaction()
+ .setCornerRadius(parent, cornerRadius)
+ .setCrop(parent, parentCrop)
+ .setClientDrawnCornerRadius(parent, cornerRadius)
+ .reparent(child, parent)
+ .setPosition(child, size, size)
+ .apply(true);
+
+ {
+ const uint32_t top = size;
+ const uint32_t left = size;
+ const uint32_t bottom = size * 2;
+ const uint32_t right = size * 2;
+ auto shot = getScreenCapture();
+ // Corners are RED because parent's client drawn corner radius is actually 0
+ // and the child is fully within the parent's crop
+ // TL
+ shot->expectColor(Rect(left, top, testLength, testLength), Color::RED);
+ // TR
+ shot->expectColor(Rect(right - testLength, top, testLength, testLength), Color::RED);
+ // BL
+ shot->expectColor(Rect(left, bottom - testLength, testLength, testLength), Color::RED);
+ // BR
+ shot->expectColor(Rect(right - testLength, bottom - testLength, testLength, testLength),
+ Color::RED);
+ // Solid center
+ shot->expectColor(Rect(parentSize / 2 - testLength, parentSize / 2 - testLength, testLength,
+ testLength),
+ Color::GREEN);
+ }
+}
+
TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadiusSimple) {
if (!deviceSupportsBlurs()) GTEST_SKIP();
if (!deviceUsesSkiaRenderEngine()) GTEST_SKIP();
diff --git a/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp b/services/surfaceflinger/tests/MultiDisplay_test.cpp
similarity index 69%
rename from services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp
rename to services/surfaceflinger/tests/MultiDisplay_test.cpp
index 56cf13d..cf6d328 100644
--- a/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp
+++ b/services/surfaceflinger/tests/MultiDisplay_test.cpp
@@ -19,6 +19,7 @@
#pragma clang diagnostic ignored "-Wconversion"
#include <common/FlagManager.h>
+#include <gui/IConsumerListener.h>
#include <ui/DisplayState.h>
#include "LayerTransactionTest.h"
@@ -32,7 +33,7 @@
::testing::Environment* const binderEnv =
::testing::AddGlobalTestEnvironment(new BinderEnvironment());
-class MultiDisplayLayerBoundsTest : public LayerTransactionTest {
+class MultiDisplayTest : public LayerTransactionTest {
protected:
virtual void SetUp() {
LayerTransactionTest::SetUp();
@@ -45,11 +46,17 @@
SurfaceComposerClient::getDisplayState(mMainDisplay, &mMainDisplayState);
SurfaceComposerClient::getActiveDisplayMode(mMainDisplay, &mMainDisplayMode);
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&mProducer, &consumer);
- consumer->setConsumerName(String8("Virtual disp consumer"));
- consumer->setDefaultBufferSize(mMainDisplayMode.resolution.getWidth(),
- mMainDisplayMode.resolution.getHeight());
+ BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+ mConsumer->setConsumerName(String8("Virtual disp consumer (MultiDisplayLayerBounds)"));
+ mConsumer->setDefaultBufferSize(mMainDisplayMode.resolution.getWidth(),
+ mMainDisplayMode.resolution.getHeight());
+
+ class StubConsumerListener : public IConsumerListener {
+ virtual void onFrameAvailable(const BufferItem&) override {}
+ virtual void onBuffersReleased() override {}
+ virtual void onSidebandStreamChanged() override {}
+ };
+ mConsumer->consumerConnect(sp<StubConsumerListener>::make(), true);
}
virtual void TearDown() {
@@ -92,12 +99,13 @@
sp<IBinder> mMainDisplay;
PhysicalDisplayId mMainDisplayId;
sp<IBinder> mVirtualDisplay;
+ sp<IGraphicBufferConsumer> mConsumer;
sp<IGraphicBufferProducer> mProducer;
sp<SurfaceControl> mColorLayer;
Color mExpectedColor = {63, 63, 195, 255};
};
-TEST_F(MultiDisplayLayerBoundsTest, RenderLayerInVirtualDisplay) {
+TEST_F(MultiDisplayTest, RenderLayerInVirtualDisplay) {
constexpr ui::LayerStack kLayerStack{1u};
createDisplay(mMainDisplayState.layerStackSpaceRect, kLayerStack);
createColorLayer(kLayerStack);
@@ -116,7 +124,7 @@
sc->expectColor(Rect(1, 1, 9, 9), {0, 0, 0, 255});
}
-TEST_F(MultiDisplayLayerBoundsTest, RenderLayerInMirroredVirtualDisplay) {
+TEST_F(MultiDisplayTest, RenderLayerInMirroredVirtualDisplay) {
// Create a display and set its layer stack to the main display's layer stack so
// the contents of the main display are mirrored on to the virtual display.
@@ -142,7 +150,7 @@
sc->expectColor(Rect(0, 0, 9, 9), {0, 0, 0, 255});
}
-TEST_F(MultiDisplayLayerBoundsTest, RenderLayerWithPromisedFenceInMirroredVirtualDisplay) {
+TEST_F(MultiDisplayTest, RenderLayerWithPromisedFenceInMirroredVirtualDisplay) {
// Create a display and use a unique layerstack ID for mirrorDisplay() so
// the contents of the main display are mirrored on to the virtual display.
@@ -173,6 +181,51 @@
sc->expectColor(Rect(0, 0, 9, 9), {0, 0, 0, 255});
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+TEST_F(MultiDisplayTest, rejectDuplicateLayerStacks) {
+ if (!FlagManager::getInstance().reject_dupe_layerstacks()) return;
+
+ // Setup
+ sp<CpuConsumer> cpuConsumer1 = sp<CpuConsumer>::make(static_cast<size_t>(1));
+ cpuConsumer1->setName(String8("consumer 1"));
+ cpuConsumer1->setDefaultBufferSize(100, 100);
+ sp<IGraphicBufferProducer> cpuProducer1 =
+ cpuConsumer1->getSurface()->getIGraphicBufferProducer();
+ CpuConsumer::LockedBuffer buffer1;
+
+ sp<CpuConsumer> cpuConsumer2 = sp<CpuConsumer>::make(static_cast<size_t>(1));
+ cpuConsumer2->setName(String8("consumer 2"));
+ cpuConsumer2->setDefaultBufferSize(100, 100);
+ sp<IGraphicBufferProducer> cpuProducer2 =
+ cpuConsumer2->getSurface()->getIGraphicBufferProducer();
+ CpuConsumer::LockedBuffer buffer2;
+
+ SurfaceComposerClient::Transaction t;
+ constexpr ui::LayerStack layerStack = {123u};
+ createColorLayer(layerStack);
+
+ static const std::string kDisplayName1("VirtualDisplay1 - rejectDuplicateLayerStacks");
+ sp<IBinder> virtualDisplay1 =
+ SurfaceComposerClient::createVirtualDisplay(kDisplayName1, false /*isSecure*/);
+
+ t.setDisplaySurface(virtualDisplay1, cpuProducer1);
+ t.setDisplayLayerStack(virtualDisplay1, layerStack);
+ t.apply(true);
+
+ static const std::string kDisplayName2("VirtualDisplay2 - rejectDuplicateLayerStacks");
+ sp<IBinder> virtualDisplay2 =
+ SurfaceComposerClient::createVirtualDisplay(kDisplayName2, false /*isSecure*/);
+
+ t.setDisplaySurface(virtualDisplay2, cpuProducer2);
+ t.setDisplayLayerStack(virtualDisplay2, layerStack);
+ t.apply(true);
+
+ // The second consumer will not be able to lock a buffer because
+ // the duplicate layer stack should be rejected.
+ ASSERT_EQ(NO_ERROR, cpuConsumer1->lockNextBuffer(&buffer1));
+ ASSERT_NE(NO_ERROR, cpuConsumer2->lockNextBuffer(&buffer2));
+}
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/tests/TransactionTestHarnesses.h b/services/surfaceflinger/tests/TransactionTestHarnesses.h
index 67a5247..c91f1ea 100644
--- a/services/surfaceflinger/tests/TransactionTestHarnesses.h
+++ b/services/surfaceflinger/tests/TransactionTestHarnesses.h
@@ -17,7 +17,6 @@
#define ANDROID_TRANSACTION_TEST_HARNESSES
#include <com_android_graphics_libgui_flags.h>
-#include <common/FlagManager.h>
#include <ui/DisplayState.h>
#include "LayerTransactionTest.h"
@@ -49,7 +48,11 @@
ui::DisplayMode displayMode;
SurfaceComposerClient::getActiveDisplayMode(displayToken, &displayMode);
- const ui::Size& resolution = displayMode.resolution;
+ ui::Size resolution = displayMode.resolution;
+ if (displayState.orientation == ui::Rotation::Rotation90 ||
+ displayState.orientation == ui::Rotation::Rotation270) {
+ std::swap(resolution.width, resolution.height);
+ }
sp<IBinder> vDisplay;
@@ -59,7 +62,7 @@
GRALLOC_USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_SW_READ_OFTEN);
sp<BufferListener> listener = sp<BufferListener>::make(this);
itemConsumer->setFrameAvailableListener(listener);
- itemConsumer->setName(String8("Virtual disp consumer"));
+ itemConsumer->setName(String8("Virtual disp consumer (TransactionTest)"));
itemConsumer->setDefaultBufferSize(resolution.getWidth(), resolution.getHeight());
#else
sp<IGraphicBufferProducer> producer;
@@ -67,7 +70,7 @@
sp<BufferItemConsumer> itemConsumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->setConsumerName(String8("Virtual disp consumer"));
+ consumer->setConsumerName(String8("Virtual disp consumer (TransactionTest)"));
consumer->setDefaultBufferSize(resolution.getWidth(), resolution.getHeight());
itemConsumer = sp<BufferItemConsumer>::make(consumer,
@@ -94,14 +97,10 @@
#else
t.setDisplaySurface(vDisplay, producer);
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
- t.setDisplayProjection(vDisplay, displayState.orientation,
- Rect(displayState.layerStackSpaceRect), Rect(resolution));
- if (FlagManager::getInstance().ce_fence_promise()) {
- t.setDisplayLayerStack(vDisplay, layerStack);
- t.setLayerStack(mirrorSc, layerStack);
- } else {
- t.setDisplayLayerStack(vDisplay, ui::DEFAULT_LAYER_STACK);
- }
+ t.setDisplayProjection(vDisplay, ui::Rotation::Rotation0, Rect(resolution),
+ Rect(resolution));
+ t.setDisplayLayerStack(vDisplay, layerStack);
+ t.setLayerStack(mirrorSc, layerStack);
t.apply();
SurfaceComposerClient::Transaction().apply(true);
@@ -121,10 +120,8 @@
// CompositionEngine::present may attempt to be called on the same
// display multiple times. The layerStack is set to invalid here so
// that the display is ignored if that scenario occurs.
- if (FlagManager::getInstance().ce_fence_promise()) {
- t.setLayerStack(mirrorSc, ui::INVALID_LAYER_STACK);
- t.apply(true);
- }
+ t.setLayerStack(mirrorSc, ui::INVALID_LAYER_STACK);
+ t.apply(true);
SurfaceComposerClient::destroyVirtualDisplay(vDisplay);
return sc;
}
diff --git a/services/surfaceflinger/tests/VirtualDisplay_test.cpp b/services/surfaceflinger/tests/VirtualDisplay_test.cpp
index d69378c..1108c7f 100644
--- a/services/surfaceflinger/tests/VirtualDisplay_test.cpp
+++ b/services/surfaceflinger/tests/VirtualDisplay_test.cpp
@@ -29,14 +29,14 @@
void SetUp() override {
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
mGLConsumer = sp<GLConsumer>::make(GLConsumer::TEXTURE_EXTERNAL, true, false, false);
- mGLConsumer->setName(String8("Virtual disp consumer"));
+ mGLConsumer->setName(String8("Virtual disp consumer (VirtualDisplayTest)"));
mGLConsumer->setDefaultBufferSize(100, 100);
mProducer = mGLConsumer->getSurface()->getIGraphicBufferProducer();
#else
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&mProducer, &consumer);
- consumer->setConsumerName(String8("Virtual disp consumer"));
+ consumer->setConsumerName(String8("Virtual disp consumer (VirtualDisplayTest)"));
consumer->setDefaultBufferSize(100, 100);
mGLConsumer = sp<GLConsumer>::make(consumer, GLConsumer::TEXTURE_EXTERNAL, true, false);
diff --git a/services/surfaceflinger/tests/WindowInfosListener_test.cpp b/services/surfaceflinger/tests/WindowInfosListener_test.cpp
index ad9a674..2dd0dd9 100644
--- a/services/surfaceflinger/tests/WindowInfosListener_test.cpp
+++ b/services/surfaceflinger/tests/WindowInfosListener_test.cpp
@@ -50,9 +50,9 @@
TEST_F(WindowInfosListenerTest, WindowInfoAddedAndRemoved) {
std::string name = "Test Layer";
sp<IBinder> token = sp<BBinder>::make();
- WindowInfo windowInfo;
- windowInfo.name = name;
- windowInfo.token = token;
+ auto windowInfo = sp<gui::WindowInfoHandle>::make();
+ windowInfo->editInfo()->name = name;
+ windowInfo->editInfo()->token = token;
sp<SurfaceControl> surfaceControl =
mClient->createSurface(String8(name.c_str()), 100, 100, PIXEL_FORMAT_RGBA_8888,
ISurfaceComposerClient::eFXSurfaceBufferState);
@@ -65,14 +65,14 @@
.apply();
auto windowPresent = [&](const std::vector<WindowInfo>& windowInfos) {
- return findMatchingWindowInfo(windowInfo, windowInfos);
+ return findMatchingWindowInfo(*windowInfo->getInfo(), windowInfos);
};
ASSERT_TRUE(waitForWindowInfosPredicate(windowPresent));
Transaction().reparent(surfaceControl, nullptr).apply();
auto windowNotPresent = [&](const std::vector<WindowInfo>& windowInfos) {
- return !findMatchingWindowInfo(windowInfo, windowInfos);
+ return !findMatchingWindowInfo(*windowInfo->getInfo(), windowInfos);
};
ASSERT_TRUE(waitForWindowInfosPredicate(windowNotPresent));
}
@@ -80,9 +80,9 @@
TEST_F(WindowInfosListenerTest, WindowInfoChanged) {
std::string name = "Test Layer";
sp<IBinder> token = sp<BBinder>::make();
- WindowInfo windowInfo;
- windowInfo.name = name;
- windowInfo.token = token;
+ auto windowInfo = sp<gui::WindowInfoHandle>::make();
+ windowInfo->editInfo()->name = name;
+ windowInfo->editInfo()->token = token;
sp<SurfaceControl> surfaceControl =
mClient->createSurface(String8(name.c_str()), 100, 100, PIXEL_FORMAT_RGBA_8888,
ISurfaceComposerClient::eFXSurfaceBufferState);
@@ -96,7 +96,7 @@
.apply();
auto windowIsPresentAndTouchableRegionEmpty = [&](const std::vector<WindowInfo>& windowInfos) {
- auto foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos);
+ auto foundWindowInfo = findMatchingWindowInfo(*windowInfo->getInfo(), windowInfos);
if (!foundWindowInfo) {
return false;
}
@@ -104,19 +104,19 @@
};
ASSERT_TRUE(waitForWindowInfosPredicate(windowIsPresentAndTouchableRegionEmpty));
- windowInfo.addTouchableRegion({0, 0, 50, 50});
+ windowInfo->editInfo()->addTouchableRegion({0, 0, 50, 50});
Transaction().setInputWindowInfo(surfaceControl, windowInfo).apply();
auto windowIsPresentAndTouchableRegionMatches =
[&](const std::vector<WindowInfo>& windowInfos) {
- auto foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos);
+ auto foundWindowInfo = findMatchingWindowInfo(*windowInfo->getInfo(), windowInfos);
if (!foundWindowInfo) {
return false;
}
auto touchableRegion =
foundWindowInfo->transform.transform(foundWindowInfo->touchableRegion);
- return touchableRegion.hasSameRects(windowInfo.touchableRegion);
+ return touchableRegion.hasSameRects(windowInfo->getInfo()->touchableRegion);
};
ASSERT_TRUE(waitForWindowInfosPredicate(windowIsPresentAndTouchableRegionMatches));
}
diff --git a/services/surfaceflinger/tests/benchmarks/LayerLifecycleManager_benchmarks.cpp b/services/surfaceflinger/tests/benchmarks/LayerLifecycleManager_benchmarks.cpp
index 7641a45..0925118 100644
--- a/services/surfaceflinger/tests/benchmarks/LayerLifecycleManager_benchmarks.cpp
+++ b/services/surfaceflinger/tests/benchmarks/LayerLifecycleManager_benchmarks.cpp
@@ -50,7 +50,7 @@
layers.emplace_back(LayerLifecycleManagerHelper::rootLayer(1));
lifecycleManager.addLayers(std::move(layers));
lifecycleManager.commitChanges();
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
auto& transactionState = transactions.back().states.front();
@@ -74,7 +74,7 @@
std::vector<std::unique_ptr<RequestedLayerState>> layers;
layers.emplace_back(LayerLifecycleManagerHelper::rootLayer(1));
lifecycleManager.addLayers(std::move(layers));
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
auto& transactionState = transactions.back().states.front();
diff --git a/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h b/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h
index b472047..7910e77 100644
--- a/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h
+++ b/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h
@@ -66,8 +66,8 @@
/*mirror=*/UNASSIGNED_LAYER_ID));
}
- static std::vector<TransactionState> setZTransaction(uint32_t id, int32_t z) {
- std::vector<TransactionState> transactions;
+ static std::vector<QueuedTransactionState> setZTransaction(uint32_t id, int32_t z) {
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -109,8 +109,9 @@
mLifecycleManager.addLayers(std::move(layers));
}
- std::vector<TransactionState> reparentLayerTransaction(uint32_t id, uint32_t newParentId) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> reparentLayerTransaction(uint32_t id,
+ uint32_t newParentId) {
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
transactions.back().states.front().parentId = newParentId;
@@ -124,8 +125,9 @@
mLifecycleManager.applyTransactions(reparentLayerTransaction(id, newParentId));
}
- std::vector<TransactionState> relativeLayerTransaction(uint32_t id, uint32_t relativeParentId) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> relativeLayerTransaction(uint32_t id,
+ uint32_t relativeParentId) {
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
transactions.back().states.front().relativeParentId = relativeParentId;
@@ -139,7 +141,7 @@
}
void removeRelativeZ(uint32_t id) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
transactions.back().states.front().state.what = layer_state_t::eLayerChanged;
@@ -148,7 +150,7 @@
}
void setPosition(uint32_t id, float x, float y) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
transactions.back().states.front().state.what = layer_state_t::ePositionChanged;
@@ -167,7 +169,7 @@
}
void updateBackgroundColor(uint32_t id, half alpha) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
transactions.back().states.front().state.what = layer_state_t::eBackgroundColorChanged;
@@ -183,7 +185,7 @@
}
void setCrop(uint32_t id, const FloatRect& crop) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -196,7 +198,7 @@
void setCrop(uint32_t id, const Rect& crop) { setCrop(id, crop.toFloatRect()); }
void setFlags(uint32_t id, uint32_t mask, uint32_t flags) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -208,7 +210,7 @@
}
void setAlpha(uint32_t id, float alpha) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -218,6 +220,17 @@
mLifecycleManager.applyTransactions(transactions);
}
+ void setAutoRefresh(uint32_t id, bool autoRefresh) {
+ std::vector<QueuedTransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eAutoRefreshChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.autoRefresh = autoRefresh;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
void hideLayer(uint32_t id) {
setFlags(id, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden);
}
@@ -225,7 +238,7 @@
void showLayer(uint32_t id) { setFlags(id, layer_state_t::eLayerHidden, 0); }
void setColor(uint32_t id, half3 rgb = half3(1._hf, 1._hf, 1._hf)) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
transactions.back().states.front().state.what = layer_state_t::eColorChanged;
@@ -235,7 +248,7 @@
}
void setLayerStack(uint32_t id, int32_t layerStack) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -246,7 +259,7 @@
}
void setTouchableRegion(uint32_t id, Region region) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -261,7 +274,7 @@
}
void setInputInfo(uint32_t id, std::function<void(gui::WindowInfo&)> configureInput) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -280,7 +293,7 @@
void setTouchableRegionCrop(uint32_t id, Region region, uint32_t touchCropId,
bool replaceTouchableRegionWithCrop) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -298,7 +311,7 @@
}
void setBackgroundBlurRadius(uint32_t id, uint32_t backgroundBlurRadius) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -309,7 +322,7 @@
}
void setFrameRateSelectionPriority(uint32_t id, int32_t priority) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -321,7 +334,7 @@
void setFrameRate(uint32_t id, float frameRate, int8_t compatibility,
int8_t changeFrameRateStrategy) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -334,7 +347,7 @@
}
void setFrameRate(uint32_t id, Layer::FrameRate framerate) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -347,7 +360,7 @@
}
void setFrameRateCategory(uint32_t id, int8_t frameRateCategory) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -358,7 +371,7 @@
}
void setFrameRateSelectionStrategy(uint32_t id, int8_t strategy) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -370,7 +383,7 @@
}
void setDefaultFrameRateCompatibility(uint32_t id, int8_t defaultFrameRateCompatibility) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -383,7 +396,7 @@
}
void setRoundedCorners(uint32_t id, float radius) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -394,7 +407,7 @@
}
void setBuffer(uint32_t id, std::shared_ptr<renderengine::ExternalTexture> texture) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -427,7 +440,7 @@
}
void setBufferCrop(uint32_t id, const Rect& bufferCrop) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -438,7 +451,7 @@
}
void setDamageRegion(uint32_t id, const Region& damageRegion) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -449,7 +462,7 @@
}
void setDataspace(uint32_t id, ui::Dataspace dataspace) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -462,7 +475,7 @@
void setMatrix(uint32_t id, float dsdx, float dtdx, float dtdy, float dsdy) {
layer_state_t::matrix22_t matrix{dsdx, dtdx, dtdy, dsdy};
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -472,8 +485,20 @@
mLifecycleManager.applyTransactions(transactions);
}
+ void setClientDrawnCornerRadius(uint32_t id, float clientDrawnCornerRadius) {
+ std::vector<QueuedTransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what =
+ layer_state_t::eClientDrawnCornerRadiusChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.clientDrawnCornerRadius = clientDrawnCornerRadius;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
void setShadowRadius(uint32_t id, float shadowRadius) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -484,7 +509,7 @@
}
void setTrustedOverlay(uint32_t id, gui::TrustedOverlay trustedOverlay) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -495,7 +520,7 @@
}
void setDropInputMode(uint32_t id, gui::DropInputMode dropInputMode) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
@@ -506,7 +531,7 @@
}
void setGameMode(uint32_t id, gui::GameMode gameMode) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
transactions.back().states.front().state.what = layer_state_t::eMetadataChanged;
@@ -518,7 +543,7 @@
}
void setEdgeExtensionEffect(uint32_t id, int edge) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
diff --git a/services/surfaceflinger/tests/tracing/Android.bp b/services/surfaceflinger/tests/tracing/Android.bp
index bce1406..6eb7f4a 100644
--- a/services/surfaceflinger/tests/tracing/Android.bp
+++ b/services/surfaceflinger/tests/tracing/Android.bp
@@ -35,9 +35,6 @@
":libsurfaceflinger_mock_sources",
"TransactionTraceTestSuite.cpp",
],
- static_libs: [
- "libc++fs",
- ],
header_libs: [
"libsurfaceflinger_mocks_headers",
],
diff --git a/services/surfaceflinger/tests/unittests/ActivePictureTrackerTest.cpp b/services/surfaceflinger/tests/unittests/ActivePictureTrackerTest.cpp
new file mode 100644
index 0000000..8011309
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/ActivePictureTrackerTest.cpp
@@ -0,0 +1,482 @@
+/*
+ * Copyright 2024 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 <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <android/gui/ActivePicture.h>
+#include <android/gui/IActivePictureListener.h>
+#include <compositionengine/mock/CompositionEngine.h>
+#include <mock/DisplayHardware/MockComposer.h>
+#include <mock/MockLayer.h>
+#include <renderengine/mock/RenderEngine.h>
+
+#include "ActivePictureTracker.h"
+#include "LayerFE.h"
+#include "TestableSurfaceFlinger.h"
+
+namespace android {
+
+using android::compositionengine::LayerFECompositionState;
+using android::gui::ActivePicture;
+using android::gui::IActivePictureListener;
+using android::mock::MockLayer;
+using surfaceflinger::frontend::LayerSnapshot;
+using testing::_;
+using testing::NiceMock;
+using testing::Return;
+using testing::SizeIs;
+using testing::StrictMock;
+
+class TestableLayerFE : public LayerFE {
+public:
+ TestableLayerFE() : LayerFE("TestableLayerFE"), snapshot(*(new LayerSnapshot)) {
+ mSnapshot = std::unique_ptr<LayerSnapshot>(&snapshot);
+ }
+
+ LayerSnapshot& snapshot;
+};
+
+class MockActivePictureListener : public gui::BnActivePictureListener {
+public:
+ operator ActivePictureTracker::Listeners const() {
+ return {sp<IActivePictureListener>::fromExisting(this)};
+ }
+
+ MOCK_METHOD(binder::Status, onActivePicturesChanged, (const std::vector<ActivePicture>&),
+ (override));
+};
+
+class ActivePictureTrackerTest : public testing::Test {
+protected:
+ const static ActivePictureTracker::Listeners NO_LISTENERS;
+
+ SurfaceFlinger* flinger() {
+ if (!mFlingerSetup) {
+ mFlinger.setupMockScheduler();
+ mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>());
+ mFlinger.setupRenderEngine(std::make_unique<renderengine::mock::RenderEngine>());
+ mFlingerSetup = true;
+ }
+ return mFlinger.flinger();
+ }
+
+ sp<NiceMock<MockLayer>> createMockLayer(int layerId, int ownerUid) {
+ auto layer = sp<NiceMock<MockLayer>>::make(flinger(), layerId);
+ EXPECT_CALL(*layer, getOwnerUid()).WillRepeatedly(Return(uid_t(ownerUid)));
+ return layer;
+ }
+
+ sp<StrictMock<MockActivePictureListener>> createMockListener() {
+ return sp<StrictMock<MockActivePictureListener>>::make();
+ }
+
+ ActivePictureTracker::Listeners mListenersToAdd;
+ ActivePictureTracker::Listeners mListenersToRemove;
+
+private:
+ TestableSurfaceFlinger mFlinger;
+ bool mFlingerSetup = false;
+};
+
+const ActivePictureTracker::Listeners ActivePictureTrackerTest::NO_LISTENERS;
+
+// Hack to workaround initializer lists not working for parcelables because parcelables inherit from
+// Parcelable, which has a virtual destructor.
+auto UnorderedElementsAre(std::initializer_list<std::tuple<int32_t, int32_t, int64_t>> tuples) {
+ std::vector<ActivePicture> activePictures;
+ for (auto tuple : tuples) {
+ ActivePicture ap;
+ ap.layerId = std::get<0>(tuple);
+ ap.ownerUid = std::get<1>(tuple);
+ ap.pictureProfileId = std::get<2>(tuple);
+ activePictures.push_back(ap);
+ }
+ return testing::UnorderedElementsAreArray(activePictures);
+}
+
+// Parcelables don't define this for matchers, which is unfortunate
+void PrintTo(const ActivePicture& activePicture, std::ostream* os) {
+ *os << activePicture.toString();
+}
+
+TEST_F(ActivePictureTrackerTest, whenListenerAdded_called) {
+ ActivePictureTracker tracker;
+ auto listener = createMockListener();
+ EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(0))).Times(1);
+ tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
+}
+
+TEST_F(ActivePictureTrackerTest, whenListenerAdded_withListenerAlreadyAdded_notCalled) {
+ ActivePictureTracker tracker;
+ auto listener = createMockListener();
+ {
+ EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(0))).Times(1);
+ tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
+ }
+ {
+ EXPECT_CALL(*listener, onActivePicturesChanged(_)).Times(0);
+ tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
+ }
+}
+
+TEST_F(ActivePictureTrackerTest, whenListenerAdded_withUncommittedProfile_calledWithNone) {
+ auto layer = createMockLayer(100, 10);
+ TestableLayerFE layerFE;
+
+ ActivePictureTracker tracker;
+ {
+ layerFE.snapshot.pictureProfileHandle = PictureProfileHandle(1);
+ tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
+ tracker.updateAndNotifyListeners(NO_LISTENERS, NO_LISTENERS);
+ }
+ {
+ auto listener = createMockListener();
+ EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(0))).Times(1);
+ tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
+ }
+}
+
+TEST_F(ActivePictureTrackerTest, whenListenerAdded_withCommittedProfile_calledWithActivePicture) {
+ auto layer = createMockLayer(100, 10);
+ TestableLayerFE layerFE;
+
+ ActivePictureTracker tracker;
+ {
+ layerFE.snapshot.pictureProfileHandle = PictureProfileHandle(1);
+ layerFE.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
+
+ auto listener = createMockListener();
+ EXPECT_CALL(*listener, onActivePicturesChanged(_))
+ .WillOnce([](const std::vector<gui::ActivePicture>& activePictures) {
+ EXPECT_THAT(activePictures, UnorderedElementsAre({{100, 10, 1}}));
+ return binder::Status::ok();
+ });
+ tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
+ }
+}
+
+TEST_F(ActivePictureTrackerTest, whenProfileAdded_calledWithActivePicture) {
+ auto layer = createMockLayer(100, 10);
+ TestableLayerFE layerFE;
+
+ ActivePictureTracker tracker;
+ auto listener = createMockListener();
+ {
+ tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
+
+ EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(0))).Times(1);
+ tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
+ }
+ {
+ layerFE.snapshot.pictureProfileHandle = PictureProfileHandle(1);
+ layerFE.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
+
+ EXPECT_CALL(*listener, onActivePicturesChanged(_))
+ .WillOnce([](const std::vector<gui::ActivePicture>& activePictures) {
+ EXPECT_THAT(activePictures, UnorderedElementsAre({{100, 10, 1}}));
+ return binder::Status::ok();
+ });
+ tracker.updateAndNotifyListeners(NO_LISTENERS, NO_LISTENERS);
+ }
+}
+
+TEST_F(ActivePictureTrackerTest, whenContinuesUsingProfile_notCalled) {
+ auto layer = createMockLayer(100, 10);
+ TestableLayerFE layerFE;
+
+ ActivePictureTracker tracker;
+ auto listener = createMockListener();
+ {
+ layerFE.snapshot.pictureProfileHandle = PictureProfileHandle(1);
+ layerFE.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
+
+ EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(1))).Times(1);
+ tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
+ }
+ {
+ layerFE.snapshot.pictureProfileHandle = PictureProfileHandle(1);
+ layerFE.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
+
+ EXPECT_CALL(*listener, onActivePicturesChanged(_)).Times(0);
+ tracker.updateAndNotifyListeners(NO_LISTENERS, NO_LISTENERS);
+ }
+}
+
+TEST_F(ActivePictureTrackerTest, whenProfileIsRemoved_calledWithNoActivePictures) {
+ auto layer = createMockLayer(100, 10);
+ TestableLayerFE layerFE;
+
+ ActivePictureTracker tracker;
+ auto listener = createMockListener();
+ {
+ layerFE.snapshot.pictureProfileHandle = PictureProfileHandle(1);
+ layerFE.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
+
+ EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(1))).Times(1);
+ tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
+ }
+ {
+ layerFE.snapshot.pictureProfileHandle = PictureProfileHandle::NONE;
+ tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
+
+ EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(0))).Times(1);
+ tracker.updateAndNotifyListeners(NO_LISTENERS, NO_LISTENERS);
+ }
+}
+
+TEST_F(ActivePictureTrackerTest, whenProfileIsNotCommitted_calledWithNoActivePictures) {
+ auto layer = createMockLayer(100, 10);
+ TestableLayerFE layerFE;
+
+ ActivePictureTracker tracker;
+ auto listener = createMockListener();
+ {
+ layerFE.snapshot.pictureProfileHandle = PictureProfileHandle(1);
+ layerFE.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
+
+ EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(1))).Times(1);
+ tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
+ }
+ {
+ layerFE.snapshot.pictureProfileHandle = PictureProfileHandle(1);
+ tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
+
+ EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(0))).Times(1);
+ tracker.updateAndNotifyListeners(NO_LISTENERS, NO_LISTENERS);
+ }
+}
+
+TEST_F(ActivePictureTrackerTest, whenProfileChanges_calledWithDifferentProfile) {
+ auto layer = createMockLayer(100, 10);
+ TestableLayerFE layerFE;
+
+ ActivePictureTracker tracker;
+ auto listener = createMockListener();
+ {
+ layerFE.snapshot.pictureProfileHandle = PictureProfileHandle(1);
+ layerFE.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
+
+ EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(1)))
+ .WillOnce([](const std::vector<gui::ActivePicture>& activePictures) {
+ EXPECT_THAT(activePictures, UnorderedElementsAre({{100, 10, 1}}));
+ return binder::Status::ok();
+ });
+ tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
+ }
+ {
+ layerFE.snapshot.pictureProfileHandle = PictureProfileHandle(2);
+ layerFE.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer, layerFE, layerFE.stealCompositionResult());
+
+ EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(1)))
+ .WillOnce([](const std::vector<gui::ActivePicture>& activePictures) {
+ EXPECT_THAT(activePictures, UnorderedElementsAre({{100, 10, 2}}));
+ return binder::Status::ok();
+ });
+ tracker.updateAndNotifyListeners(NO_LISTENERS, NO_LISTENERS);
+ }
+}
+
+TEST_F(ActivePictureTrackerTest, whenMultipleCommittedProfiles_calledWithMultipleActivePictures) {
+ auto layer1 = createMockLayer(100, 10);
+ TestableLayerFE layerFE1;
+
+ auto layer2 = createMockLayer(200, 20);
+ TestableLayerFE layerFE2;
+
+ ActivePictureTracker tracker;
+ auto listener = createMockListener();
+ {
+ layerFE1.snapshot.pictureProfileHandle = PictureProfileHandle(1);
+ layerFE1.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer1, layerFE1, layerFE1.stealCompositionResult());
+
+ layerFE2.snapshot.pictureProfileHandle = PictureProfileHandle(2);
+ layerFE2.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer2, layerFE2, layerFE2.stealCompositionResult());
+
+ EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(2)))
+ .WillOnce([](const std::vector<gui::ActivePicture>& activePictures) {
+ EXPECT_THAT(activePictures, UnorderedElementsAre({{100, 10, 1}, {200, 20, 2}}));
+ return binder::Status::ok();
+ });
+ tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
+ }
+}
+
+TEST_F(ActivePictureTrackerTest, whenNonCommittedProfileChanges_notCalled) {
+ auto layer1 = createMockLayer(100, 10);
+ TestableLayerFE layerFE1;
+
+ auto layer2 = createMockLayer(200, 20);
+ TestableLayerFE layerFE2;
+
+ ActivePictureTracker tracker;
+ auto listener = createMockListener();
+ {
+ layerFE1.snapshot.pictureProfileHandle = PictureProfileHandle(1);
+ layerFE1.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer1, layerFE1, layerFE1.stealCompositionResult());
+
+ layerFE2.snapshot.pictureProfileHandle = PictureProfileHandle(1);
+ tracker.onLayerComposed(*layer2, layerFE2, layerFE2.stealCompositionResult());
+
+ EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(1))).Times(1);
+ tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
+ }
+ {
+ layerFE1.snapshot.pictureProfileHandle = PictureProfileHandle(1);
+ layerFE1.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer1, layerFE1, layerFE1.stealCompositionResult());
+
+ layerFE2.snapshot.pictureProfileHandle = PictureProfileHandle(2);
+ tracker.onLayerComposed(*layer2, layerFE2, layerFE2.stealCompositionResult());
+
+ EXPECT_CALL(*listener, onActivePicturesChanged(_)).Times(0);
+ tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
+ }
+}
+
+TEST_F(ActivePictureTrackerTest, whenDifferentLayerUsesSameProfile_called) {
+ auto layer1 = createMockLayer(100, 10);
+ TestableLayerFE layerFE1;
+
+ auto layer2 = createMockLayer(200, 20);
+ TestableLayerFE layerFE2;
+
+ ActivePictureTracker tracker;
+ auto listener = createMockListener();
+ {
+ layerFE1.snapshot.pictureProfileHandle = PictureProfileHandle(1);
+ layerFE1.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer1, layerFE1, layerFE1.stealCompositionResult());
+
+ layerFE2.snapshot.pictureProfileHandle = PictureProfileHandle(2);
+ layerFE2.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer2, layerFE2, layerFE2.stealCompositionResult());
+
+ EXPECT_CALL(*listener, onActivePicturesChanged(_))
+ .WillOnce([](const std::vector<gui::ActivePicture>& activePictures) {
+ EXPECT_THAT(activePictures, UnorderedElementsAre({{100, 10, 1}, {200, 20, 2}}));
+ return binder::Status::ok();
+ });
+ tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
+ }
+ {
+ layerFE1.snapshot.pictureProfileHandle = PictureProfileHandle(2);
+ layerFE1.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer1, layerFE1, layerFE1.stealCompositionResult());
+
+ layerFE2.snapshot.pictureProfileHandle = PictureProfileHandle(1);
+ layerFE2.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer2, layerFE2, layerFE2.stealCompositionResult());
+
+ EXPECT_CALL(*listener, onActivePicturesChanged(_))
+ .WillOnce([](const std::vector<gui::ActivePicture>& activePictures) {
+ EXPECT_THAT(activePictures, UnorderedElementsAre({{100, 10, 2}, {200, 20, 1}}));
+ return binder::Status::ok();
+ });
+ tracker.updateAndNotifyListeners(NO_LISTENERS, NO_LISTENERS);
+ }
+}
+
+TEST_F(ActivePictureTrackerTest, whenSameUidDifferentLayerUsesSameProfile_called) {
+ auto layer1 = createMockLayer(100, 10);
+ TestableLayerFE layerFE1;
+
+ auto layer2 = createMockLayer(200, 10);
+ TestableLayerFE layerFE2;
+
+ ActivePictureTracker tracker;
+ auto listener = createMockListener();
+ {
+ layerFE1.snapshot.pictureProfileHandle = PictureProfileHandle(1);
+ layerFE1.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer1, layerFE1, layerFE1.stealCompositionResult());
+
+ layerFE2.snapshot.pictureProfileHandle = PictureProfileHandle(2);
+ layerFE2.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer2, layerFE2, layerFE2.stealCompositionResult());
+
+ EXPECT_CALL(*listener, onActivePicturesChanged(_))
+ .WillOnce([](const std::vector<gui::ActivePicture>& activePictures) {
+ EXPECT_THAT(activePictures, UnorderedElementsAre({{100, 10, 1}, {200, 10, 2}}));
+ return binder::Status::ok();
+ });
+ tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
+ }
+ {
+ layerFE1.snapshot.pictureProfileHandle = PictureProfileHandle(2);
+ layerFE1.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer1, layerFE1, layerFE1.stealCompositionResult());
+
+ layerFE2.snapshot.pictureProfileHandle = PictureProfileHandle(1);
+ layerFE2.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer2, layerFE2, layerFE2.stealCompositionResult());
+
+ EXPECT_CALL(*listener, onActivePicturesChanged(_))
+ .WillOnce([](const std::vector<gui::ActivePicture>& activePictures) {
+ EXPECT_THAT(activePictures, UnorderedElementsAre({{100, 10, 2}, {200, 10, 1}}));
+ return binder::Status::ok();
+ });
+ tracker.updateAndNotifyListeners(NO_LISTENERS, NO_LISTENERS);
+ }
+}
+
+TEST_F(ActivePictureTrackerTest, whenNewLayerUsesSameProfile_called) {
+ auto layer1 = createMockLayer(100, 10);
+ TestableLayerFE layerFE1;
+
+ ActivePictureTracker tracker;
+ auto listener = createMockListener();
+ {
+ layerFE1.snapshot.pictureProfileHandle = PictureProfileHandle(1);
+ layerFE1.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer1, layerFE1, layerFE1.stealCompositionResult());
+
+ EXPECT_CALL(*listener, onActivePicturesChanged(SizeIs(1))).Times(1);
+ tracker.updateAndNotifyListeners(*listener, NO_LISTENERS);
+ }
+
+ auto layer2 = createMockLayer(200, 10);
+ TestableLayerFE layerFE2;
+ {
+ layerFE1.snapshot.pictureProfileHandle = PictureProfileHandle(1);
+ layerFE1.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer1, layerFE1, layerFE1.stealCompositionResult());
+
+ layerFE2.snapshot.pictureProfileHandle = PictureProfileHandle(1);
+ layerFE2.onPictureProfileCommitted();
+ tracker.onLayerComposed(*layer2, layerFE2, layerFE2.stealCompositionResult());
+
+ EXPECT_CALL(*listener, onActivePicturesChanged(_))
+ .WillOnce([](const std::vector<gui::ActivePicture>& activePictures) {
+ EXPECT_THAT(activePictures, UnorderedElementsAre({{100, 10, 1}, {200, 10, 1}}));
+ return binder::Status::ok();
+ });
+ tracker.updateAndNotifyListeners(NO_LISTENERS, NO_LISTENERS);
+ }
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index f1bd87c..f1c1549 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -22,24 +22,52 @@
default_team: "trendy_team_android_core_graphics_stack",
}
+// This is a step towards pulling out the "backend" sources to clean up the
+// dependency graph between CompositionEngine and SurfaceFlinger.
+// MockNativeWindow doesn't strictly belong here, but this works for now so
+// that CompositionEngine tests can use these mocks.
+filegroup {
+ name: "libsurfaceflinger_backend_mock_sources",
+ srcs: [
+ ":poweradvisor_mock_sources",
+ "mock/DisplayHardware/MockComposer.cpp",
+ "mock/DisplayHardware/MockHWC2.cpp",
+ "mock/DisplayHardware/MockHWComposer.cpp",
+ "mock/system/window/MockNativeWindow.cpp",
+ ],
+}
+
+cc_library_headers {
+ name: "libsurfaceflinger_backend_mock_headers",
+ export_include_dirs: ["."],
+ static_libs: [
+ "libgmock",
+ "libgtest",
+ ],
+ export_static_lib_headers: [
+ "libgmock",
+ "libgtest",
+ ],
+}
+
+filegroup {
+ name: "poweradvisor_mock_sources",
+ srcs: [
+ "mock/PowerAdvisor/*.cpp",
+ ],
+}
+
filegroup {
name: "libsurfaceflinger_mock_sources",
srcs: [
- "mock/DisplayHardware/MockPowerHalController.cpp",
- "mock/DisplayHardware/MockComposer.cpp",
- "mock/DisplayHardware/MockHWC2.cpp",
- "mock/DisplayHardware/MockIPower.cpp",
- "mock/DisplayHardware/MockPowerHintSessionWrapper.cpp",
- "mock/DisplayHardware/MockPowerAdvisor.cpp",
"mock/MockEventThread.cpp",
"mock/MockFrameTimeline.cpp",
"mock/MockFrameTracer.cpp",
"mock/MockNativeWindowSurface.cpp",
"mock/MockTimeStats.cpp",
- "mock/MockVsyncController.cpp",
"mock/MockVSyncDispatch.cpp",
"mock/MockVSyncTracker.cpp",
- "mock/system/window/MockNativeWindow.cpp",
+ "mock/MockVsyncController.cpp",
],
}
@@ -57,84 +85,12 @@
"surfaceflinger_defaults",
],
test_suites: ["device-tests"],
- static_libs: ["libc++fs"],
header_libs: ["surfaceflinger_tests_common_headers"],
srcs: [
+ "*.cpp",
+ ":libsurfaceflinger_backend_mock_sources",
":libsurfaceflinger_mock_sources",
":libsurfaceflinger_sources",
- "libsurfaceflinger_unittest_main.cpp",
- "ActiveDisplayRotationFlagsTest.cpp",
- "BackgroundExecutorTest.cpp",
- "CommitTest.cpp",
- "CompositionTest.cpp",
- "DaltonizerTest.cpp",
- "DisplayIdGeneratorTest.cpp",
- "DisplayTransactionTest.cpp",
- "DisplayDevice_GetBestColorModeTest.cpp",
- "DisplayDevice_SetDisplayBrightnessTest.cpp",
- "DisplayDevice_SetProjectionTest.cpp",
- "DisplayModeControllerTest.cpp",
- "EventThreadTest.cpp",
- "FlagManagerTest.cpp",
- "FpsReporterTest.cpp",
- "FpsTest.cpp",
- "FramebufferSurfaceTest.cpp",
- "FrameRateOverrideMappingsTest.cpp",
- "FrameTimelineTest.cpp",
- "HWComposerTest.cpp",
- "JankTrackerTest.cpp",
- "OneShotTimerTest.cpp",
- "LayerHistoryIntegrationTest.cpp",
- "LayerInfoTest.cpp",
- "LayerMetadataTest.cpp",
- "LayerHierarchyTest.cpp",
- "LayerLifecycleManagerTest.cpp",
- "LayerSnapshotTest.cpp",
- "LayerTestUtils.cpp",
- "MessageQueueTest.cpp",
- "PowerAdvisorTest.cpp",
- "SmallAreaDetectionAllowMappingsTest.cpp",
- "SurfaceFlinger_ColorMatrixTest.cpp",
- "SurfaceFlinger_CreateDisplayTest.cpp",
- "SurfaceFlinger_DestroyDisplayTest.cpp",
- "SurfaceFlinger_DisplayModeSwitching.cpp",
- "SurfaceFlinger_DisplayTransactionCommitTest.cpp",
- "SurfaceFlinger_ExcludeDolbyVisionTest.cpp",
- "SurfaceFlinger_FoldableTest.cpp",
- "SurfaceFlinger_GetDisplayNativePrimariesTest.cpp",
- "SurfaceFlinger_GetDisplayStatsTest.cpp",
- "SurfaceFlinger_HdrOutputControlTest.cpp",
- "SurfaceFlinger_HotplugTest.cpp",
- "SurfaceFlinger_InitializeDisplaysTest.cpp",
- "SurfaceFlinger_NotifyExpectedPresentTest.cpp",
- "SurfaceFlinger_NotifyPowerBoostTest.cpp",
- "SurfaceFlinger_PowerHintTest.cpp",
- "SurfaceFlinger_SetDisplayStateTest.cpp",
- "SurfaceFlinger_SetPowerModeInternalTest.cpp",
- "SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp",
- "SchedulerTest.cpp",
- "RefreshRateSelectorTest.cpp",
- "RefreshRateStatsTest.cpp",
- "RegionSamplingTest.cpp",
- "TestableScheduler.cpp",
- "TimeStatsTest.cpp",
- "FrameTracerTest.cpp",
- "TransactionApplicationTest.cpp",
- "TransactionFrameTracerTest.cpp",
- "TransactionProtoParserTest.cpp",
- "TransactionSurfaceFrameTest.cpp",
- "TransactionTraceWriterTest.cpp",
- "TransactionTracingTest.cpp",
- "TunnelModeEnabledReporterTest.cpp",
- "VSyncCallbackRegistrationTest.cpp",
- "VSyncDispatchTimerQueueTest.cpp",
- "VSyncDispatchRealtimeTest.cpp",
- "VsyncModulatorTest.cpp",
- "VSyncPredictorTest.cpp",
- "VSyncReactorTest.cpp",
- "VsyncConfigurationTest.cpp",
- "VsyncScheduleTest.cpp",
- "WindowInfosListenerInvokerTest.cpp",
],
}
@@ -147,6 +103,7 @@
"librenderengine_deps",
"libsurfaceflinger_common_test_deps",
"libsurfaceflinger_proto_deps",
+ "poweradvisor_deps",
],
static_libs: [
"android.hardware.common-V2-ndk",
@@ -160,9 +117,8 @@
"android.hardware.power@1.2",
"android.hardware.power@1.3",
"libaidlcommonsupport",
- "libcompositionengine_mocks",
"libcompositionengine",
- "libframetimeline",
+ "libcompositionengine_mocks",
"libgmock",
"libgui_mocks",
"libperfetto_client_experimental",
@@ -183,14 +139,15 @@
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.common@1.2",
+ "libEGL",
+ "libGLESv1_CM",
+ "libGLESv2",
+ "libSurfaceFlingerProp",
"libbase",
"libbinder",
"libbinder_ndk",
"libcutils",
- "libEGL",
"libfmq",
- "libGLESv1_CM",
- "libGLESv2",
"libgui",
"libhidlbase",
"libinput",
@@ -199,11 +156,11 @@
"libpowermanager",
"libprocessgroup",
"libprotobuf-cpp-lite",
- "libSurfaceFlingerProp",
+ "libstatslog_surfaceflinger",
"libsync",
+ "libtracing_perfetto",
"libui",
"libutils",
- "libtracing_perfetto",
],
header_libs: [
"android.hardware.graphics.composer3-command-buffer",
diff --git a/services/surfaceflinger/tests/unittests/BackgroundExecutorTest.cpp b/services/surfaceflinger/tests/unittests/BackgroundExecutorTest.cpp
index 5413bae..72d1351 100644
--- a/services/surfaceflinger/tests/unittests/BackgroundExecutorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/BackgroundExecutorTest.cpp
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2024 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 <gtest/gtest.h>
#include <condition_variable>
diff --git a/services/surfaceflinger/tests/unittests/CommitAndCompositeTest.h b/services/surfaceflinger/tests/unittests/CommitAndCompositeTest.h
index d4c801f..c858d9a 100644
--- a/services/surfaceflinger/tests/unittests/CommitAndCompositeTest.h
+++ b/services/surfaceflinger/tests/unittests/CommitAndCompositeTest.h
@@ -22,8 +22,8 @@
#include "TestableSurfaceFlinger.h"
#include "mock/DisplayHardware/MockComposer.h"
-#include "mock/DisplayHardware/MockPowerAdvisor.h"
#include "mock/MockTimeStats.h"
+#include "mock/PowerAdvisor/MockPowerAdvisor.h"
#include "mock/system/window/MockNativeWindow.h"
namespace android {
@@ -33,11 +33,11 @@
void SetUp() override {
mFlinger.setupMockScheduler({.displayId = DEFAULT_DISPLAY_ID});
mComposer = new Hwc2::mock::Composer();
- mPowerAdvisor = new Hwc2::mock::PowerAdvisor();
+ mPowerAdvisor = new adpf::mock::PowerAdvisor();
mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
mFlinger.setupTimeStats(std::shared_ptr<TimeStats>(mTimeStats));
mFlinger.setupComposer(std::unique_ptr<Hwc2::Composer>(mComposer));
- mFlinger.setupPowerAdvisor(std::unique_ptr<Hwc2::PowerAdvisor>(mPowerAdvisor));
+ mFlinger.setupPowerAdvisor(std::unique_ptr<adpf::PowerAdvisor>(mPowerAdvisor));
constexpr bool kIsPrimary = true;
FakeHwcDisplayInjector(DEFAULT_DISPLAY_ID, hal::DisplayType::PHYSICAL, kIsPrimary)
@@ -54,8 +54,8 @@
compositionengine::impl::createDisplay(mFlinger.getCompositionEngine(),
std::move(compostionEngineDisplayArgs));
mDisplay = FakeDisplayDeviceInjector(mFlinger, compositionDisplay,
- ui::DisplayConnectionType::Internal, HWC_DISPLAY,
- kIsPrimary)
+ ui::DisplayConnectionType::Internal,
+ DEFAULT_DISPLAY_PORT, HWC_DISPLAY, kIsPrimary)
.setDisplaySurface(mDisplaySurface)
.setNativeWindow(mNativeWindow)
.setPowerMode(hal::PowerMode::ON)
@@ -68,7 +68,9 @@
using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector;
static constexpr hal::HWDisplayId HWC_DISPLAY = FakeHwcDisplayInjector::DEFAULT_HWC_DISPLAY_ID;
- static constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId::fromPort(42u);
+ static constexpr uint8_t DEFAULT_DISPLAY_PORT = 42u;
+ static constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID =
+ PhysicalDisplayId::fromPort(DEFAULT_DISPLAY_PORT);
static constexpr int DEFAULT_DISPLAY_WIDTH = 1920;
static constexpr int DEFAULT_DISPLAY_HEIGHT = 1024;
@@ -79,7 +81,7 @@
sp<compositionengine::mock::DisplaySurface>::make();
sp<mock::NativeWindow> mNativeWindow = sp<mock::NativeWindow>::make();
mock::TimeStats* mTimeStats = new mock::TimeStats();
- Hwc2::mock::PowerAdvisor* mPowerAdvisor = nullptr;
+ adpf::mock::PowerAdvisor* mPowerAdvisor = nullptr;
Hwc2::mock::Composer* mComposer = nullptr;
};
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 4f72424..9ece312 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -36,14 +36,13 @@
#include <system/window.h>
#include <utils/String8.h>
-#include "DisplayRenderArea.h"
#include "Layer.h"
#include "TestableSurfaceFlinger.h"
#include "mock/DisplayHardware/MockComposer.h"
-#include "mock/DisplayHardware/MockPowerAdvisor.h"
#include "mock/MockEventThread.h"
#include "mock/MockTimeStats.h"
#include "mock/MockVsyncController.h"
+#include "mock/PowerAdvisor/MockPowerAdvisor.h"
#include "mock/system/window/MockNativeWindow.h"
namespace android {
@@ -76,7 +75,8 @@
constexpr hal::HWLayerId HWC_LAYER = 5000;
constexpr Transform DEFAULT_TRANSFORM = static_cast<Transform>(0);
-constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId::fromPort(42u);
+constexpr uint8_t DEFAULT_DISPLAY_PORT = 42u;
+constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId::fromPort(DEFAULT_DISPLAY_PORT);
constexpr int DEFAULT_DISPLAY_WIDTH = 1920;
constexpr int DEFAULT_DISPLAY_HEIGHT = 1024;
@@ -110,9 +110,9 @@
mFlinger.setupTimeStats(std::shared_ptr<TimeStats>(mTimeStats));
mComposer = new Hwc2::mock::Composer();
- mPowerAdvisor = new Hwc2::mock::PowerAdvisor();
+ mPowerAdvisor = new adpf::mock::PowerAdvisor();
mFlinger.setupComposer(std::unique_ptr<Hwc2::Composer>(mComposer));
- mFlinger.setupPowerAdvisor(std::unique_ptr<Hwc2::PowerAdvisor>(mPowerAdvisor));
+ mFlinger.setupPowerAdvisor(std::unique_ptr<adpf::PowerAdvisor>(mPowerAdvisor));
mFlinger.mutableMaxRenderTargetSize() = 16384;
}
@@ -158,7 +158,7 @@
Hwc2::mock::Composer* mComposer = nullptr;
renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
mock::TimeStats* mTimeStats = new mock::TimeStats();
- Hwc2::mock::PowerAdvisor* mPowerAdvisor = nullptr;
+ adpf::mock::PowerAdvisor* mPowerAdvisor = nullptr;
sp<Fence> mClientTargetAcquireFence = Fence::NO_FENCE;
@@ -198,25 +198,21 @@
const Rect sourceCrop(0, 0, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT);
constexpr bool regionSampling = false;
- auto renderArea =
- DisplayRenderArea::create(mDisplay, sourceCrop, sourceCrop.getSize(),
- ui::Dataspace::V0_SRGB,
- RenderArea::Options::CAPTURE_SECURE_LAYERS |
- RenderArea::Options::HINT_FOR_SEAMLESS_TRANSITION);
-
auto getLayerSnapshotsFn = mFlinger.getLayerSnapshotsForScreenshotsFn(mDisplay->getLayerStack(),
CaptureArgs::UNSET_UID);
const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
mCaptureScreenBuffer =
- std::make_shared<renderengine::mock::FakeExternalTexture>(renderArea->getReqWidth(),
- renderArea->getReqHeight(),
+ std::make_shared<renderengine::mock::FakeExternalTexture>(sourceCrop.getSize().width,
+ sourceCrop.getSize().height,
HAL_PIXEL_FORMAT_RGBA_8888, 1,
usage);
- auto future = mFlinger.renderScreenImpl(mDisplay, std::move(renderArea), getLayerSnapshotsFn,
- mCaptureScreenBuffer, regionSampling);
+ auto future = mFlinger.renderScreenImpl(mDisplay, sourceCrop, ui::Dataspace::V0_SRGB,
+ getLayerSnapshotsFn, mCaptureScreenBuffer,
+ regionSampling, mDisplay->isSecure(),
+ /* seamlessTransition */ true);
ASSERT_TRUE(future.valid());
const auto fenceResult = future.get();
@@ -276,7 +272,8 @@
test->mDisplay =
FakeDisplayDeviceInjector(test->mFlinger, compositionDisplay,
- kDisplayConnectionType, HWC_DISPLAY, kIsPrimary)
+ kDisplayConnectionType, DEFAULT_DISPLAY_PORT, HWC_DISPLAY,
+ kIsPrimary)
.setDisplaySurface(test->mDisplaySurface)
.setNativeWindow(test->mNativeWindow)
.setSecure(Derived::IS_SECURE)
diff --git a/services/surfaceflinger/tests/unittests/DisplayModeControllerTest.cpp b/services/surfaceflinger/tests/unittests/DisplayModeControllerTest.cpp
index d971150..84dc5fc 100644
--- a/services/surfaceflinger/tests/unittests/DisplayModeControllerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayModeControllerTest.cpp
@@ -20,6 +20,7 @@
#include "Display/DisplayModeController.h"
#include "Display/DisplaySnapshot.h"
#include "DisplayHardware/HWComposer.h"
+#include "DisplayHardware/Hal.h"
#include "DisplayIdentificationTestHelpers.h"
#include "FpsOps.h"
#include "mock/DisplayHardware/MockComposer.h"
@@ -66,11 +67,12 @@
setVsyncEnabled(kHwcDisplayId, hal::IComposerClient::Vsync::DISABLE));
EXPECT_CALL(*mComposerHal, onHotplugConnect(kHwcDisplayId));
- const auto infoOpt = mComposer->onHotplug(kHwcDisplayId, hal::Connection::CONNECTED);
+ const auto infoOpt =
+ mComposer->onHotplug(kHwcDisplayId, HWComposer::HotplugEvent::Connected);
ASSERT_TRUE(infoOpt);
mDisplayId = infoOpt->id;
- mDisplaySnapshotOpt.emplace(mDisplayId, ui::DisplayConnectionType::Internal,
+ mDisplaySnapshotOpt.emplace(mDisplayId, infoOpt->port, ui::DisplayConnectionType::Internal,
makeModes(kMode60, kMode90, kMode120), ui::ColorModes{},
std::nullopt);
@@ -103,7 +105,7 @@
EXPECT_CALL(*mComposerHal,
setActiveConfigWithConstraints(kHwcDisplayId, hwcModeId, constraints, _))
- .WillOnce(DoAll(SetArgPointee<3>(timeline), Return(hal::V2_4::Error::NONE)));
+ .WillOnce(DoAll(SetArgPointee<3>(timeline), Return(hal::Error::NONE)));
return constraints;
}
@@ -183,7 +185,8 @@
hal::VsyncPeriodChangeTimeline timeline;
const auto constraints = expectModeSet(modeRequest, timeline);
- EXPECT_TRUE(mDmc.initiateModeChange(mDisplayId, std::move(modeRequest), constraints, timeline));
+ EXPECT_EQ(DisplayModeController::ModeChangeResult::Changed,
+ mDmc.initiateModeChange(mDisplayId, std::move(modeRequest), constraints, timeline));
EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, mDmc.getPendingMode(mDisplayId));
mDmc.clearDesiredMode(mDisplayId);
@@ -210,7 +213,8 @@
hal::VsyncPeriodChangeTimeline timeline;
auto constraints = expectModeSet(modeRequest, timeline);
- EXPECT_TRUE(mDmc.initiateModeChange(mDisplayId, std::move(modeRequest), constraints, timeline));
+ EXPECT_EQ(DisplayModeController::ModeChangeResult::Changed,
+ mDmc.initiateModeChange(mDisplayId, std::move(modeRequest), constraints, timeline));
EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode90, mDmc.getPendingMode(mDisplayId));
// No action since a mode switch has already been initiated.
@@ -223,7 +227,8 @@
constexpr bool kSubsequent = true;
constraints = expectModeSet(modeRequest, timeline, kSubsequent);
- EXPECT_TRUE(mDmc.initiateModeChange(mDisplayId, std::move(modeRequest), constraints, timeline));
+ EXPECT_EQ(DisplayModeController::ModeChangeResult::Changed,
+ mDmc.initiateModeChange(mDisplayId, std::move(modeRequest), constraints, timeline));
EXPECT_DISPLAY_MODE_REQUEST(kDesiredMode120, mDmc.getPendingMode(mDisplayId));
mDmc.clearDesiredMode(mDisplayId);
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
index db3c0a1..4322af7 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
@@ -47,10 +47,10 @@
#include "TestableSurfaceFlinger.h"
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/DisplayHardware/MockDisplayMode.h"
-#include "mock/DisplayHardware/MockPowerAdvisor.h"
#include "mock/MockEventThread.h"
#include "mock/MockNativeWindowSurface.h"
#include "mock/MockVsyncController.h"
+#include "mock/PowerAdvisor/MockPowerAdvisor.h"
#include "mock/system/window/MockNativeWindow.h"
namespace android {
@@ -114,11 +114,15 @@
// Test instances
TestableSurfaceFlinger mFlinger;
+
sp<mock::NativeWindow> mNativeWindow = sp<mock::NativeWindow>::make();
+ sp<compositionengine::mock::DisplaySurface> mDisplaySurface =
+ sp<compositionengine::mock::DisplaySurface>::make();
+
sp<GraphicBuffer> mBuffer =
sp<GraphicBuffer>::make(1u, 1u, PIXEL_FORMAT_RGBA_8888,
GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_OFTEN);
- Hwc2::mock::PowerAdvisor mPowerAdvisor;
+ adpf::mock::PowerAdvisor mPowerAdvisor;
FakeDisplayInjector mFakeDisplayInjector{mFlinger, mPowerAdvisor, mNativeWindow};
@@ -193,7 +197,7 @@
}
};
-template <uint64_t displayId>
+template <VirtualDisplayId::BaseId displayId>
struct DisplayIdGetter<HalVirtualDisplayIdType<displayId>> {
static HalVirtualDisplayId get() { return HalVirtualDisplayId(displayId); }
};
@@ -231,6 +235,16 @@
static constexpr std::optional<HWDisplayId> value = PhysicalDisplay::HWC_DISPLAY_ID;
};
+template <typename>
+struct PortGetter {
+ static constexpr std::optional<uint8_t> value;
+};
+
+template <typename PhysicalDisplay>
+struct PortGetter<PhysicalDisplayIdType<PhysicalDisplay>> {
+ static constexpr std::optional<uint8_t> value = PhysicalDisplay::PORT;
+};
+
// DisplayIdType can be:
// 1) PhysicalDisplayIdType<...> for generated ID of physical display backed by HWC.
// 2) HalVirtualDisplayIdType<...> for hard-coded ID of virtual display backed by HWC.
@@ -241,6 +255,7 @@
using DISPLAY_ID = DisplayIdGetter<DisplayIdType>;
using CONNECTION_TYPE = DisplayConnectionTypeGetter<DisplayIdType>;
using HWC_DISPLAY_ID_OPT = HwcDisplayIdGetter<DisplayIdType>;
+ using PORT = PortGetter<DisplayIdType>;
static constexpr int WIDTH = width;
static constexpr int HEIGHT = height;
@@ -277,11 +292,13 @@
TestableSurfaceFlinger::FakeDisplayDeviceInjector(test->mFlinger,
compositionDisplay,
CONNECTION_TYPE::value,
+ PORT::value,
HWC_DISPLAY_ID_OPT::value,
static_cast<bool>(PRIMARY));
injector.setSecure(static_cast<bool>(SECURE));
injector.setNativeWindow(test->mNativeWindow);
+ injector.setDisplaySurface(test->mDisplaySurface);
// Creating a DisplayDevice requires getting default dimensions from the
// native window along with some other initial setup.
@@ -348,9 +365,10 @@
// The HWC active configuration id
static constexpr hal::HWConfigId HWC_ACTIVE_CONFIG_ID = 2001;
- static void injectPendingHotplugEvent(DisplayTransactionTest* test, Connection connection) {
+ static void injectPendingHotplugEvent(DisplayTransactionTest* test,
+ HWComposer::HotplugEvent event) {
test->mFlinger.mutablePendingHotplugEvents().emplace_back(
- TestableSurfaceFlinger::HotplugEvent{HWC_DISPLAY_ID, connection});
+ TestableSurfaceFlinger::HotplugEvent{HWC_DISPLAY_ID, event});
}
// Called by tests to inject a HWC display setup
@@ -520,13 +538,14 @@
static constexpr auto GET_IDENTIFICATION_DATA = getInternalEdid;
};
-template <ui::DisplayConnectionType connectionType, bool hasIdentificationData, bool secure>
+template <ui::DisplayConnectionType connectionType, bool hasIdentificationData, bool secure,
+ HWDisplayId hwDisplayId = 1002>
struct SecondaryDisplay {
static constexpr auto CONNECTION_TYPE = connectionType;
static constexpr Primary PRIMARY = Primary::FALSE;
static constexpr bool SECURE = secure;
static constexpr uint8_t PORT = 254;
- static constexpr HWDisplayId HWC_DISPLAY_ID = 1002;
+ static constexpr HWDisplayId HWC_DISPLAY_ID = hwDisplayId;
static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData;
static constexpr auto GET_IDENTIFICATION_DATA =
connectionType == ui::DisplayConnectionType::Internal ? getInternalEdid
@@ -558,6 +577,11 @@
/*hasIdentificationData=*/true, kNonSecure>,
1080, 2092>;
+template <HWDisplayId hwDisplayId = 1002>
+using ExternalDisplayWithIdentificationVariant = PhysicalDisplayVariant<
+ SecondaryDisplay<ui::DisplayConnectionType::External,
+ /*hasIdentificationData=*/true, kNonSecure, hwDisplayId>,
+ 1920, 1280>;
using ExternalDisplayVariant =
PhysicalDisplayVariant<SecondaryDisplay<ui::DisplayConnectionType::External,
/*hasIdentificationData=*/false, kSecure>,
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index 625d2e6..6f15db8 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -23,13 +23,14 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <gui/DisplayEventReceiver.h>
#include <log/log.h>
#include <scheduler/VsyncConfig.h>
#include <utils/Errors.h>
#include "AsyncCallRecorder.h"
#include "DisplayHardware/DisplayMode.h"
-#include "FrameTimeline.h"
+#include "FrameTimeline/FrameTimeline.h"
#include "Scheduler/EventThread.h"
#include "mock/MockVSyncDispatch.h"
#include "mock/MockVSyncTracker.h"
@@ -111,6 +112,8 @@
void expectOnExpectedPresentTimePosted(nsecs_t expectedPresentTime);
void expectUidFrameRateMappingEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,
std::vector<FrameRateOverride>);
+ void expectQueuedBufferCountReceivedByConnection(
+ ConnectionEventRecorder& connectionEventRecorder, uint32_t expectedBufferCount);
void onVSyncEvent(nsecs_t timestamp, nsecs_t expectedPresentationTime,
nsecs_t deadlineTimestamp) {
@@ -144,6 +147,7 @@
sp<MockEventThreadConnection> mConnection;
sp<MockEventThreadConnection> mThrottledConnection;
std::unique_ptr<frametimeline::impl::TokenManager> mTokenManager;
+ std::vector<ConnectionEventRecorder*> mBufferStuffedConnectionRecorders;
std::chrono::nanoseconds mVsyncPeriod;
@@ -266,7 +270,7 @@
ASSERT_TRUE(args.has_value()) << name << " did not receive an event for timestamp "
<< expectedTimestamp;
const auto& event = std::get<0>(args.value());
- EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_VSYNC, event.header.type)
+ EXPECT_EQ(DisplayEventType::DISPLAY_EVENT_VSYNC, event.header.type)
<< name << " did not get the correct event for timestamp " << expectedTimestamp;
EXPECT_EQ(expectedTimestamp, event.header.timestamp)
<< name << " did not get the expected timestamp for timestamp " << expectedTimestamp;
@@ -340,7 +344,7 @@
auto args = mConnectionEventCallRecorder.waitForCall();
ASSERT_TRUE(args.has_value());
const auto& event = std::get<0>(args.value());
- EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, event.header.type);
+ EXPECT_EQ(DisplayEventType::DISPLAY_EVENT_HOTPLUG, event.header.type);
EXPECT_EQ(expectedDisplayId, event.header.displayId);
EXPECT_EQ(expectedConnected, event.hotplug.connected);
}
@@ -351,7 +355,7 @@
auto args = mConnectionEventCallRecorder.waitForCall();
ASSERT_TRUE(args.has_value());
const auto& event = std::get<0>(args.value());
- EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE, event.header.type);
+ EXPECT_EQ(DisplayEventType::DISPLAY_EVENT_MODE_CHANGE, event.header.type);
EXPECT_EQ(expectedDisplayId, event.header.displayId);
EXPECT_EQ(expectedConfigId, event.modeChange.modeId);
EXPECT_EQ(expectedVsyncPeriod, event.modeChange.vsyncPeriod);
@@ -363,7 +367,7 @@
auto args = mConnectionEventCallRecorder.waitForCall();
ASSERT_TRUE(args.has_value());
const auto& event = std::get<0>(args.value());
- EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE, event.header.type);
+ EXPECT_EQ(DisplayEventType::DISPLAY_EVENT_FRAME_RATE_OVERRIDE, event.header.type);
EXPECT_EQ(expectedDisplayId, event.header.displayId);
EXPECT_EQ(uid, event.frameRateOverride.uid);
EXPECT_EQ(frameRateHz, event.frameRateOverride.frameRateHz);
@@ -372,10 +376,18 @@
auto args = mConnectionEventCallRecorder.waitForCall();
ASSERT_TRUE(args.has_value());
const auto& event = std::get<0>(args.value());
- EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH, event.header.type);
+ EXPECT_EQ(DisplayEventType::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH, event.header.type);
EXPECT_EQ(expectedDisplayId, event.header.displayId);
}
+void EventThreadTest::expectQueuedBufferCountReceivedByConnection(
+ ConnectionEventRecorder& connectionEventRecorder, uint32_t expectedBufferCount) {
+ auto args = connectionEventRecorder.waitForCall();
+ ASSERT_TRUE(args.has_value());
+ const auto& event = std::get<0>(args.value());
+ EXPECT_EQ(expectedBufferCount, event.vsync.vsyncData.numberQueuedBuffers);
+}
+
namespace {
using namespace testing;
@@ -862,12 +874,69 @@
auto args = mConnectionEventCallRecorder.waitForCall();
ASSERT_TRUE(args.has_value());
const auto& event = std::get<0>(args.value());
- EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_HDCP_LEVELS_CHANGE, event.header.type);
+ EXPECT_EQ(DisplayEventType::DISPLAY_EVENT_HDCP_LEVELS_CHANGE, event.header.type);
EXPECT_EQ(EXTERNAL_DISPLAY_ID, event.header.displayId);
EXPECT_EQ(HDCP_V1, event.hdcpLevelsChange.connectedLevel);
EXPECT_EQ(HDCP_V2, event.hdcpLevelsChange.maxLevel);
}
+TEST_F(EventThreadTest, connectionReceivesBufferStuffing) {
+ setupEventThread();
+
+ // Create a connection that will experience buffer stuffing.
+ ConnectionEventRecorder stuffedConnectionEventRecorder{0};
+ sp<MockEventThreadConnection> stuffedConnection =
+ createConnection(stuffedConnectionEventRecorder,
+ gui::ISurfaceComposer::EventRegistration::modeChanged |
+ gui::ISurfaceComposer::EventRegistration::frameRateOverride,
+ 111);
+
+ // Add a connection and buffer count to the list of stuffed Uids that will receive
+ // data in the next vsync event.
+ BufferStuffingMap bufferStuffedUids;
+ bufferStuffedUids.try_emplace(stuffedConnection->mOwnerUid, 3);
+ mThread->addBufferStuffedUids(bufferStuffedUids);
+ mBufferStuffedConnectionRecorders.emplace_back(&stuffedConnectionEventRecorder);
+
+ // Signal that we want the next vsync event to be posted to two connections.
+ mThread->requestNextVsync(mConnection);
+ mThread->requestNextVsync(stuffedConnection);
+ onVSyncEvent(123, 456, 789);
+
+ // Vsync event data contains number of queued buffers.
+ expectQueuedBufferCountReceivedByConnection(mConnectionEventCallRecorder, 0);
+ expectQueuedBufferCountReceivedByConnection(stuffedConnectionEventRecorder, 3);
+}
+
+TEST_F(EventThreadTest, connectionsWithSameUidReceiveBufferStuffing) {
+ setupEventThread();
+
+ // Create a connection with the same Uid as another connection.
+ ConnectionEventRecorder secondConnectionEventRecorder{0};
+ sp<MockEventThreadConnection> secondConnection =
+ createConnection(secondConnectionEventRecorder,
+ gui::ISurfaceComposer::EventRegistration::modeChanged |
+ gui::ISurfaceComposer::EventRegistration::frameRateOverride,
+ mConnectionUid);
+
+ // Add connection Uid and buffer count to the list of stuffed Uids that will receive
+ // data in the next vsync event.
+ BufferStuffingMap bufferStuffedUids;
+ bufferStuffedUids.try_emplace(mConnectionUid, 3);
+ mThread->addBufferStuffedUids(bufferStuffedUids);
+ mBufferStuffedConnectionRecorders.emplace_back(&mConnectionEventCallRecorder);
+ mBufferStuffedConnectionRecorders.emplace_back(&secondConnectionEventRecorder);
+
+ // Signal that we want the next vsync event to be posted to two connections.
+ mThread->requestNextVsync(mConnection);
+ mThread->requestNextVsync(secondConnection);
+ onVSyncEvent(123, 456, 789);
+
+ // Vsync event data contains number of queued buffers.
+ expectQueuedBufferCountReceivedByConnection(mConnectionEventCallRecorder, 3);
+ expectQueuedBufferCountReceivedByConnection(secondConnectionEventRecorder, 3);
+}
+
} // namespace
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/FakeDisplayInjector.h b/services/surfaceflinger/tests/unittests/FakeDisplayInjector.h
index 6e4bf2b..5f7a9f2 100644
--- a/services/surfaceflinger/tests/unittests/FakeDisplayInjector.h
+++ b/services/surfaceflinger/tests/unittests/FakeDisplayInjector.h
@@ -19,24 +19,27 @@
#include <gmock/gmock.h>
#include "TestableSurfaceFlinger.h"
-#include "mock/DisplayHardware/MockPowerAdvisor.h"
+#include "mock/PowerAdvisor/MockPowerAdvisor.h"
#include "mock/system/window/MockNativeWindow.h"
namespace android {
+static constexpr uint8_t kDefaultPort = 255u;
+
using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector;
+using android::adpf::mock::PowerAdvisor;
using android::hardware::graphics::composer::hal::HWDisplayId;
-using android::Hwc2::mock::PowerAdvisor;
struct FakeDisplayInjectorArgs {
- PhysicalDisplayId displayId = PhysicalDisplayId::fromPort(255u);
+ PhysicalDisplayId displayId = PhysicalDisplayId::fromPort(kDefaultPort);
+ uint8_t port = kDefaultPort;
HWDisplayId hwcDisplayId = 0;
bool isPrimary = true;
};
class FakeDisplayInjector {
public:
- FakeDisplayInjector(TestableSurfaceFlinger& flinger, Hwc2::mock::PowerAdvisor& powerAdvisor,
+ FakeDisplayInjector(TestableSurfaceFlinger& flinger, PowerAdvisor& powerAdvisor,
sp<mock::NativeWindow> nativeWindow)
: mFlinger(flinger), mPowerAdvisor(powerAdvisor), mNativeWindow(nativeWindow) {}
@@ -73,7 +76,7 @@
.build());
auto injector = FakeDisplayDeviceInjector(mFlinger, compositionDisplay,
- ui::DisplayConnectionType::Internal,
+ ui::DisplayConnectionType::Internal, args.port,
args.hwcDisplayId, args.isPrimary);
injector.setNativeWindow(mNativeWindow);
@@ -89,7 +92,7 @@
}
TestableSurfaceFlinger& mFlinger;
- Hwc2::mock::PowerAdvisor& mPowerAdvisor;
+ PowerAdvisor& mPowerAdvisor;
sp<mock::NativeWindow> mNativeWindow;
};
diff --git a/services/surfaceflinger/tests/unittests/FlagManagerTest.cpp b/services/surfaceflinger/tests/unittests/FlagManagerTest.cpp
index 51b5f40..a5b347a 100644
--- a/services/surfaceflinger/tests/unittests/FlagManagerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FlagManagerTest.cpp
@@ -85,12 +85,6 @@
EXPECT_EQ(false, mFlagManager.test_flag());
}
-TEST_F(FlagManagerTest, crashesIfQueriedBeforeBoot) {
- mFlagManager.markBootIncomplete();
- EXPECT_DEATH(FlagManager::getInstance()
- .refresh_rate_overlay_on_external_display(), "");
-}
-
TEST_F(FlagManagerTest, returnsOverrideTrue) {
mFlagManager.markBootCompleted();
diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
index 0dfbd61..54f2259 100644
--- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
@@ -166,6 +166,7 @@
a.presentTime == b.presentTime;
}
+ NO_THREAD_SAFETY_ANALYSIS
const std::map<int64_t, TimelineItem>& getPredictions() const {
return mTokenManager->mPredictions;
}
@@ -201,10 +202,12 @@
uint32_t* maxDisplayFrames;
size_t maxTokens;
static constexpr pid_t kSurfaceFlingerPid = 666;
- static constexpr nsecs_t kPresentThreshold = std::chrono::nanoseconds(2ns).count();
+ static constexpr nsecs_t kPresentThresholdLegacy = std::chrono::nanoseconds(2ns).count();
+ static constexpr nsecs_t kPresentThresholdExtended = std::chrono::nanoseconds(4ns).count();
static constexpr nsecs_t kDeadlineThreshold = std::chrono::nanoseconds(0ns).count();
static constexpr nsecs_t kStartThreshold = std::chrono::nanoseconds(2ns).count();
- static constexpr JankClassificationThresholds kTestThresholds{kPresentThreshold,
+ static constexpr JankClassificationThresholds kTestThresholds{kPresentThresholdLegacy,
+ kPresentThresholdExtended,
kDeadlineThreshold,
kStartThreshold};
};
diff --git a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
index e0753a3..b34de1a 100644
--- a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
@@ -69,7 +69,7 @@
using ::testing::StrictMock;
struct HWComposerTest : testing::Test {
- using HalError = hardware::graphics::composer::V2_1::Error;
+ using HalError = hal::Error;
Hwc2::mock::Composer* const mHal = new StrictMock<Hwc2::mock::Composer>();
impl::HWComposer mHwc{std::unique_ptr<Hwc2::Composer>(mHal)};
@@ -94,7 +94,7 @@
constexpr hal::HWDisplayId kHwcDisplayId = 1;
expectHotplugConnect(kHwcDisplayId);
- const auto info = mHwc.onHotplug(kHwcDisplayId, hal::Connection::CONNECTED);
+ const auto info = mHwc.onHotplug(kHwcDisplayId, HWComposer::HotplugEvent::Connected);
ASSERT_TRUE(info);
ASSERT_FALSE(mHwc.isHeadless());
@@ -111,7 +111,7 @@
constexpr hal::HWDisplayId kHwcDisplayId = 1;
expectHotplugConnect(kHwcDisplayId);
- const auto info = mHwc.onHotplug(kHwcDisplayId, hal::Connection::CONNECTED);
+ const auto info = mHwc.onHotplug(kHwcDisplayId, HWComposer::HotplugEvent::Connected);
ASSERT_TRUE(info);
EXPECT_CALL(*mHal, getDisplayConnectionType(kHwcDisplayId, _))
@@ -133,7 +133,7 @@
constexpr hal::HWDisplayId kHwcDisplayId = 2;
expectHotplugConnect(kHwcDisplayId);
- const auto info = mHwc.onHotplug(kHwcDisplayId, hal::Connection::CONNECTED);
+ const auto info = mHwc.onHotplug(kHwcDisplayId, HWComposer::HotplugEvent::Connected);
ASSERT_TRUE(info);
{
@@ -164,7 +164,7 @@
constexpr int32_t kMaxFrameIntervalNs = 50000000; // 20Fps
expectHotplugConnect(kHwcDisplayId);
- const auto info = mHwc.onHotplug(kHwcDisplayId, hal::Connection::CONNECTED);
+ const auto info = mHwc.onHotplug(kHwcDisplayId, HWComposer::HotplugEvent::Connected);
ASSERT_TRUE(info);
ASSERT_TRUE(info->preferredDetailedTimingDescriptor.has_value());
@@ -266,7 +266,7 @@
constexpr int32_t kMaxFrameIntervalNs = 50000000; // 20Fps
expectHotplugConnect(kHwcDisplayId);
- const auto info = mHwc.onHotplug(kHwcDisplayId, hal::Connection::CONNECTED);
+ const auto info = mHwc.onHotplug(kHwcDisplayId, HWComposer::HotplugEvent::Connected);
ASSERT_TRUE(info);
EXPECT_CALL(*mHal, isVrrSupported()).WillRepeatedly(Return(false));
@@ -364,7 +364,7 @@
constexpr hal::HWConfigId kConfigId = 42;
constexpr int32_t kMaxFrameIntervalNs = 50000000; // 20Fps
expectHotplugConnect(kHwcDisplayId);
- const auto info = mHwc.onHotplug(kHwcDisplayId, hal::Connection::CONNECTED);
+ const auto info = mHwc.onHotplug(kHwcDisplayId, HWComposer::HotplugEvent::Connected);
ASSERT_TRUE(info);
EXPECT_CALL(*mHal, isVrrSupported()).WillRepeatedly(Return(true));
@@ -384,6 +384,7 @@
const ui::Size size = info->preferredDetailedTimingDescriptor->physicalSizeInMm;
const float expectedDpiX = (kWidth * kMmPerInch / size.width);
const float expectedDpiY = (kHeight * kMmPerInch / size.height);
+ const OutputType hdrOutputType = OutputType::SYSTEM;
const hal::VrrConfig vrrConfig =
hal::VrrConfig{.minFrameIntervalNs = static_cast<Fps>(120_Hz).getPeriodNsecs(),
.notifyExpectedPresentConfig = hal::VrrConfig::
@@ -394,7 +395,8 @@
.height = kHeight,
.configGroup = kConfigGroup,
.vsyncPeriod = kVsyncPeriod,
- .vrrConfig = vrrConfig};
+ .vrrConfig = vrrConfig,
+ .hdrOutputType = hdrOutputType};
EXPECT_CALL(*mHal, getDisplayConfigurations(kHwcDisplayId, _, _))
.WillOnce(DoAll(SetArgPointee<2>(std::vector<hal::DisplayConfiguration>{
@@ -410,6 +412,7 @@
EXPECT_EQ(modes.front().configGroup, kConfigGroup);
EXPECT_EQ(modes.front().vsyncPeriod, kVsyncPeriod);
EXPECT_EQ(modes.front().vrrConfig, vrrConfig);
+ EXPECT_EQ(modes.front().hdrOutputType, hdrOutputType);
if (!FlagManager::getInstance().correct_dpi_with_display_size()) {
EXPECT_EQ(modes.front().dpiX, -1);
EXPECT_EQ(modes.front().dpiY, -1);
@@ -435,6 +438,7 @@
EXPECT_EQ(modes.front().configGroup, kConfigGroup);
EXPECT_EQ(modes.front().vsyncPeriod, kVsyncPeriod);
EXPECT_EQ(modes.front().vrrConfig, vrrConfig);
+ EXPECT_EQ(modes.front().hdrOutputType, hdrOutputType);
EXPECT_EQ(modes.front().dpiX, kDpi);
EXPECT_EQ(modes.front().dpiY, kDpi);
@@ -448,7 +452,7 @@
constexpr hal::HWDisplayId kHwcDisplayId = 1;
expectHotplugConnect(kHwcDisplayId);
- const auto info = mHwc.onHotplug(kHwcDisplayId, hal::Connection::CONNECTED);
+ const auto info = mHwc.onHotplug(kHwcDisplayId, HWComposer::HotplugEvent::Connected);
ASSERT_TRUE(info);
const auto physicalDisplayId = info->id;
diff --git a/services/surfaceflinger/tests/unittests/JankTrackerTest.cpp b/services/surfaceflinger/tests/unittests/JankTrackerTest.cpp
index 2941a14..0f16073 100644
--- a/services/surfaceflinger/tests/unittests/JankTrackerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/JankTrackerTest.cpp
@@ -213,4 +213,33 @@
EXPECT_EQ(listenerCount(), 0u);
}
-} // namespace android
\ No newline at end of file
+TEST_F(JankTrackerTest, multipleLayersAreTrackedIndependently) {
+ size_t jankDataReceived = 0;
+ size_t numBatchesReceived = 0;
+
+ EXPECT_CALL(*mListener.get(), onJankData(_))
+ .WillRepeatedly([&](const std::vector<gui::JankData>& jankData) {
+ jankDataReceived += jankData.size();
+ numBatchesReceived++;
+ return binder::Status::ok();
+ });
+ addJankListener(123);
+ addJankListener(321);
+ addJankData(123, 1);
+ addJankData(123, 2);
+ addJankData(123, 3);
+ addJankData(321, 4);
+ addJankData(321, 5);
+
+ JankTracker::flushJankData(123);
+ flushBackgroundThread();
+ EXPECT_EQ(numBatchesReceived, 1u);
+ EXPECT_EQ(jankDataReceived, 3u);
+
+ JankTracker::flushJankData(321);
+ flushBackgroundThread();
+ EXPECT_EQ(numBatchesReceived, 2u);
+ EXPECT_EQ(jankDataReceived, 5u);
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp
index de37b63..f3d6dcc 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp
@@ -584,7 +584,7 @@
auto layer = createLegacyAndFrontedEndLayer(1);
showLayer(1);
- setFrameRate(1, (33_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_GTE,
+ setFrameRate(1, (33_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_AT_LEAST,
ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
setFrameRateCategory(1, 0);
@@ -623,7 +623,7 @@
auto layer = createLegacyAndFrontedEndLayer(1);
showLayer(1);
- setFrameRate(1, (33_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_GTE,
+ setFrameRate(1, (33_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_AT_LEAST,
ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
setFrameRateCategory(1, 0);
@@ -654,6 +654,72 @@
EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[0].frameRateCategory);
}
+TEST_F(LayerHistoryIntegrationTest, oneLayerGteNoVote_arr) {
+ SET_FLAG_FOR_TEST(flags::arr_setframerate_gte_enum, true);
+ // Set the test to be on a vrr mode.
+ SET_FLAG_FOR_TEST(flags::vrr_config, true);
+ mSelector->setActiveMode(kVrrModeId, HI_FPS);
+
+ auto layer = createLegacyAndFrontedEndLayer(1);
+ showLayer(1);
+ setFrameRate(1, (0_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_AT_LEAST,
+ ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+
+ EXPECT_EQ(1u, layerCount());
+ EXPECT_EQ(0u, activeLayerCount());
+
+ nsecs_t time = systemTime();
+ for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
+ setBufferWithPresentTime(layer, time);
+ time += HI_FPS_PERIOD;
+ }
+
+ // Layer is active but GTE with 0 should be considered NoVote, thus nothing from summarize.
+ ASSERT_EQ(0u, summarizeLayerHistory(time).size());
+ EXPECT_EQ(1u, activeLayerCount());
+ EXPECT_EQ(1, frequentLayerCount(time));
+
+ // layer became inactive.
+ setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic);
+ time += MAX_ACTIVE_LAYER_PERIOD_NS.count();
+ ASSERT_EQ(0u, summarizeLayerHistory(time).size());
+ EXPECT_EQ(0u, activeLayerCount());
+ EXPECT_EQ(0, frequentLayerCount(time));
+}
+
+TEST_F(LayerHistoryIntegrationTest, oneLayerGteNoVote_mrr) {
+ SET_FLAG_FOR_TEST(flags::arr_setframerate_gte_enum, true);
+ // True by default on MRR devices as well, but the device is not set to VRR mode.
+ SET_FLAG_FOR_TEST(flags::vrr_config, true);
+
+ auto layer = createLegacyAndFrontedEndLayer(1);
+ showLayer(1);
+ setFrameRate(1, (0_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_AT_LEAST,
+ ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+ setFrameRateCategory(1, 0);
+
+ EXPECT_EQ(1u, layerCount());
+ EXPECT_EQ(0u, activeLayerCount());
+
+ nsecs_t time = systemTime();
+ for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
+ setBufferWithPresentTime(layer, time);
+ time += HI_FPS_PERIOD;
+ }
+
+ // Layer is active but GTE with 0 should be considered NoVote, thus nothing from summarize.
+ ASSERT_EQ(0u, summarizeLayerHistory(time).size());
+ EXPECT_EQ(1u, activeLayerCount());
+ EXPECT_EQ(1, frequentLayerCount(time));
+
+ // layer became inactive.
+ setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic);
+ time += MAX_ACTIVE_LAYER_PERIOD_NS.count();
+ ASSERT_EQ(0u, summarizeLayerHistory(time).size());
+ EXPECT_EQ(0u, activeLayerCount());
+ EXPECT_EQ(0, frequentLayerCount(time));
+}
+
TEST_F(LayerHistoryIntegrationTest, oneLayerExplicitVoteWithCategory_vrrFeatureOff) {
SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, false);
@@ -715,6 +781,204 @@
EXPECT_EQ(0, frequentLayerCount(time));
}
+// Tests MRR NoPreference-only vote, no game default override. Expects vote reset.
+TEST_F(LayerHistoryIntegrationTest, oneLayerCategoryNoPreference_mrr) {
+ SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, false);
+ SET_FLAG_FOR_TEST(flags::game_default_frame_rate, true);
+ SET_FLAG_FOR_TEST(flags::vrr_config, true);
+
+ const LayerHistory::LayerVoteType defaultVote = LayerHistory::LayerVoteType::Min;
+
+ auto layer = createLegacyAndFrontedEndLayer(1);
+ setDefaultLayerVote(layer.get(), defaultVote);
+ showLayer(1);
+ setFrameRate(1, (0_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT,
+ ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+ setFrameRateCategory(1, ANATIVEWINDOW_FRAME_RATE_CATEGORY_NO_PREFERENCE);
+
+ EXPECT_EQ(1u, layerCount());
+ EXPECT_EQ(0u, activeLayerCount());
+
+ nsecs_t time = systemTime();
+ for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
+ setBufferWithPresentTime(layer, time);
+ time += HI_FPS_PERIOD;
+ }
+
+ EXPECT_EQ(1u, summarizeLayerHistory(time).size());
+ EXPECT_EQ(1u, activeLayerCount());
+ EXPECT_EQ(1, frequentLayerCount(time));
+ EXPECT_EQ(defaultVote, summarizeLayerHistory(time)[0].vote);
+ EXPECT_EQ(0_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate);
+ EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[0].frameRateCategory);
+}
+
+// Tests VRR NoPreference-only vote, no game default override. Expects NoPreference, *not* vote
+// reset.
+TEST_F(LayerHistoryIntegrationTest, oneLayerCategoryNoPreference_vrr) {
+ SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, false);
+ SET_FLAG_FOR_TEST(flags::game_default_frame_rate, true);
+ SET_FLAG_FOR_TEST(flags::vrr_config, true);
+ mSelector->setActiveMode(kVrrModeId, HI_FPS);
+
+ const LayerHistory::LayerVoteType defaultVote = LayerHistory::LayerVoteType::Min;
+
+ auto layer = createLegacyAndFrontedEndLayer(1);
+ setDefaultLayerVote(layer.get(), defaultVote);
+ showLayer(1);
+ setFrameRate(1, (0_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT,
+ ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+ setFrameRateCategory(1, ANATIVEWINDOW_FRAME_RATE_CATEGORY_NO_PREFERENCE);
+
+ EXPECT_EQ(1u, layerCount());
+ EXPECT_EQ(0u, activeLayerCount());
+
+ nsecs_t time = systemTime();
+ for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
+ setBufferWithPresentTime(layer, time);
+ time += HI_FPS_PERIOD;
+ }
+
+ EXPECT_EQ(1u, summarizeLayerHistory(time).size());
+ EXPECT_EQ(1u, activeLayerCount());
+ EXPECT_EQ(1, frequentLayerCount(time));
+ EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitCategory, summarizeLayerHistory(time)[0].vote);
+ EXPECT_EQ(0_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate);
+ EXPECT_EQ(FrameRateCategory::NoPreference, summarizeLayerHistory(time)[0].frameRateCategory);
+}
+
+TEST_F(LayerHistoryIntegrationTest, oneLayerCategoryNoPreferenceWithGameDefault_vrr) {
+ SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, false);
+ SET_FLAG_FOR_TEST(flags::game_default_frame_rate, true);
+ SET_FLAG_FOR_TEST(flags::vrr_config, true);
+ mSelector->setActiveMode(kVrrModeId, HI_FPS);
+
+ const Fps gameDefaultFrameRate = Fps::fromValue(30.0f);
+ const uid_t uid = 456;
+
+ history().updateGameDefaultFrameRateOverride(
+ FrameRateOverride({uid, gameDefaultFrameRate.getValue()}));
+
+ auto layer = createLegacyAndFrontedEndLayerWithUid(1, gui::Uid(uid));
+ showLayer(1);
+ setFrameRate(1, (0_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT,
+ ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+ setFrameRateCategory(1, ANATIVEWINDOW_FRAME_RATE_CATEGORY_NO_PREFERENCE);
+
+ EXPECT_EQ(1u, layerCount());
+ EXPECT_EQ(0u, activeLayerCount());
+
+ nsecs_t time = systemTime();
+ for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
+ setBufferWithPresentTime(layer, time);
+ time += HI_FPS_PERIOD;
+ }
+
+ EXPECT_EQ(1u, summarizeLayerHistory(time).size());
+ EXPECT_EQ(1u, activeLayerCount());
+ EXPECT_EQ(1, frequentLayerCount(time));
+ EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summarizeLayerHistory(time)[0].vote);
+ EXPECT_EQ(gameDefaultFrameRate, summarizeLayerHistory(time)[0].desiredRefreshRate);
+ EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[0].frameRateCategory);
+}
+
+TEST_F(LayerHistoryIntegrationTest, oneLayerCategoryNoPreferenceWithGameDefault_mrr) {
+ SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, false);
+ SET_FLAG_FOR_TEST(flags::game_default_frame_rate, true);
+ SET_FLAG_FOR_TEST(flags::vrr_config, true);
+
+ const Fps gameDefaultFrameRate = Fps::fromValue(30.0f);
+ const uid_t uid = 456;
+
+ history().updateGameDefaultFrameRateOverride(
+ FrameRateOverride({uid, gameDefaultFrameRate.getValue()}));
+
+ auto layer = createLegacyAndFrontedEndLayerWithUid(1, gui::Uid(uid));
+ showLayer(1);
+ setFrameRate(1, (0_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT,
+ ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+ setFrameRateCategory(1, ANATIVEWINDOW_FRAME_RATE_CATEGORY_NO_PREFERENCE);
+
+ EXPECT_EQ(1u, layerCount());
+ EXPECT_EQ(0u, activeLayerCount());
+
+ nsecs_t time = systemTime();
+ for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
+ setBufferWithPresentTime(layer, time);
+ time += HI_FPS_PERIOD;
+ }
+
+ EXPECT_EQ(1u, summarizeLayerHistory(time).size());
+ EXPECT_EQ(1u, activeLayerCount());
+ EXPECT_EQ(1, frequentLayerCount(time));
+ EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summarizeLayerHistory(time)[0].vote);
+ EXPECT_EQ(gameDefaultFrameRate, summarizeLayerHistory(time)[0].desiredRefreshRate);
+ EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[0].frameRateCategory);
+}
+
+TEST_F(LayerHistoryIntegrationTest, oneLayerNoVoteWithGameDefault_vrr) {
+ SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, false);
+ SET_FLAG_FOR_TEST(flags::game_default_frame_rate, true);
+ SET_FLAG_FOR_TEST(flags::vrr_config, true);
+ mSelector->setActiveMode(kVrrModeId, HI_FPS);
+
+ const Fps gameDefaultFrameRate = Fps::fromValue(30.0f);
+ const uid_t uid = 456;
+
+ history().updateGameDefaultFrameRateOverride(
+ FrameRateOverride({uid, gameDefaultFrameRate.getValue()}));
+
+ auto layer = createLegacyAndFrontedEndLayerWithUid(1, gui::Uid(uid));
+ showLayer(1);
+ setFrameRate(1, (0_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_NO_VOTE,
+ ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+
+ EXPECT_EQ(1u, layerCount());
+ EXPECT_EQ(0u, activeLayerCount());
+
+ nsecs_t time = systemTime();
+ for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
+ setBufferWithPresentTime(layer, time);
+ time += HI_FPS_PERIOD;
+ }
+
+ // Expect NoVote to be skipped in summarize.
+ EXPECT_EQ(0u, summarizeLayerHistory(time).size());
+ EXPECT_EQ(1u, activeLayerCount());
+ EXPECT_EQ(1, frequentLayerCount(time));
+}
+
+TEST_F(LayerHistoryIntegrationTest, oneLayerNoVoteWithGameDefault_mrr) {
+ SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, false);
+ SET_FLAG_FOR_TEST(flags::game_default_frame_rate, true);
+ SET_FLAG_FOR_TEST(flags::vrr_config, true);
+
+ const Fps gameDefaultFrameRate = Fps::fromValue(30.0f);
+ const uid_t uid = 456;
+
+ history().updateGameDefaultFrameRateOverride(
+ FrameRateOverride({uid, gameDefaultFrameRate.getValue()}));
+
+ auto layer = createLegacyAndFrontedEndLayerWithUid(1, gui::Uid(uid));
+ showLayer(1);
+ setFrameRate(1, (0_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_NO_VOTE,
+ ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+
+ EXPECT_EQ(1u, layerCount());
+ EXPECT_EQ(0u, activeLayerCount());
+
+ nsecs_t time = systemTime();
+ for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
+ setBufferWithPresentTime(layer, time);
+ time += HI_FPS_PERIOD;
+ }
+
+ // Expect NoVote to be skipped in summarize.
+ EXPECT_EQ(0u, summarizeLayerHistory(time).size());
+ EXPECT_EQ(1u, activeLayerCount());
+ EXPECT_EQ(1, frequentLayerCount(time));
+}
+
TEST_F(LayerHistoryIntegrationTest, oneLayerExplicitVoteWithCategory) {
SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, true);
diff --git a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
index c7cc21c..35ec536 100644
--- a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
@@ -21,7 +21,7 @@
#include "FrontEnd/LayerLifecycleManager.h"
#include "LayerHierarchyTest.h"
-#include "TransactionState.h"
+#include "QueuedTransactionState.h"
using namespace android::surfaceflinger;
@@ -104,7 +104,7 @@
EXPECT_FALSE(managedLayers.front()->changes.test(RequestedLayerState::Changes::Z));
// apply transactions that do not affect the hierarchy
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
transactions.back().states.front().state.backgroundBlurRadius = 22;
@@ -297,7 +297,7 @@
layers.emplace_back(rootLayer(1));
lifecycleManager.addLayers(std::move(layers));
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
transactions.back().states.front().state.bgColor.a = 0.5;
@@ -326,7 +326,7 @@
layers.emplace_back(rootLayer(1));
lifecycleManager.addLayers(std::move(layers));
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
transactions.back().states.front().state.bgColor.a = 0.5;
@@ -360,7 +360,7 @@
layers.emplace_back(rootLayer(1));
lifecycleManager.addLayers(std::move(layers));
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
transactions.back().states.front().state.bgColor.a = 0.5;
@@ -619,14 +619,32 @@
}
}
-TEST_F(LayerLifecycleManagerTest, testInputInfoOfRequestedLayerState) {
- // By default the layer has no buffer, so it doesn't need an input info
- EXPECT_FALSE(getRequestedLayerState(mLifecycleManager, 111)->needsInputInfo());
-
- setBuffer(111);
+TEST_F(LayerLifecycleManagerTest, layerWithBufferNeedsInputInfo) {
+ // If a layer has no buffer or no color, it doesn't have an input info
+ LayerHierarchyTestBase::createRootLayer(3);
+ setColor(3, {-1._hf, -1._hf, -1._hf});
mLifecycleManager.commitChanges();
- EXPECT_TRUE(getRequestedLayerState(mLifecycleManager, 111)->needsInputInfo());
+ EXPECT_FALSE(getRequestedLayerState(mLifecycleManager, 3)->needsInputInfo());
+
+ setBuffer(3);
+ mLifecycleManager.commitChanges();
+
+ EXPECT_TRUE(getRequestedLayerState(mLifecycleManager, 3)->needsInputInfo());
+}
+
+TEST_F(LayerLifecycleManagerTest, layerWithColorNeedsInputInfo) {
+ // If a layer has no buffer or no color, it doesn't have an input info
+ LayerHierarchyTestBase::createRootLayer(4);
+ setColor(4, {-1._hf, -1._hf, -1._hf});
+ mLifecycleManager.commitChanges();
+
+ EXPECT_FALSE(getRequestedLayerState(mLifecycleManager, 4)->needsInputInfo());
+
+ setColor(4, {1._hf, 0._hf, 0._hf});
+ mLifecycleManager.commitChanges();
+
+ EXPECT_TRUE(getRequestedLayerState(mLifecycleManager, 4)->needsInputInfo());
}
} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index a35ae15..7aad84b 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -28,7 +28,7 @@
#include "ui/GraphicTypes.h"
#include <com_android_graphics_libgui_flags.h>
-#include <com_android_graphics_surfaceflinger_flags.h>
+#include <cmath>
#define UPDATE_AND_VERIFY(BUILDER, ...) \
({ \
@@ -330,7 +330,7 @@
}
TEST_F(LayerSnapshotTest, UpdateMetadata) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
transactions.back().states.front().state.what = layer_state_t::eMetadataChanged;
@@ -375,7 +375,7 @@
TEST_F(LayerSnapshotTest, UpdateMetadataOfHiddenLayers) {
hideLayer(1);
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
transactions.back().states.front().state.what = layer_state_t::eMetadataChanged;
@@ -1426,6 +1426,85 @@
EXPECT_EQ(getSnapshot(1)->geomContentCrop, Rect(0, 0, 100, 100));
}
+TEST_F(LayerSnapshotTest, setCornerRadius) {
+ static constexpr float RADIUS = 123.f;
+ setRoundedCorners(1, RADIUS);
+ setCrop(1, Rect{1000, 1000});
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_EQ(getSnapshot({.id = 1})->roundedCorner.radius.x, RADIUS);
+}
+
+TEST_F(LayerSnapshotTest, ignoreCornerRadius) {
+ static constexpr float RADIUS = 123.f;
+ setClientDrawnCornerRadius(1, RADIUS);
+ setRoundedCorners(1, RADIUS);
+ setCrop(1, Rect{1000, 1000});
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_TRUE(getSnapshot({.id = 1})->roundedCorner.hasClientDrawnRadius());
+ EXPECT_EQ(getSnapshot({.id = 1})->roundedCorner.radius.x, 0.f);
+}
+
+TEST_F(LayerSnapshotTest, childInheritsParentScaledSettings) {
+ // ROOT
+ // ├── 1 (crop rect set to contain child layer)
+ // │ ├── 11
+ static constexpr float RADIUS = 123.f;
+
+ setRoundedCorners(1, RADIUS);
+ FloatRect parentCropRect(1, 1, 999, 999);
+ setCrop(1, parentCropRect);
+ // Rotate surface by 90
+ setMatrix(11, 0.f, -1.f, 1.f, 0.f);
+
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+
+ ui::Transform t = getSnapshot({.id = 11})->localTransform.inverse();
+
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_EQ(getSnapshot({.id = 11})->roundedCorner.cropRect, t.transform(parentCropRect));
+ EXPECT_EQ(getSnapshot({.id = 11})->roundedCorner.radius.x, RADIUS * t.getScaleX());
+ EXPECT_EQ(getSnapshot({.id = 11})->roundedCorner.radius.y, RADIUS * t.getScaleY());
+ EXPECT_EQ(getSnapshot({.id = 11})->roundedCorner.requestedRadius.x, RADIUS * t.getScaleX());
+ EXPECT_EQ(getSnapshot({.id = 11})->roundedCorner.requestedRadius.y, RADIUS * t.getScaleY());
+}
+
+TEST_F(LayerSnapshotTest, childInheritsParentClientDrawnCornerRadius) {
+ // ROOT
+ // ├── 1 (crop rect set to contain child layers )
+ // │ ├── 11
+ // │ │ └── 111
+
+ static constexpr float RADIUS = 123.f;
+
+ setClientDrawnCornerRadius(1, RADIUS);
+ setRoundedCorners(1, RADIUS);
+ setCrop(1, Rect(1, 1, 999, 999));
+
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_TRUE(getSnapshot({.id = 1})->roundedCorner.hasClientDrawnRadius());
+ EXPECT_TRUE(getSnapshot({.id = 11})->roundedCorner.hasRoundedCorners());
+ EXPECT_EQ(getSnapshot({.id = 11})->roundedCorner.radius.x, RADIUS);
+}
+
+TEST_F(LayerSnapshotTest, childIgnoreCornerRadiusOverridesParent) {
+ // ROOT
+ // ├── 1 (crop rect set to contain child layers )
+ // │ ├── 11
+ // │ │ └── 111
+
+ static constexpr float RADIUS = 123.f;
+
+ setRoundedCorners(1, RADIUS);
+ setCrop(1, Rect(1, 1, 999, 999));
+
+ setClientDrawnCornerRadius(11, RADIUS);
+
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_EQ(getSnapshot({.id = 1})->roundedCorner.radius.x, RADIUS);
+ EXPECT_EQ(getSnapshot({.id = 11})->roundedCorner.radius.x, 0.f);
+ EXPECT_EQ(getSnapshot({.id = 111})->roundedCorner.radius.x, RADIUS);
+}
+
TEST_F(LayerSnapshotTest, setShadowRadius) {
static constexpr float SHADOW_RADIUS = 123.f;
setShadowRadius(1, SHADOW_RADIUS);
@@ -1551,11 +1630,14 @@
}
TEST_F(LayerSnapshotTest, NonVisibleLayerWithInput) {
+ SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::
+ skip_invisible_windows_in_input,
+ false);
LayerHierarchyTestBase::createRootLayer(3);
setColor(3, {-1._hf, -1._hf, -1._hf});
UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
transactions.back().states.front().state.what = layer_state_t::eInputInfoChanged;
@@ -1576,6 +1658,39 @@
EXPECT_TRUE(foundInputLayer);
}
+TEST_F(LayerSnapshotTest, NonVisibleLayerWithInputShouldNotBeIncluded) {
+ SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::
+ skip_invisible_windows_in_input,
+ true);
+ LayerHierarchyTestBase::createRootLayer(3);
+ setColor(3, {-1._hf, -1._hf, -1._hf});
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+
+ std::vector<QueuedTransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+ transactions.back().states.front().state.what = layer_state_t::eInputInfoChanged;
+ transactions.back().states.front().layerId = 3;
+ transactions.back().states.front().state.windowInfoHandle = sp<gui::WindowInfoHandle>::make();
+ auto inputInfo = transactions.back().states.front().state.windowInfoHandle->editInfo();
+ inputInfo->token = sp<BBinder>::make();
+ hideLayer(3);
+ mLifecycleManager.applyTransactions(transactions);
+
+ update(mSnapshotBuilder);
+
+ bool foundInputLayer = false;
+ mSnapshotBuilder.forEachInputSnapshot([&](const frontend::LayerSnapshot& snapshot) {
+ if (snapshot.uniqueSequence == 3) {
+ EXPECT_TRUE(
+ snapshot.inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NOT_VISIBLE));
+ EXPECT_FALSE(snapshot.isVisible);
+ foundInputLayer = true;
+ }
+ });
+ EXPECT_FALSE(foundInputLayer);
+}
+
TEST_F(LayerSnapshotTest, ForEachSnapshotsWithPredicate) {
std::vector<uint32_t> visitedUniqueSequences;
mSnapshotBuilder.forEachSnapshot(
@@ -1922,17 +2037,132 @@
}
TEST_F(LayerSnapshotTest, shouldUpdateInputWhenNoInputInfo) {
- // By default the layer has no buffer, so we don't expect it to have an input info
+ // If a layer has no buffer or no color, it doesn't have an input info
+ setColor(111, {-1._hf, -1._hf, -1._hf});
+ UPDATE_AND_VERIFY(mSnapshotBuilder, {1, 11, 12, 121, 122, 1221, 13, 2});
EXPECT_FALSE(getSnapshot(111)->hasInputInfo());
setBuffer(111);
-
UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
EXPECT_TRUE(getSnapshot(111)->hasInputInfo());
EXPECT_TRUE(getSnapshot(111)->inputInfo.inputConfig.test(
gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL));
- EXPECT_FALSE(getSnapshot(2)->hasInputInfo());
+}
+
+// content dirty test
+TEST_F(LayerSnapshotTest, contentDirtyWhenParentAlphaChanges) {
+ setAlpha(1, 0.5);
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_TRUE(getSnapshot(1)->contentDirty);
+ EXPECT_TRUE(getSnapshot(11)->contentDirty);
+ EXPECT_TRUE(getSnapshot(111)->contentDirty);
+
+ // subsequent updates clear the dirty bit
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_FALSE(getSnapshot(1)->contentDirty);
+ EXPECT_FALSE(getSnapshot(11)->contentDirty);
+ EXPECT_FALSE(getSnapshot(111)->contentDirty);
+}
+
+TEST_F(LayerSnapshotTest, contentDirtyWhenAutoRefresh) {
+ setAutoRefresh(1, true);
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_TRUE(getSnapshot(1)->contentDirty);
+
+ // subsequent updates don't clear the dirty bit
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_TRUE(getSnapshot(1)->contentDirty);
+
+ // second update after removing auto refresh will clear content dirty
+ setAutoRefresh(1, false);
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_FALSE(getSnapshot(1)->contentDirty);
+}
+
+TEST_F(LayerSnapshotTest, contentDirtyWhenColorChanges) {
+ setColor(1, {1, 2, 3});
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_TRUE(getSnapshot(1)->contentDirty);
+
+ // subsequent updates clear the dirty bit
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_FALSE(getSnapshot(1)->contentDirty);
+}
+
+TEST_F(LayerSnapshotTest, contentDirtyWhenParentGeometryChanges) {
+ setPosition(1, 2, 3);
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_TRUE(getSnapshot(1)->contentDirty);
+
+ // subsequent updates clear the dirty bit
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_FALSE(getSnapshot(1)->contentDirty);
+}
+TEST_F(LayerSnapshotTest, shouldUpdatePictureProfileHandle) {
+ std::vector<QueuedTransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+ transactions.back().states.back().layerId = 1;
+ transactions.back().states.back().state.layerId = 1;
+ transactions.back().states.back().state.what = layer_state_t::ePictureProfileHandleChanged;
+ transactions.back().states.back().state.pictureProfileHandle = PictureProfileHandle(3);
+
+ mLifecycleManager.applyTransactions(transactions);
+ EXPECT_EQ(mLifecycleManager.getGlobalChanges(), RequestedLayerState::Changes::Content);
+
+ update(mSnapshotBuilder);
+
+ EXPECT_EQ(getSnapshot(1)->clientChanges, layer_state_t::ePictureProfileHandleChanged);
+ EXPECT_EQ(getSnapshot(1)->pictureProfileHandle, PictureProfileHandle(3));
+}
+
+TEST_F(LayerSnapshotTest, shouldUpdatePictureProfilePriorityFromAppContentPriority) {
+ {
+ std::vector<QueuedTransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+ transactions.back().states.back().layerId = 1;
+ transactions.back().states.back().state.layerId = 1;
+ transactions.back().states.back().state.what = layer_state_t::eAppContentPriorityChanged;
+ transactions.back().states.back().state.appContentPriority = 1;
+ transactions.back().states.push_back({});
+ transactions.back().states.back().layerId = 2;
+ transactions.back().states.back().state.layerId = 2;
+ transactions.back().states.back().state.what = layer_state_t::eAppContentPriorityChanged;
+ transactions.back().states.back().state.appContentPriority = -1;
+
+ mLifecycleManager.applyTransactions(transactions);
+ EXPECT_EQ(mLifecycleManager.getGlobalChanges(), RequestedLayerState::Changes::Content);
+
+ update(mSnapshotBuilder);
+
+ EXPECT_GT(getSnapshot(1)->pictureProfilePriority, getSnapshot(2)->pictureProfilePriority);
+ EXPECT_EQ(getSnapshot(1)->pictureProfilePriority - getSnapshot(2)->pictureProfilePriority,
+ 2);
+ }
+ {
+ std::vector<QueuedTransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+ transactions.back().states.back().layerId = 1;
+ transactions.back().states.back().state.layerId = 1;
+ transactions.back().states.back().state.what = layer_state_t::eAppContentPriorityChanged;
+ transactions.back().states.back().state.appContentPriority = INT_MIN;
+ transactions.back().states.push_back({});
+ transactions.back().states.back().layerId = 2;
+ transactions.back().states.back().state.layerId = 2;
+ transactions.back().states.back().state.what = layer_state_t::eAppContentPriorityChanged;
+ transactions.back().states.back().state.appContentPriority = INT_MAX;
+
+ mLifecycleManager.applyTransactions(transactions);
+ EXPECT_EQ(mLifecycleManager.getGlobalChanges(), RequestedLayerState::Changes::Content);
+
+ update(mSnapshotBuilder);
+
+ EXPECT_GT(getSnapshot(2)->pictureProfilePriority, getSnapshot(1)->pictureProfilePriority);
+ }
}
} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp b/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp
index 71f9f88..e9b86b2 100644
--- a/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp
+++ b/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp
@@ -22,7 +22,7 @@
#include <scheduler/interface/ICompositor.h>
-#include "FrameTimeline.h"
+#include "FrameTimeline/FrameTimeline.h"
#include "Scheduler/MessageQueue.h"
#include "mock/MockVSyncDispatch.h"
#include "utils/Timers.h"
@@ -159,9 +159,9 @@
constexpr VsyncId vsyncId{42};
EXPECT_CALL(mTokenManager,
- generateTokenForPredictions(frametimeline::TimelineItem(kStartTime.ns(),
- kEndTime.ns(),
- kPresentTime.ns())))
+ generateTokenForPredictions(
+ frametimeline::TimelineItem(kStartTime.ns(), kEndTime.ns(),
+ kPresentTime.ns(), kPresentTime.ns())))
.WillOnce(Return(ftl::to_underlying(vsyncId)));
EXPECT_CALL(*mEventQueue.mHandler, dispatchFrame(vsyncId, kPresentTime)).Times(1);
EXPECT_NO_FATAL_FAILURE(
diff --git a/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp b/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
index c879280..d7f7bdb 100644
--- a/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
@@ -17,7 +17,8 @@
#undef LOG_TAG
#define LOG_TAG "PowerAdvisorTest"
-#include <DisplayHardware/PowerAdvisor.h>
+#include "PowerAdvisor/PowerAdvisor.h"
+
#include <android_os.h>
#include <binder/Status.h>
#include <com_android_graphics_surfaceflinger_flags.h>
@@ -29,18 +30,18 @@
#include <ui/DisplayId.h>
#include <chrono>
#include <future>
-#include "TestableSurfaceFlinger.h"
-#include "mock/DisplayHardware/MockPowerHalController.h"
-#include "mock/DisplayHardware/MockPowerHintSessionWrapper.h"
+#include "mock/PowerAdvisor/MockPowerHalController.h"
+#include "mock/PowerAdvisor/MockPowerHintSessionWrapper.h"
using namespace android;
-using namespace android::Hwc2::mock;
+using namespace android::adpf::mock;
using namespace android::hardware::power;
using namespace std::chrono_literals;
using namespace testing;
using namespace android::power;
+using namespace ftl::flag_operators;
-namespace android::Hwc2::impl {
+namespace android::adpf::impl {
class PowerAdvisorTest : public testing::Test {
public:
@@ -54,6 +55,8 @@
void setTimingTestingMode(bool testinMode);
void allowReportActualToAcquireMutex();
bool sessionExists();
+ ftl::Flags<Workload> getCommittedWorkload() const;
+ ftl::Flags<Workload> getQueuedWorkload() const;
int64_t toNanos(Duration d);
struct GpuTestConfig {
@@ -73,7 +76,6 @@
void testGpuScenario(GpuTestConfig& config, WorkDuration& ret);
protected:
- TestableSurfaceFlinger mFlinger;
std::unique_ptr<PowerAdvisor> mPowerAdvisor;
MockPowerHalController* mMockPowerHalController;
std::shared_ptr<MockPowerHintSessionWrapper> mMockPowerHintSession;
@@ -85,6 +87,7 @@
int64_t mSessionId = 123;
SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel, true);
SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel_fixed, false);
+ SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::adpf_fmq_sf, false);
};
bool PowerAdvisorTest::sessionExists() {
@@ -97,7 +100,7 @@
}
void PowerAdvisorTest::SetUp() {
- mPowerAdvisor = std::make_unique<impl::PowerAdvisor>(*mFlinger.flinger());
+ mPowerAdvisor = std::make_unique<impl::PowerAdvisor>([]() {}, 80ms);
mPowerAdvisor->mPowerHal = std::make_unique<NiceMock<MockPowerHalController>>();
mMockPowerHalController =
reinterpret_cast<MockPowerHalController*>(mPowerAdvisor->mPowerHal.get());
@@ -184,6 +187,7 @@
SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::adpf_gpu_sf,
config.adpfGpuFlagOn);
SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel_fixed, config.usesFmq);
+ SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::adpf_fmq_sf, config.usesFmq);
mPowerAdvisor->onBootFinished();
bool expectsFmqSuccess = config.usesSharedFmqFlag && !config.fmqFull;
if (config.usesFmq) {
@@ -314,6 +318,14 @@
return mPowerAdvisor->sTargetSafetyMargin;
}
+ftl::Flags<Workload> PowerAdvisorTest::getCommittedWorkload() const {
+ return mPowerAdvisor->mCommittedWorkload;
+}
+
+ftl::Flags<Workload> PowerAdvisorTest::getQueuedWorkload() const {
+ return ftl::Flags<Workload>{mPowerAdvisor->mQueuedWorkload.load()};
+}
+
namespace {
TEST_F(PowerAdvisorTest, hintSessionUseHwcDisplay) {
@@ -789,6 +801,7 @@
TEST_F(PowerAdvisorTest, fmq_sendHint) {
SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel_fixed, true);
+ SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::adpf_fmq_sf, true);
mPowerAdvisor->onBootFinished();
SetUpFmq(true, false);
auto startTime = uptimeNanos();
@@ -807,6 +820,7 @@
TEST_F(PowerAdvisorTest, fmq_sendHint_noSharedFlag) {
SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel_fixed, true);
+ SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::adpf_fmq_sf, true);
mPowerAdvisor->onBootFinished();
SetUpFmq(false, false);
SessionHint hint;
@@ -821,6 +835,7 @@
TEST_F(PowerAdvisorTest, fmq_sendHint_queueFull) {
SET_FLAG_FOR_TEST(android::os::adpf_use_fmq_channel_fixed, true);
+ SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::adpf_fmq_sf, true);
mPowerAdvisor->onBootFinished();
SetUpFmq(true, true);
ASSERT_EQ(mBackendFmq->availableToRead(), 2uL);
@@ -838,5 +853,32 @@
ASSERT_EQ(hint, SessionHint::CPU_LOAD_UP);
}
+TEST_F(PowerAdvisorTest, trackQueuedWorkloads) {
+ mPowerAdvisor->setQueuedWorkload(ftl::Flags<Workload>());
+ ASSERT_EQ(getQueuedWorkload(), ftl::Flags<Workload>());
+
+ // verify workloads are queued
+ mPowerAdvisor->setQueuedWorkload(ftl::Flags<Workload>(Workload::VISIBLE_REGION));
+ ASSERT_EQ(getQueuedWorkload(), ftl::Flags<Workload>(Workload::VISIBLE_REGION));
+
+ mPowerAdvisor->setQueuedWorkload(ftl::Flags<Workload>(Workload::EFFECTS));
+ ASSERT_EQ(getQueuedWorkload(), Workload::VISIBLE_REGION | Workload::EFFECTS);
+
+ // verify queued workloads are cleared after commit
+ mPowerAdvisor->setCommittedWorkload(ftl::Flags<Workload>());
+ ASSERT_EQ(getQueuedWorkload(), ftl::Flags<Workload>());
+}
+
+TEST_F(PowerAdvisorTest, trackCommittedWorkloads) {
+ // verify queued workloads are cleared after commit
+ mPowerAdvisor->setCommittedWorkload(Workload::SCREENSHOT | Workload::VISIBLE_REGION);
+ ASSERT_EQ(getCommittedWorkload(), Workload::SCREENSHOT | Workload::VISIBLE_REGION);
+
+ // on composite, verify we update the committed workload so we track workload increases for the
+ // next frame accurately
+ mPowerAdvisor->setCompositedWorkload(Workload::VISIBLE_REGION | Workload::DISPLAY_CHANGES);
+ ASSERT_EQ(getCommittedWorkload(), Workload::VISIBLE_REGION | Workload::DISPLAY_CHANGES);
+}
+
} // namespace
-} // namespace android::Hwc2::impl
+} // namespace android::adpf::impl
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
index adbd868..9b3cba5 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
@@ -2112,6 +2112,46 @@
EXPECT_FALSE(actualRankedFrameRates.consideredSignals.touch);
}
+TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_touchBoost_twoUids_arr) {
+ if (GetParam() != Config::FrameRateOverride::Enabled) {
+ return;
+ }
+
+ SET_FLAG_FOR_TEST(flags::vrr_config, true);
+ // Device with VRR config mode
+ auto selector = createSelector(kVrrMode_120, kModeId120);
+
+ std::vector<LayerRequirement> layers = {{.ownerUid = 1234, .weight = 1.f},
+ {.ownerUid = 5678, .weight = 1.f}};
+ auto& lr1 = layers[0];
+ auto& lr2 = layers[1];
+
+ lr1.vote = LayerVoteType::ExplicitCategory;
+ lr1.frameRateCategory = FrameRateCategory::Normal;
+ lr1.name = "ExplicitCategory Normal";
+ lr2.vote = LayerVoteType::ExplicitDefault;
+ lr2.desiredRefreshRate = 30_Hz;
+ lr2.name = "30Hz ExplicitDefault";
+ auto actualRankedFrameRates = selector.getRankedFrameRates(layers, {.touch = true});
+ // No global touch boost, for example a game that uses setFrameRate(30, default compatibility).
+ // However see 60 due to Normal vote.
+ EXPECT_FRAME_RATE_MODE(kVrrMode120TE240, 60_Hz,
+ actualRankedFrameRates.ranking.front().frameRateMode);
+ EXPECT_FALSE(actualRankedFrameRates.consideredSignals.touch);
+
+ lr1.vote = LayerVoteType::ExplicitCategory;
+ lr1.frameRateCategory = FrameRateCategory::HighHint;
+ lr1.name = "ExplicitCategory HighHint";
+ lr2.vote = LayerVoteType::ExplicitDefault;
+ lr2.desiredRefreshRate = 30_Hz;
+ lr2.name = "30Hz ExplicitDefault";
+ // Gets touch boost because the touched (HighHint) app is different from the 30 Default app.
+ actualRankedFrameRates = selector.getRankedFrameRates(layers, {.touch = true});
+ EXPECT_FRAME_RATE_MODE(kVrrMode120TE240, 120_Hz,
+ actualRankedFrameRates.ranking.front().frameRateMode);
+ EXPECT_TRUE(actualRankedFrameRates.consideredSignals.touch);
+}
+
TEST_P(RefreshRateSelectorTest,
getBestFrameRateMode_withFrameRateCategory_idleTimer_60_120_nonVrr) {
SET_FLAG_FOR_TEST(flags::vrr_config, false);
@@ -3697,6 +3737,51 @@
EXPECT_TRUE(frameRateOverrides.empty());
}
+TEST_P(RefreshRateSelectorTest, getFrameRateOverrides_twoUids_arr) {
+ if (GetParam() != Config::FrameRateOverride::Enabled) {
+ return;
+ }
+
+ SET_FLAG_FOR_TEST(flags::vrr_config, true);
+ // Device with VRR config mode
+ auto selector = createSelector(kVrrMode_120, kModeId120);
+
+ std::vector<LayerRequirement> layers = {{.ownerUid = 1234, .weight = 1.f},
+ {.ownerUid = 5678, .weight = 1.f}};
+ auto& lr1 = layers[0];
+ auto& lr2 = layers[1];
+
+ lr1.vote = LayerVoteType::ExplicitCategory;
+ lr1.frameRateCategory = FrameRateCategory::Normal;
+ lr1.name = "ExplicitCategory Normal";
+ lr2.vote = LayerVoteType::ExplicitDefault;
+ lr2.desiredRefreshRate = 30_Hz;
+ lr2.name = "30Hz ExplicitDefault";
+ // No global touch boost, for example a game that uses setFrameRate(30, default compatibility).
+ // The `displayFrameRate` is 60.
+ // However 30 Default app still gets frame rate override.
+ auto frameRateOverrides = selector.getFrameRateOverrides(layers, 60_Hz, {});
+ EXPECT_EQ(2u, frameRateOverrides.size());
+ ASSERT_EQ(1u, frameRateOverrides.count(1234));
+ EXPECT_EQ(60_Hz, frameRateOverrides.at(1234));
+ ASSERT_EQ(1u, frameRateOverrides.count(5678));
+ EXPECT_EQ(30_Hz, frameRateOverrides.at(5678));
+
+ lr1.vote = LayerVoteType::ExplicitCategory;
+ lr1.frameRateCategory = FrameRateCategory::HighHint;
+ lr1.name = "ExplicitCategory HighHint";
+ lr2.vote = LayerVoteType::ExplicitDefault;
+ lr2.desiredRefreshRate = 30_Hz;
+ lr2.name = "30Hz ExplicitDefault";
+ // Gets touch boost because the touched (HighHint) app is different from the 30 Default app.
+ // The `displayFrameRate` is 120 (late touch boost).
+ // However 30 Default app still gets frame rate override.
+ frameRateOverrides = selector.getFrameRateOverrides(layers, 120_Hz, {});
+ EXPECT_EQ(1u, frameRateOverrides.size());
+ ASSERT_EQ(1u, frameRateOverrides.count(5678));
+ EXPECT_EQ(30_Hz, frameRateOverrides.at(5678));
+}
+
TEST_P(RefreshRateSelectorTest, getFrameRateOverrides_withFrameRateCategory) {
if (GetParam() == Config::FrameRateOverride::Disabled) {
return;
@@ -4582,5 +4667,47 @@
EXPECT_EQ(120_Hz, primaryRefreshRates[i].modePtr->getPeakFps());
}
}
+
+TEST_P(RefreshRateSelectorTest, getSupportedFrameRates) {
+ if (GetParam() != Config::FrameRateOverride::Enabled) {
+ return;
+ }
+
+ auto selector = createSelector(kModes_60_90, kModeId90);
+ const FpsRange range60 = {0_Hz, 60_Hz};
+ EXPECT_EQ(SetPolicyResult::Changed,
+ selector.setDisplayManagerPolicy(
+ {kModeId60, {range60, range60}, {range60, range60}}));
+
+ // Irrespective of the policy we get the full range of possible frame rates
+ const std::vector<float> expected = {90.0f, 60.0f, 45.0f, 30.0f, 22.5f, 20.0f};
+
+ const auto allSupportedFrameRates = selector.getSupportedFrameRates();
+ ASSERT_EQ(expected.size(), allSupportedFrameRates.size());
+ for (size_t i = 0; i < expected.size(); i++) {
+ EXPECT_EQ(expected[i], allSupportedFrameRates[i])
+ << "expected " << expected[i] << " received " << allSupportedFrameRates[i];
+ }
+}
+
+TEST_P(RefreshRateSelectorTest, getSupportedFrameRatesArr) {
+ if (GetParam() != Config::FrameRateOverride::Enabled) {
+ return;
+ }
+
+ SET_FLAG_FOR_TEST(flags::vrr_config, true);
+ const auto selector = createSelector(kVrrMode_120, kModeId120);
+
+ const std::vector<float> expected = {120.0f, 80.0f, 60.0f, 48.0f, 40.0f, 34.285f,
+ 30.0f, 26.666f, 24.0f, 21.818f, 20.0f};
+
+ const auto allSupportedFrameRates = selector.getSupportedFrameRates();
+ ASSERT_EQ(expected.size(), allSupportedFrameRates.size());
+ constexpr float kEpsilon = 0.001f;
+ for (size_t i = 0; i < expected.size(); i++) {
+ EXPECT_TRUE(std::abs(expected[i] - allSupportedFrameRates[i]) <= kEpsilon)
+ << "expected " << expected[i] << " received " << allSupportedFrameRates[i];
+ }
+}
} // namespace
} // namespace android::scheduler
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index ac09cbc..1fc874d 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -222,7 +222,7 @@
const auto selectorPtr =
std::make_shared<RefreshRateSelector>(kDisplay1Modes, kDisplay1Mode120->getId());
mScheduler->registerDisplay(kDisplayId1, selectorPtr);
- mScheduler->onDisplayModeChanged(kDisplayId1, kDisplay1Mode120_120);
+ mScheduler->onDisplayModeChanged(kDisplayId1, kDisplay1Mode120_120, true);
mScheduler->setContentRequirements({kLayer});
@@ -250,7 +250,7 @@
EXPECT_CALL(*mEventThread, onModeChanged(kDisplay1Mode120_120)).Times(1);
mScheduler->touchTimerCallback(TimerState::Reset);
- mScheduler->onDisplayModeChanged(kDisplayId1, kDisplay1Mode120_120);
+ mScheduler->onDisplayModeChanged(kDisplayId1, kDisplay1Mode120_120, true);
}
TEST_F(SchedulerTest, calculateMaxAcquiredBufferCount) {
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
index 2d3ebb4..aadff76 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
@@ -27,7 +27,8 @@
class CreateDisplayTest : public DisplayTransactionTest {
public:
- void createDisplayWithRequestedRefreshRate(const std::string& name, uint64_t displayId,
+ void createDisplayWithRequestedRefreshRate(const std::string& name,
+ VirtualDisplayId::BaseId baseId,
float pacesetterDisplayRefreshRate,
float requestedRefreshRate,
float expectedAdjustedRefreshRate) {
@@ -49,12 +50,10 @@
EXPECT_EQ(display.requestedRefreshRate, Fps::fromValue(requestedRefreshRate));
EXPECT_EQ(name.c_str(), display.displayName);
- std::optional<VirtualDisplayId> vid =
- DisplayId::fromValue<VirtualDisplayId>(displayId | DisplayId::FLAG_VIRTUAL);
- ASSERT_TRUE(vid.has_value());
-
+ const VirtualDisplayId vid = GpuVirtualDisplayId(baseId);
sp<DisplayDevice> device =
- mFlinger.createVirtualDisplayDevice(displayToken, *vid, requestedRefreshRate);
+ mFlinger.createVirtualDisplayDevice(displayToken, vid, requestedRefreshRate);
+
EXPECT_TRUE(device->isVirtual());
device->adjustRefreshRate(Fps::fromValue(pacesetterDisplayRefreshRate));
// verifying desired value
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
index 8699621..62f1a52 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
@@ -34,7 +34,7 @@
static_cast<hal::HWConfigId>( \
ftl::to_underlying(modeId)), \
_, _)) \
- .WillOnce(DoAll(SetArgPointee<3>(timeline), Return(Error::NONE)))
+ .WillOnce(DoAll(SetArgPointee<3>(timeline), Return(hal::Error::NONE)))
namespace android {
namespace {
@@ -126,8 +126,9 @@
static constexpr HWDisplayId kInnerDisplayHwcId = PrimaryDisplayVariant::HWC_DISPLAY_ID;
static constexpr HWDisplayId kOuterDisplayHwcId = kInnerDisplayHwcId + 1;
-
- static constexpr PhysicalDisplayId kOuterDisplayId = PhysicalDisplayId::fromPort(254u);
+ static constexpr uint8_t kOuterDisplayPort = 254u;
+ static constexpr PhysicalDisplayId kOuterDisplayId =
+ PhysicalDisplayId::fromPort(kOuterDisplayPort);
auto injectOuterDisplay() {
// For the inner display, this is handled by setupHwcHotplugCallExpectations.
@@ -149,6 +150,7 @@
kModeId120);
},
{.displayId = kOuterDisplayId,
+ .port = kOuterDisplayPort,
.hwcDisplayId = kOuterDisplayHwcId,
.isPrimary = kIsPrimary});
@@ -169,16 +171,22 @@
static constexpr DisplayModeId kModeId90{1};
static constexpr DisplayModeId kModeId120{2};
static constexpr DisplayModeId kModeId90_4K{3};
+ static constexpr DisplayModeId kModeId60_8K{4};
static inline const DisplayModePtr kMode60 = createDisplayMode(kModeId60, 60_Hz, 0);
static inline const DisplayModePtr kMode90 = createDisplayMode(kModeId90, 90_Hz, 1);
static inline const DisplayModePtr kMode120 = createDisplayMode(kModeId120, 120_Hz, 2);
static constexpr ui::Size kResolution4K{3840, 2160};
+ static constexpr ui::Size kResolution8K{7680, 4320};
+
static inline const DisplayModePtr kMode90_4K =
createDisplayMode(kModeId90_4K, 90_Hz, 3, kResolution4K);
+ static inline const DisplayModePtr kMode60_8K =
+ createDisplayMode(kModeId60_8K, 60_Hz, 4, kResolution8K);
- static inline const DisplayModes kModes = makeModes(kMode60, kMode90, kMode120, kMode90_4K);
+ static inline const DisplayModes kModes =
+ makeModes(kMode60, kMode90, kMode120, kMode90_4K, kMode60_8K);
};
void DisplayModeSwitchingTest::setupScheduler(
@@ -324,6 +332,8 @@
}
TEST_F(DisplayModeSwitchingTest, changeResolutionWithoutRefreshRequired) {
+ SET_FLAG_FOR_TEST(flags::synced_resolution_switch, false);
+
EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId60));
EXPECT_EQ(NO_ERROR,
@@ -358,6 +368,44 @@
EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId90_4K));
}
+TEST_F(DisplayModeSwitchingTest, changeResolutionSynced) {
+ SET_FLAG_FOR_TEST(flags::synced_resolution_switch, true);
+
+ EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId60));
+
+ // PrimaryDisplayVariant has a 4K size, so switch to 8K.
+ EXPECT_EQ(NO_ERROR,
+ mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(),
+ mock::createDisplayModeSpecs(kModeId60_8K,
+ 60_Hz)));
+
+ EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId60_8K));
+
+ // The mode should not be set until the commit that resizes the display.
+ mFlinger.commit();
+ EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId60_8K));
+ mFlinger.commit();
+ EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId60_8K));
+
+ // Set the display size to match the resolution.
+ DisplayState state;
+ state.what = DisplayState::eDisplaySizeChanged;
+ state.token = mDisplay->getDisplayToken().promote();
+ state.width = static_cast<uint32_t>(kResolution8K.width);
+ state.height = static_cast<uint32_t>(kResolution8K.height);
+
+ // The next commit should set the mode and resize the framebuffer.
+ const VsyncPeriodChangeTimeline timeline{.refreshRequired = false};
+ EXPECT_CALL(*mDisplaySurface, resizeBuffers(kResolution8K));
+ EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId60_8K);
+
+ constexpr bool kModeset = true;
+ mFlinger.setDisplayStateLocked(state);
+ mFlinger.configureAndCommit(kModeset);
+
+ EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId60_8K));
+}
+
TEST_F(DisplayModeSwitchingTest, innerXorOuterDisplay) {
SET_FLAG_FOR_TEST(flags::connected_display, true);
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp
index 9bf344c..1335640 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp
@@ -163,7 +163,7 @@
setupCommonPreconditions<Case>();
// A hotplug connect event is enqueued for a display
- Case::Display::injectPendingHotplugEvent(this, Connection::CONNECTED);
+ Case::Display::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
// --------------------------------------------------------------------
// Call Expectations
@@ -197,7 +197,7 @@
setupCommonPreconditions<Case>();
// A hotplug connect event is enqueued for a display
- Case::Display::injectPendingHotplugEvent(this, Connection::CONNECTED);
+ Case::Display::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
// --------------------------------------------------------------------
// Invocation
@@ -219,7 +219,7 @@
setupCommonPreconditions<Case>();
// A hotplug disconnect event is enqueued for a display
- Case::Display::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
+ Case::Display::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Disconnected);
// The display is already completely set up.
Case::Display::injectHwcDisplay(this);
@@ -327,9 +327,10 @@
setupCommonPreconditions<Case>();
// A hotplug connect event is enqueued for a display
- Case::Display::injectPendingHotplugEvent(this, Connection::CONNECTED);
+ Case::Display::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
// A hotplug disconnect event is also enqueued for the same display
- Case::Display::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
+ Case::Display::injectPendingHotplugEvent(this,
+ HWComposer::HotplugEvent::Disconnected);
// --------------------------------------------------------------------
// Call Expectations
@@ -378,9 +379,10 @@
existing.inject();
// A hotplug disconnect event is enqueued for a display
- Case::Display::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
+ Case::Display::injectPendingHotplugEvent(this,
+ HWComposer::HotplugEvent::Disconnected);
// A hotplug connect event is also enqueued for the same display
- Case::Display::injectPendingHotplugEvent(this, Connection::CONNECTED);
+ Case::Display::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
// --------------------------------------------------------------------
// Call Expectations
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp
index aef467a..b0cda0f 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp
@@ -41,9 +41,9 @@
const auto& pendingEvents = mFlinger.mutablePendingHotplugEvents();
ASSERT_EQ(2u, pendingEvents.size());
EXPECT_EQ(hwcDisplayId1, pendingEvents[0].hwcDisplayId);
- EXPECT_EQ(Connection::CONNECTED, pendingEvents[0].connection);
+ EXPECT_EQ(HWComposer::HotplugEvent::Connected, pendingEvents[0].event);
EXPECT_EQ(hwcDisplayId2, pendingEvents[1].hwcDisplayId);
- EXPECT_EQ(Connection::DISCONNECTED, pendingEvents[1].connection);
+ EXPECT_EQ(HWComposer::HotplugEvent::Disconnected, pendingEvents[1].event);
}
TEST_F(HotplugTest, schedulesFrameToCommitDisplayTransaction) {
@@ -59,6 +59,137 @@
EXPECT_TRUE(hasTransactionFlagSet(eDisplayTransactionNeeded));
}
+TEST_F(HotplugTest, createsDisplaySnapshotsForDisplaysWithIdentificationData) {
+ // Configure a primary display with identification data.
+ using PrimaryDisplay = InnerDisplayVariant;
+ PrimaryDisplay::setupHwcHotplugCallExpectations(this);
+ PrimaryDisplay::setupHwcGetActiveConfigCallExpectations(this);
+ PrimaryDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
+
+ // TODO: b/241286146 - Remove this unnecessary call.
+ EXPECT_CALL(*mComposer,
+ setVsyncEnabled(PrimaryDisplay::HWC_DISPLAY_ID, IComposerClient::Vsync::DISABLE))
+ .WillOnce(Return(Error::NONE));
+
+ // A single commit should be scheduled.
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame(_)).Times(1);
+
+ mFlinger.configure();
+
+ // Configure an external display with identification info.
+ using ExternalDisplay = ExternalDisplayWithIdentificationVariant<>;
+ ExternalDisplay::setupHwcHotplugCallExpectations(this);
+ ExternalDisplay::setupHwcGetActiveConfigCallExpectations(this);
+ ExternalDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
+
+ // TODO: b/241286146 - Remove this unnecessary call.
+ EXPECT_CALL(*mComposer,
+ setVsyncEnabled(ExternalDisplay::HWC_DISPLAY_ID, IComposerClient::Vsync::DISABLE))
+ .WillOnce(Return(Error::NONE));
+
+ mFlinger.configure();
+
+ EXPECT_TRUE(hasPhysicalHwcDisplay(PrimaryDisplay::HWC_DISPLAY_ID));
+ EXPECT_TRUE(mFlinger.getHwComposer().isConnected(PrimaryDisplay::DISPLAY_ID::get()));
+ const auto primaryDisplayIdOpt =
+ mFlinger.getHwComposer().toPhysicalDisplayId(PrimaryDisplay::HWC_DISPLAY_ID);
+ ASSERT_TRUE(primaryDisplayIdOpt.has_value());
+ const auto primaryPhysicalDisplayOpt =
+ mFlinger.physicalDisplays().get(primaryDisplayIdOpt.value());
+ ASSERT_TRUE(primaryPhysicalDisplayOpt.has_value());
+ const auto primaryDisplaySnapshotRef = primaryPhysicalDisplayOpt->get().snapshotRef();
+ EXPECT_EQ(PrimaryDisplay::DISPLAY_ID::get(), primaryDisplaySnapshotRef.get().displayId());
+ EXPECT_EQ(PrimaryDisplay::PORT::value, primaryDisplaySnapshotRef.get().port());
+ EXPECT_EQ(PrimaryDisplay::CONNECTION_TYPE::value,
+ primaryDisplaySnapshotRef.get().connectionType());
+
+ EXPECT_TRUE(hasPhysicalHwcDisplay(ExternalDisplay::HWC_DISPLAY_ID));
+ EXPECT_TRUE(mFlinger.getHwComposer().isConnected(ExternalDisplay::DISPLAY_ID::get()));
+ const auto externalDisplayIdOpt =
+ mFlinger.getHwComposer().toPhysicalDisplayId(ExternalDisplay::HWC_DISPLAY_ID);
+ ASSERT_TRUE(externalDisplayIdOpt.has_value());
+ const auto externalPhysicalDisplayOpt =
+ mFlinger.physicalDisplays().get(externalDisplayIdOpt.value());
+ ASSERT_TRUE(externalPhysicalDisplayOpt.has_value());
+ const auto externalDisplaySnapshotRef = externalPhysicalDisplayOpt->get().snapshotRef();
+ EXPECT_EQ(ExternalDisplay::DISPLAY_ID::get(), externalDisplaySnapshotRef.get().displayId());
+ EXPECT_EQ(ExternalDisplay::PORT::value, externalDisplaySnapshotRef.get().port());
+ EXPECT_EQ(ExternalDisplay::CONNECTION_TYPE::value,
+ externalDisplaySnapshotRef.get().connectionType());
+}
+
+TEST_F(HotplugTest, createsDisplaySnapshotsForDisplaysWithoutIdentificationData) {
+ // Configure a primary display without identification data.
+ using PrimaryDisplay = PrimaryDisplayVariant;
+ PrimaryDisplay::setupHwcHotplugCallExpectations(this);
+ PrimaryDisplay::setupHwcGetActiveConfigCallExpectations(this);
+ PrimaryDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
+
+ // TODO: b/241286146 - Remove this unnecessary call.
+ EXPECT_CALL(*mComposer,
+ setVsyncEnabled(PrimaryDisplay::HWC_DISPLAY_ID, IComposerClient::Vsync::DISABLE))
+ .WillOnce(Return(Error::NONE));
+
+ // A single commit should be scheduled.
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame(_)).Times(1);
+
+ mFlinger.configure();
+
+ // Configure an external display with identification info.
+ using ExternalDisplay = ExternalDisplayWithIdentificationVariant<>;
+ ExternalDisplay::setupHwcHotplugCallExpectations(this);
+ ExternalDisplay::setupHwcGetActiveConfigCallExpectations(this);
+ ExternalDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
+
+ // TODO: b/241286146 - Remove this unnecessary call.
+ EXPECT_CALL(*mComposer,
+ setVsyncEnabled(ExternalDisplay::HWC_DISPLAY_ID, IComposerClient::Vsync::DISABLE))
+ .WillOnce(Return(Error::NONE));
+
+ mFlinger.configure();
+
+ // Both ID and port are expected to be equal to 0 for primary internal display due to no
+ // identification data.
+ constexpr uint8_t primaryInternalDisplayPort = 0u;
+ constexpr PhysicalDisplayId primaryInternalDisplayId =
+ PhysicalDisplayId::fromPort(primaryInternalDisplayPort);
+ EXPECT_TRUE(hasPhysicalHwcDisplay(PrimaryDisplay::HWC_DISPLAY_ID));
+ ASSERT_EQ(primaryInternalDisplayId, PrimaryDisplay::DISPLAY_ID::get());
+ EXPECT_TRUE(mFlinger.getHwComposer().isConnected(PrimaryDisplay::DISPLAY_ID::get()));
+ const auto primaryDisplayIdOpt =
+ mFlinger.getHwComposer().toPhysicalDisplayId(PrimaryDisplay::HWC_DISPLAY_ID);
+ ASSERT_TRUE(primaryDisplayIdOpt.has_value());
+ const auto primaryPhysicalDisplayOpt =
+ mFlinger.physicalDisplays().get(primaryDisplayIdOpt.value());
+ ASSERT_TRUE(primaryPhysicalDisplayOpt.has_value());
+ const auto primaryDisplaySnapshotRef = primaryPhysicalDisplayOpt->get().snapshotRef();
+ EXPECT_EQ(primaryInternalDisplayId, primaryDisplaySnapshotRef.get().displayId());
+ EXPECT_EQ(primaryInternalDisplayPort, primaryDisplaySnapshotRef.get().port());
+ EXPECT_EQ(PrimaryDisplay::CONNECTION_TYPE::value,
+ primaryDisplaySnapshotRef.get().connectionType());
+
+ // Even though the external display has identification data available, the lack of data for the
+ // internal display has set of the legacy multi-display mode in SF and therefore the external
+ // display's identification data will be ignored.
+ // Both ID and port are expected to be equal to 1 for external internal display.
+ constexpr uint8_t externalDisplayPort = 1u;
+ constexpr PhysicalDisplayId externalDisplayId =
+ PhysicalDisplayId::fromPort(externalDisplayPort);
+ EXPECT_TRUE(hasPhysicalHwcDisplay(ExternalDisplay::HWC_DISPLAY_ID));
+ EXPECT_TRUE(mFlinger.getHwComposer().isConnected(externalDisplayId));
+ const auto externalDisplayIdOpt =
+ mFlinger.getHwComposer().toPhysicalDisplayId(ExternalDisplay::HWC_DISPLAY_ID);
+ ASSERT_TRUE(externalDisplayIdOpt.has_value());
+ const auto externalPhysicalDisplayOpt =
+ mFlinger.physicalDisplays().get(externalDisplayIdOpt.value());
+ ASSERT_TRUE(externalPhysicalDisplayOpt.has_value());
+ const auto externalDisplaySnapshotRef = externalPhysicalDisplayOpt->get().snapshotRef();
+ EXPECT_EQ(externalDisplayId, externalDisplaySnapshotRef.get().displayId());
+ EXPECT_EQ(externalDisplayPort, externalDisplaySnapshotRef.get().port());
+ EXPECT_EQ(ExternalDisplay::CONNECTION_TYPE::value,
+ externalDisplaySnapshotRef.get().connectionType());
+}
+
TEST_F(HotplugTest, ignoresDuplicateDisconnection) {
// Inject a primary display.
PrimaryDisplayVariant::injectHwcDisplay(this);
@@ -67,7 +198,7 @@
ExternalDisplay::setupHwcHotplugCallExpectations(this);
ExternalDisplay::setupHwcGetActiveConfigCallExpectations(this);
- // TODO(b/241286146): Remove this unnecessary call.
+ // TODO: b/241286146 - Remove this unnecessary call.
EXPECT_CALL(*mComposer,
setVsyncEnabled(ExternalDisplay::HWC_DISPLAY_ID, IComposerClient::Vsync::DISABLE))
.WillOnce(Return(Error::NONE));
@@ -75,15 +206,15 @@
// A single commit should be scheduled for both configure calls.
EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame(_)).Times(1);
- ExternalDisplay::injectPendingHotplugEvent(this, Connection::CONNECTED);
+ ExternalDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
mFlinger.configure();
EXPECT_TRUE(hasPhysicalHwcDisplay(ExternalDisplay::HWC_DISPLAY_ID));
// Disconnecting a display that was already disconnected should be a no-op.
- ExternalDisplay::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
- ExternalDisplay::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
- ExternalDisplay::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
+ ExternalDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Disconnected);
+ ExternalDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Disconnected);
+ ExternalDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Disconnected);
mFlinger.configure();
// The display should be scheduled for removal during the next commit. At this point, it should
@@ -111,24 +242,73 @@
EXPECT_CALL(*mComposer, getActiveConfig(ExternalDisplay::HWC_DISPLAY_ID, _))
.WillRepeatedly(Return(Error::BAD_DISPLAY));
- // TODO(b/241286146): Remove this unnecessary call.
+ // TODO: b/241286146 - Remove this unnecessary call.
EXPECT_CALL(*mComposer,
setVsyncEnabled(ExternalDisplay::HWC_DISPLAY_ID, IComposerClient::Vsync::DISABLE))
.WillOnce(Return(Error::NONE));
EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame(_)).Times(1);
- ExternalDisplay::injectPendingHotplugEvent(this, Connection::CONNECTED);
+ ExternalDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
mFlinger.configure();
// The hotplug should be rejected, so no HWComposer::DisplayData should be created.
EXPECT_FALSE(hasPhysicalHwcDisplay(ExternalDisplay::HWC_DISPLAY_ID));
// Disconnecting a display that does not exist should be a no-op.
- ExternalDisplay::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
+ ExternalDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Disconnected);
mFlinger.configure();
EXPECT_FALSE(hasPhysicalHwcDisplay(ExternalDisplay::HWC_DISPLAY_ID));
}
+TEST_F(HotplugTest, rejectsHotplugOnActivePortsDuplicate) {
+ SET_FLAG_FOR_TEST(flags::connected_display, true);
+
+ // Inject a primary display.
+ PrimaryDisplayVariant::injectHwcDisplay(this);
+
+ // Second display should come up properly.
+ using SecondDisplay = ExternalDisplayWithIdentificationVariant<>;
+ SecondDisplay::setupHwcHotplugCallExpectations(this);
+ SecondDisplay::setupHwcGetActiveConfigCallExpectations(this);
+
+ // TODO: b/241286146 - Remove this unnecessary call.
+ EXPECT_CALL(*mComposer,
+ setVsyncEnabled(SecondDisplay::HWC_DISPLAY_ID, IComposerClient::Vsync::DISABLE))
+ .WillOnce(Return(Error::NONE));
+
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame(_)).Times(1);
+
+ SecondDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
+ mFlinger.configure();
+
+ EXPECT_TRUE(hasPhysicalHwcDisplay(SecondDisplay::HWC_DISPLAY_ID));
+
+ // Third display will return the same port ID as the second, and the hotplug
+ // should fail.
+ constexpr HWDisplayId kHwDisplayId = 1234;
+ using DuplicatePortDisplay = ExternalDisplayWithIdentificationVariant<kHwDisplayId>;
+
+ // We expect display identification to be fetched correctly, since EDID and
+ // port are available and successfully retrieved from HAL.
+ EXPECT_CALL(*mComposer,
+ getDisplayIdentificationData(DuplicatePortDisplay::HWC_DISPLAY_ID, _, _))
+ .WillOnce(DoAll(SetArgPointee<1>(*DuplicatePortDisplay::PORT::value),
+ SetArgPointee<2>(getExternalEedid()), Return(Error::NONE)));
+
+ DuplicatePortDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
+ mFlinger.configure();
+
+ // The hotplug should be rejected due to an attempt to connect a display to an already active
+ // port. No HWComposer::DisplayData should be created.
+ EXPECT_FALSE(hasPhysicalHwcDisplay(DuplicatePortDisplay::HWC_DISPLAY_ID));
+
+ // Disconnecting a display that was not successfully configured should be a no-op.
+ DuplicatePortDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Disconnected);
+ mFlinger.configure();
+
+ EXPECT_FALSE(hasPhysicalHwcDisplay(DuplicatePortDisplay::HWC_DISPLAY_ID));
+}
+
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyExpectedPresentTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyExpectedPresentTest.cpp
index 20a3315..6cc6322 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyExpectedPresentTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyExpectedPresentTest.cpp
@@ -18,12 +18,13 @@
#define LOG_TAG "LibSurfaceFlingerUnittests"
#include <gui/SurfaceComposerClient.h>
+#include "DisplayHardware/Hal.h"
#include "DisplayTransactionTestHelpers.h"
namespace android {
using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector;
-using android::hardware::graphics::composer::V2_1::Error;
+using android::hardware::graphics::composer::hal::Error;
class NotifyExpectedPresentTest : public DisplayTransactionTest {
public:
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_PowerHintTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_PowerHintTest.cpp
index c3934e6..3ae5ed9 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_PowerHintTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_PowerHintTest.cpp
@@ -21,6 +21,8 @@
#include "CommitAndCompositeTest.h"
+#include "DisplayHardware/Hal.h"
+
using namespace std::chrono_literals;
using testing::_;
using testing::Return;
@@ -40,7 +42,7 @@
EXPECT_CALL(*mComposer, presentOrValidateDisplay(HWC_DISPLAY, _, _, _, _, _, _)).WillOnce([] {
constexpr Duration kMockHwcRunTime = 20ms;
std::this_thread::sleep_for(kMockHwcRunTime);
- return hardware::graphics::composer::V2_1::Error::NONE;
+ return hardware::graphics::composer::hal::Error::NONE;
});
EXPECT_CALL(*mPowerAdvisor, reportActualWorkDuration()).Times(1);
@@ -61,7 +63,7 @@
EXPECT_CALL(*mComposer, presentOrValidateDisplay(HWC_DISPLAY, _, _, _, _, _, _)).WillOnce([] {
constexpr Duration kMockHwcRunTime = 20ms;
std::this_thread::sleep_for(kMockHwcRunTime);
- return hardware::graphics::composer::V2_1::Error::NONE;
+ return hardware::graphics::composer::hal::Error::NONE;
});
EXPECT_CALL(*mPowerAdvisor, reportActualWorkDuration()).Times(0);
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
index 352000e..cd554ea 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
@@ -239,7 +239,10 @@
ASSERT_TRUE(displayId);
const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value;
ASSERT_TRUE(hwcDisplayId);
- mFlinger.getHwComposer().allocatePhysicalDisplay(*hwcDisplayId, *displayId, std::nullopt);
+ const auto port = Case::Display::PORT::value;
+ ASSERT_TRUE(port);
+ mFlinger.getHwComposer().allocatePhysicalDisplay(*hwcDisplayId, *displayId, *port,
+ std::nullopt);
DisplayModePtr activeMode = DisplayMode::Builder(Case::Display::HWC_ACTIVE_CONFIG_ID)
.setResolution(Case::Display::RESOLUTION)
.setVsyncPeriod(DEFAULT_VSYNC_PERIOD)
@@ -250,6 +253,7 @@
state.physical = {.id = *displayId,
.hwcDisplayId = *hwcDisplayId,
+ .port = *port,
.activeMode = activeMode};
ui::ColorModes colorModes;
@@ -258,7 +262,7 @@
}
const auto it = mFlinger.mutablePhysicalDisplays()
- .emplace_or_replace(*displayId, displayToken, *displayId,
+ .emplace_or_replace(*displayId, displayToken, *displayId, *port,
*kConnectionTypeOpt, makeModes(activeMode),
std::move(colorModes), std::nullopt)
.first;
@@ -299,6 +303,13 @@
mFlinger.mutableDisplayModeController()
.getActiveMode(device->getPhysicalId())
.modePtr->getHwcId());
+
+ EXPECT_EQ(Case::Display::PORT::value,
+ mFlinger.physicalDisplays()
+ .get(device->getPhysicalId())
+ .transform([](const display::PhysicalDisplay& display) {
+ return display.snapshot().port();
+ }));
}
}
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 4dec5f6..8084450 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -42,24 +42,23 @@
#include "FrontEnd/RequestedLayerState.h"
#include "Layer.h"
#include "NativeWindowSurface.h"
-#include "RenderArea.h"
#include "Scheduler/RefreshRateSelector.h"
+#include "Scheduler/VSyncTracker.h"
+#include "Scheduler/VsyncController.h"
#include "SurfaceFlinger.h"
#include "TestableScheduler.h"
#include "android/gui/ISurfaceComposerClient.h"
+
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/DisplayHardware/MockDisplayMode.h"
-#include "mock/DisplayHardware/MockPowerAdvisor.h"
#include "mock/MockEventThread.h"
#include "mock/MockFrameTimeline.h"
#include "mock/MockFrameTracer.h"
#include "mock/MockSchedulerCallback.h"
-#include "mock/system/window/MockNativeWindow.h"
-
-#include "Scheduler/VSyncTracker.h"
-#include "Scheduler/VsyncController.h"
#include "mock/MockVSyncTracker.h"
#include "mock/MockVsyncController.h"
+#include "mock/PowerAdvisor/MockPowerAdvisor.h"
+#include "mock/system/window/MockNativeWindow.h"
namespace android {
@@ -184,13 +183,13 @@
}
void setupComposer(std::unique_ptr<Hwc2::Composer> composer) {
- mFlinger->mCompositionEngine->setHwComposer(
- std::make_unique<impl::HWComposer>(std::move(composer)));
+ mFlinger->mHWComposer = std::make_unique<impl::HWComposer>(std::move(composer));
+ mFlinger->mCompositionEngine->setHwComposer(mFlinger->mHWComposer.get());
mFlinger->mDisplayModeController.setHwComposer(
&mFlinger->mCompositionEngine->getHwComposer());
}
- void setupPowerAdvisor(std::unique_ptr<Hwc2::PowerAdvisor> powerAdvisor) {
+ void setupPowerAdvisor(std::unique_ptr<adpf::PowerAdvisor> powerAdvisor) {
mFlinger->mPowerAdvisor = std::move(powerAdvisor);
}
@@ -338,9 +337,9 @@
mFlinger->configure();
}
- void configureAndCommit() {
+ void configureAndCommit(bool modeset = false) {
configure();
- commitTransactionsLocked(eDisplayTransactionNeeded);
+ commitTransactionsLocked(eDisplayTransactionNeeded, modeset);
}
void commit(TimePoint frameTime, VsyncId vsyncId, TimePoint expectedVsyncTime,
@@ -430,11 +429,14 @@
dispSurface, producer);
}
- void commitTransactionsLocked(uint32_t transactionFlags) {
+ void commitTransactionsLocked(uint32_t transactionFlags, bool modeset = false) {
Mutex::Autolock lock(mFlinger->mStateLock);
ftl::FakeGuard guard(kMainThreadContext);
mFlinger->processDisplayChangesLocked();
mFlinger->commitTransactionsLocked(transactionFlags);
+ if (modeset) {
+ mFlinger->initiateDisplayModeChanges();
+ }
}
void onComposerHalHotplugEvent(hal::HWDisplayId hwcDisplayId, DisplayHotplugEvent event) {
@@ -461,23 +463,34 @@
return mFlinger->setPowerModeInternal(display, mode);
}
- auto renderScreenImpl(const sp<DisplayDevice> display,
- std::unique_ptr<const RenderArea> renderArea,
+ auto renderScreenImpl(const sp<DisplayDevice> display, const Rect sourceCrop,
+ ui::Dataspace dataspace,
SurfaceFlinger::GetLayerSnapshotsFunction getLayerSnapshotsFn,
const std::shared_ptr<renderengine::ExternalTexture>& buffer,
- bool regionSampling) {
+ bool regionSampling, bool isSecure, bool seamlessTransition) {
Mutex::Autolock lock(mFlinger->mStateLock);
ftl::FakeGuard guard(kMainThreadContext);
ScreenCaptureResults captureResults;
- auto displayState = std::optional{display->getCompositionDisplay()->getState()};
+ const auto& state = display->getCompositionDisplay()->getState();
auto layers = getLayerSnapshotsFn();
- auto layerFEs = mFlinger->extractLayerFEs(layers);
- return mFlinger->renderScreenImpl(renderArea.get(), buffer, regionSampling,
+ SurfaceFlinger::ScreenshotArgs screenshotArgs;
+ screenshotArgs.captureTypeVariant = display;
+ screenshotArgs.displayId = std::nullopt;
+ screenshotArgs.sourceCrop = sourceCrop;
+ screenshotArgs.reqSize = sourceCrop.getSize();
+ screenshotArgs.dataspace = dataspace;
+ screenshotArgs.isSecure = isSecure;
+ screenshotArgs.seamlessTransition = seamlessTransition;
+ screenshotArgs.displayBrightnessNits = state.displayBrightnessNits;
+ screenshotArgs.sdrWhitePointNits = state.sdrWhitePointNits;
+ screenshotArgs.renderIntent = state.renderIntent;
+ screenshotArgs.colorMode = state.colorMode;
+
+ return mFlinger->renderScreenImpl(screenshotArgs, buffer, regionSampling,
false /* grayscale */, false /* isProtected */,
- false /* attachGainmap */, captureResults, displayState,
- layers, layerFEs);
+ captureResults, layers);
}
auto getLayerSnapshotsForScreenshotsFn(ui::LayerStack layerStack, uint32_t uid) {
@@ -516,7 +529,7 @@
mergedTransactionIds);
}
- auto setTransactionStateInternal(TransactionState& transaction) {
+ auto setTransactionStateInternal(QueuedTransactionState& transaction) {
return FTL_FAKE_GUARD(kMainThreadContext,
mFlinger->mTransactionHandler.queueTransaction(
std::move(transaction)));
@@ -773,7 +786,8 @@
mutableCurrentState().displays.clear();
mutableDrawingState().displays.clear();
mFlinger->mScheduler.reset();
- mFlinger->mCompositionEngine->setHwComposer(std::unique_ptr<HWComposer>());
+ mFlinger->mHWComposer = std::unique_ptr<HWComposer>();
+ mFlinger->mCompositionEngine->setHwComposer(mFlinger->mHWComposer.get());
mFlinger->mRenderEngine = std::unique_ptr<renderengine::RenderEngine>();
mFlinger->mCompositionEngine->setRenderEngine(mFlinger->mRenderEngine.get());
mFlinger->mTransactionTracing.reset();
@@ -949,11 +963,13 @@
FakeDisplayDeviceInjector(TestableSurfaceFlinger& flinger,
std::shared_ptr<compositionengine::Display> display,
std::optional<ui::DisplayConnectionType> connectionType,
+ std::optional<uint8_t> port,
std::optional<hal::HWDisplayId> hwcDisplayId, bool isPrimary)
: mFlinger(flinger),
mCreationArgs(flinger.mFlinger, flinger.mFlinger->getHwComposer(), mDisplayToken,
display),
mConnectionType(connectionType),
+ mPort(port),
mHwcDisplayId(hwcDisplayId) {
mCreationArgs.isPrimary = isPrimary;
mCreationArgs.initialPowerMode = hal::PowerMode::ON;
@@ -1102,11 +1118,12 @@
.hwcDisplayId = *mHwcDisplayId,
.activeMode = activeModeOpt->get()};
- const auto it = mFlinger.mutablePhysicalDisplays()
- .emplace_or_replace(*physicalId, mDisplayToken, *physicalId,
- *mConnectionType, std::move(modes),
- ui::ColorModes(), std::nullopt)
- .first;
+ const auto it =
+ mFlinger.mutablePhysicalDisplays()
+ .emplace_or_replace(*physicalId, mDisplayToken, *physicalId, *mPort,
+ *mConnectionType, std::move(modes),
+ ui::ColorModes(), std::nullopt)
+ .first;
mFlinger.mutableDisplayModeController()
.registerDisplay(*physicalId, it->second.snapshot(),
@@ -1140,6 +1157,7 @@
DisplayModeId mActiveModeId;
bool mSchedulerRegistration = true;
const std::optional<ui::DisplayConnectionType> mConnectionType;
+ const std::optional<uint8_t> mPort;
const std::optional<hal::HWDisplayId> mHwcDisplayId;
};
@@ -1162,7 +1180,7 @@
scheduler::mock::NoOpSchedulerCallback mNoOpSchedulerCallback;
std::unique_ptr<frametimeline::impl::TokenManager> mTokenManager;
scheduler::TestableScheduler* mScheduler = nullptr;
- Hwc2::mock::PowerAdvisor mPowerAdvisor;
+ adpf::mock::PowerAdvisor mPowerAdvisor;
};
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index 1e8cd0a..69dfcc4 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -33,8 +33,8 @@
#include <vector>
#include "FrontEnd/TransactionHandler.h"
+#include "QueuedTransactionState.h"
#include "TestableSurfaceFlinger.h"
-#include "TransactionState.h"
#include <com_android_graphics_surfaceflinger_flags.h>
@@ -84,7 +84,7 @@
static_assert(0xffffffffffffffff == static_cast<uint64_t>(-1));
};
- void checkEqual(TransactionInfo info, TransactionState state) {
+ void checkEqual(TransactionInfo info, QueuedTransactionState state) {
EXPECT_EQ(0u, info.states.size());
EXPECT_EQ(0u, state.states.size());
@@ -318,7 +318,7 @@
auto applyToken2 = sp<BBinder>::make();
// Transaction 1 has a buffer with an unfired fence. It should not be ready to be applied.
- TransactionState transaction1;
+ QueuedTransactionState transaction1;
transaction1.applyToken = applyToken1;
transaction1.id = 42069;
transaction1.states.emplace_back();
@@ -340,7 +340,7 @@
transaction1.isAutoTimestamp = true;
// Transaction 2 should be ready to be applied.
- TransactionState transaction2;
+ QueuedTransactionState transaction2;
transaction2.applyToken = applyToken2;
transaction2.id = 2;
transaction2.isAutoTimestamp = true;
@@ -446,15 +446,15 @@
resolvedStates.emplace_back(resolvedState);
}
- TransactionState transactionState(transaction.frameTimelineInfo, resolvedStates,
- transaction.displays, transaction.flags,
- transaction.applyToken,
- transaction.inputWindowCommands,
- transaction.desiredPresentTime,
- transaction.isAutoTimestamp, {}, systemTime(),
- mHasListenerCallbacks, mCallbacks, getpid(),
- static_cast<int>(getuid()), transaction.id,
- transaction.mergedTransactionIds);
+ QueuedTransactionState transactionState(transaction.frameTimelineInfo, resolvedStates,
+ transaction.displays, transaction.flags,
+ transaction.applyToken,
+ transaction.inputWindowCommands,
+ transaction.desiredPresentTime,
+ transaction.isAutoTimestamp, {}, systemTime(),
+ mHasListenerCallbacks, mCallbacks, getpid(),
+ static_cast<int>(getuid()), transaction.id,
+ transaction.mergedTransactionIds);
mFlinger.setTransactionStateInternal(transactionState);
}
mFlinger.flushTransactionQueues();
@@ -955,12 +955,12 @@
TEST(TransactionHandlerTest, QueueTransaction) {
TransactionHandler handler;
- TransactionState transaction;
+ QueuedTransactionState transaction;
transaction.applyToken = sp<BBinder>::make();
transaction.id = 42;
handler.queueTransaction(std::move(transaction));
handler.collectTransactions();
- std::vector<TransactionState> transactionsReadyToBeApplied = handler.flushTransactions();
+ std::vector<QueuedTransactionState> transactionsReadyToBeApplied = handler.flushTransactions();
EXPECT_EQ(transactionsReadyToBeApplied.size(), 1u);
EXPECT_EQ(transactionsReadyToBeApplied.front().id, 42u);
diff --git a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp
index af02330..d3eec5c 100644
--- a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp
@@ -30,7 +30,7 @@
TEST(TransactionProtoParserTest, parse) {
const sp<IBinder> displayHandle = sp<BBinder>::make();
- TransactionState t1;
+ QueuedTransactionState t1;
t1.originPid = 1;
t1.originUid = 2;
t1.frameTimelineInfo.vsyncId = 3;
@@ -86,7 +86,7 @@
TransactionProtoParser parser(std::make_unique<TestMapper>(displayHandle));
perfetto::protos::TransactionState proto = parser.toProto(t1);
- TransactionState t2 = parser.fromProto(proto);
+ QueuedTransactionState t2 = parser.fromProto(proto);
ASSERT_EQ(t1.originPid, t2.originPid);
ASSERT_EQ(t1.originUid, t2.originUid);
diff --git a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
index f8f08c7..036d8c4 100644
--- a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
@@ -49,19 +49,19 @@
void queueAndCommitTransaction(int64_t vsyncId) {
frontend::Update update;
- TransactionState transaction;
+ QueuedTransactionState transaction;
transaction.id = static_cast<uint64_t>(vsyncId * 3);
transaction.originUid = 1;
transaction.originPid = 2;
mTracing.addQueuedTransaction(transaction);
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
update.transactions.emplace_back(transaction);
mTracing.addCommittedTransactions(vsyncId, 0, update, {}, false);
flush();
}
void verifyEntry(const perfetto::protos::TransactionTraceEntry& actualProto,
- const std::vector<TransactionState>& expectedTransactions,
+ const std::vector<QueuedTransactionState>& expectedTransactions,
int64_t expectedVsyncId) {
EXPECT_EQ(actualProto.vsync_id(), expectedVsyncId);
ASSERT_EQ(actualProto.transactions().size(),
@@ -92,10 +92,10 @@
};
TEST_F(TransactionTracingTest, addTransactions) {
- std::vector<TransactionState> transactions;
+ std::vector<QueuedTransactionState> transactions;
transactions.reserve(100);
for (uint64_t i = 0; i < 100; i++) {
- TransactionState transaction;
+ QueuedTransactionState transaction;
transaction.id = i;
transaction.originPid = static_cast<int32_t>(i);
transaction.mergedTransactionIds = std::vector<uint64_t>{i + 100, i + 102};
@@ -108,13 +108,13 @@
int64_t firstTransactionSetVsyncId = 42;
frontend::Update firstUpdate;
firstUpdate.transactions =
- std::vector<TransactionState>(transactions.begin() + 50, transactions.end());
+ std::vector<QueuedTransactionState>(transactions.begin() + 50, transactions.end());
mTracing.addCommittedTransactions(firstTransactionSetVsyncId, 0, firstUpdate, {}, false);
int64_t secondTransactionSetVsyncId = 43;
frontend::Update secondUpdate;
secondUpdate.transactions =
- std::vector<TransactionState>(transactions.begin(), transactions.begin() + 50);
+ std::vector<QueuedTransactionState>(transactions.begin(), transactions.begin() + 50);
mTracing.addCommittedTransactions(secondTransactionSetVsyncId, 0, secondUpdate, {}, false);
flush();
@@ -140,7 +140,7 @@
getLayerCreationArgs(mChildLayerId, mParentLayerId,
/*layerIdToMirror=*/UNASSIGNED_LAYER_ID, /*flags=*/456,
/*addToRoot=*/true));
- TransactionState transaction;
+ QueuedTransactionState transaction;
transaction.id = 50;
ResolvedComposerState layerState;
layerState.layerId = mParentLayerId;
@@ -164,7 +164,7 @@
// add transactions that modify the layer state further so we can test that layer state
// gets merged
{
- TransactionState transaction;
+ QueuedTransactionState transaction;
transaction.id = 51;
ResolvedComposerState layerState;
layerState.layerId = mParentLayerId;
@@ -278,7 +278,7 @@
/*layerIdToMirror=*/mLayerId, /*flags=*/0,
/*addToRoot=*/false));
- TransactionState transaction;
+ QueuedTransactionState transaction;
transaction.id = 50;
ResolvedComposerState layerState;
layerState.layerId = mLayerId;
diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
index 918107d..a221d5e 100644
--- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
@@ -304,6 +304,53 @@
EXPECT_THAT(intercept, IsCloseTo(expectedIntercept, mMaxRoundingError));
}
+TEST_F(VSyncPredictorTest, recoverAfterDriftedVSyncAreReplacedWithCorrectVSync) {
+ SET_FLAG_FOR_TEST(flags::vsync_predictor_recovery, true);
+ auto constexpr idealPeriodNs = 4166666;
+ auto constexpr minFrameIntervalNs = 8333333;
+ auto constexpr idealPeriod = Fps::fromPeriodNsecs(idealPeriodNs);
+ auto constexpr minFrameRate = Fps::fromPeriodNsecs(minFrameIntervalNs);
+ hal::VrrConfig vrrConfig{.minFrameIntervalNs = minFrameIntervalNs};
+ ftl::NonNull<DisplayModePtr> mode =
+ ftl::as_non_null(createVrrDisplayMode(DisplayModeId(0), idealPeriod, vrrConfig));
+ VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), mode, kHistorySize,
+ kMinimumSamplesForPrediction, kOutlierTolerancePercent};
+ vrrTracker.setRenderRate(minFrameRate, /*applyImmediately*/ true);
+ // Curated list of VSyncs that causes the VSync drift.
+ std::vector<nsecs_t> const simulatedVsyncs{74473665741, 74481774375, 74489911818, 74497993491,
+ 74506000833, 74510002150, 74513904390, 74517748707,
+ 74521550947, 74525383187, 74529165427, 74533067667,
+ 74536751484, 74540653724, 74544282649, 74548084889,
+ 74551917129, 74555699369, 74559601609, 74563601611,
+ 74567503851, 74571358168, 74575260408, 74578889333,
+ 74582691573, 74586523813, 74590306053, 74593589870,
+ 74597492110, 74601121035, 74604923275, 74608755515,
+ 74612537755, 74616166680, 74619795605, 74623424530,
+ 74627043455, 74630645695, 74634245935, 74637778175,
+ 74641291992, 74644794232, 74648275157, 74651575397,
+ 74654807637, 74658007877, 74661176117, 74664345357};
+ for (auto const& timestamp : simulatedVsyncs) {
+ vrrTracker.addVsyncTimestamp(timestamp);
+ }
+ auto slope = vrrTracker.getVSyncPredictionModel().slope;
+ // Without using the idealPeriod for the calculation of the VSync predictor mode the
+ // the slope would be 3343031
+ EXPECT_THAT(slope, IsCloseTo(4347805, mMaxRoundingError));
+ EXPECT_FALSE(vrrTracker.needsMoreSamples());
+
+ auto lastVsync = 74664345357;
+ // Add valid VSyncs to replace the drifted VSyncs
+ for (int i = 0; i <= kHistorySize; i++) {
+ lastVsync += minFrameIntervalNs;
+ EXPECT_TRUE(vrrTracker.addVsyncTimestamp(lastVsync));
+ }
+ EXPECT_FALSE(vrrTracker.needsMoreSamples());
+ slope = vrrTracker.getVSyncPredictionModel().slope;
+ // Corrected slop is closer to the idealPeriod
+ // when valid vsync are inserted otherwise this would still be 3349673
+ EXPECT_THAT(slope, IsCloseTo(idealPeriodNs, mMaxRoundingError));
+}
+
TEST_F(VSyncPredictorTest, handlesVsyncChange) {
auto const fastPeriod = 100;
auto const fastTimeBase = 100;
@@ -397,8 +444,8 @@
}
}
-// See b/145667109, and comment in prod code under test.
-TEST_F(VSyncPredictorTest, doesNotPredictBeforeTimePointWithHigherIntercept) {
+TEST_F(VSyncPredictorTest, doesNotPredictBeforeTimePointWithHigherIntercept_withPredictorRecovery) {
+ SET_FLAG_FOR_TEST(flags::vsync_predictor_recovery, true);
std::vector<nsecs_t> const simulatedVsyncs{
158929578733000,
158929306806205, // oldest TS in ringbuffer
@@ -409,6 +456,34 @@
158929706370359,
};
auto const idealPeriod = 11111111;
+ auto const expectedPeriod = 11079563;
+ auto const expectedIntercept = 1335662;
+
+ tracker.setDisplayModePtr(displayMode(idealPeriod));
+ for (auto const& timestamp : simulatedVsyncs) {
+ tracker.addVsyncTimestamp(timestamp);
+ }
+
+ auto [slope, intercept] = tracker.getVSyncPredictionModel();
+ EXPECT_THAT(slope, IsCloseTo(expectedPeriod, mMaxRoundingError));
+ EXPECT_THAT(intercept, IsCloseTo(expectedIntercept, mMaxRoundingError));
+
+ // (timePoint - oldestTS) % expectedPeriod works out to be: 894272
+ // (timePoint - oldestTS) / expectedPeriod works out to be: 38.08
+ auto const timePoint = 158929728723871;
+ auto const prediction = tracker.nextAnticipatedVSyncTimeFrom(timePoint);
+ EXPECT_THAT(prediction, Ge(timePoint));
+}
+
+// See b/145667109, and comment in prod code under test.
+TEST_F(VSyncPredictorTest, doesNotPredictBeforeTimePointWithHigherIntercept) {
+ SET_FLAG_FOR_TEST(flags::vsync_predictor_recovery, false);
+ std::vector<nsecs_t> const simulatedVsyncs{
+ 158929578733000,
+ 158929306806205, // oldest TS in ringbuffer
+ 158929650879052, 158929661969209, 158929684198847, 158929695268171, 158929706370359,
+ };
+ auto const idealPeriod = 11111111;
auto const expectedPeriod = 11113919;
auto const expectedIntercept = -1195945;
@@ -421,9 +496,9 @@
EXPECT_THAT(slope, IsCloseTo(expectedPeriod, mMaxRoundingError));
EXPECT_THAT(intercept, IsCloseTo(expectedIntercept, mMaxRoundingError));
- // (timePoint - oldestTS) % expectedPeriod works out to be: 395334
- // (timePoint - oldestTS) / expectedPeriod works out to be: 38.96
- // so failure to account for the offset will floor the ordinal to 38, which was in the past.
+ // (timePoint - oldestTS) % expectedPeriod works out to be: 10702663
+ // (timePoint - oldestTS) / expectedPeriod works out to be: 37.96
+ // so failure to account for the offset will floor the ordinal to 37, which was in the past.
auto const timePoint = 158929728723871;
auto const prediction = tracker.nextAnticipatedVSyncTimeFrom(timePoint);
EXPECT_THAT(prediction, Ge(timePoint));
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index 615cc94..7319f1e 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -20,6 +20,7 @@
#include "DisplayHardware/ComposerHal.h"
#include "DisplayHardware/HWC2.h"
+#include "DisplayHardware/Hal.h"
namespace android {
@@ -34,9 +35,9 @@
using android::hardware::graphics::common::V1_2::Dataspace;
using android::hardware::graphics::common::V1_2::PixelFormat;
+using android::hardware::graphics::composer::hal::Error;
using android::hardware::graphics::composer::V2_1::Config;
using android::hardware::graphics::composer::V2_1::Display;
-using android::hardware::graphics::composer::V2_1::Error;
using android::hardware::graphics::composer::V2_1::IComposer;
using android::hardware::graphics::composer::V2_1::Layer;
using android::hardware::graphics::composer::V2_4::IComposerCallback;
@@ -142,8 +143,8 @@
V2_4::Error(Display, Config, std::vector<VsyncPeriodNanos>*));
MOCK_METHOD2(getDisplayVsyncPeriod, V2_4::Error(Display, VsyncPeriodNanos*));
MOCK_METHOD4(setActiveConfigWithConstraints,
- V2_4::Error(Display, Config, const IComposerClient::VsyncPeriodChangeConstraints&,
- VsyncPeriodChangeTimeline*));
+ Error(Display, Config, const IComposerClient::VsyncPeriodChangeConstraints&,
+ VsyncPeriodChangeTimeline*));
MOCK_METHOD2(setAutoLowLatencyMode, V2_4::Error(Display, bool));
MOCK_METHOD2(setBootDisplayConfig, Error(Display, Config));
MOCK_METHOD1(clearBootDisplayConfig, Error(Display));
@@ -185,7 +186,15 @@
(Display, std::vector<Layer>*,
std::vector<aidl::android::hardware::graphics::composer3::DisplayLuts::LayerLut>*));
MOCK_METHOD(Error, setLayerLuts,
- (Display, Layer, std::vector<aidl::android::hardware::graphics::composer3::Lut>&));
+ (Display, Layer, aidl::android::hardware::graphics::composer3::Luts&));
+ MOCK_METHOD(Error, getMaxLayerPictureProfiles, (Display, int32_t*));
+ MOCK_METHOD(Error, setDisplayPictureProfileId, (Display, PictureProfileId id));
+ MOCK_METHOD(Error, setLayerPictureProfileId, (Display, Layer, PictureProfileId id));
+ MOCK_METHOD(Error, getLuts,
+ (Display, const std::vector<sp<GraphicBuffer>>&,
+ std::vector<aidl::android::hardware::graphics::composer3::Luts>*));
+ MOCK_METHOD4(getLayerPresentFences,
+ Error(Display, std::vector<Layer>*, std::vector<int>*, std::vector<int64_t>*));
};
} // namespace Hwc2::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
index 53ed2e1..4ca6fe0 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
@@ -17,6 +17,7 @@
#pragma once
#include <gmock/gmock.h>
+#include <cstdint>
#include "DisplayHardware/HWC2.h"
@@ -52,7 +53,7 @@
(override));
MOCK_METHOD(hal::Error, getName, (std::string *), (const, override));
MOCK_METHOD(hal::Error, getRequests,
- (hal::DisplayRequest *, (std::unordered_map<Layer *, hal::LayerRequest> *)),
+ (hal::DisplayRequest*, (std::unordered_map<Layer*, hal::LayerRequest>*)),
(override));
MOCK_METHOD((ftl::Expected<ui::DisplayConnectionType, hal::Error>), getConnectionType, (),
(const, override));
@@ -85,8 +86,8 @@
MOCK_METHOD(ftl::Future<hal::Error>, setDisplayBrightness,
(float, float, const Hwc2::Composer::DisplayBrightnessOptions &), (override));
MOCK_METHOD(hal::Error, setActiveConfigWithConstraints,
- (hal::HWConfigId, const hal::VsyncPeriodChangeConstraints &,
- hal::VsyncPeriodChangeTimeline *),
+ (hal::HWConfigId, const hal::VsyncPeriodChangeConstraints&,
+ hal::VsyncPeriodChangeTimeline*),
(override));
MOCK_METHOD(hal::Error, setBootDisplayConfig, (hal::HWConfigId), (override));
MOCK_METHOD(hal::Error, clearBootDisplayConfig, (), (override));
@@ -111,7 +112,13 @@
(aidl::android::hardware::graphics::composer3::OverlayProperties *),
(const override));
MOCK_METHOD(hal::Error, getRequestedLuts,
- ((HWC2::Display::LayerLuts*), (HWC2::Display::LutFileDescriptorMapper&)),
+ (HWC2::Display::LayerLuts*, HWC2::Display::LutFileDescriptorMapper&), (override));
+ MOCK_METHOD(hal::Error, getMaxLayerPictureProfiles, (int32_t*), (override));
+ MOCK_METHOD(hal::Error, setPictureProfileHandle, (const android::PictureProfileHandle&),
+ (override));
+ MOCK_METHOD(hal::Error, getLuts,
+ (const std::vector<android::sp<android::GraphicBuffer>>&,
+ std::vector<aidl::android::hardware::graphics::composer3::Luts>*),
(override));
};
@@ -126,6 +133,8 @@
(uint32_t, const android::sp<android::GraphicBuffer> &,
const android::sp<android::Fence> &),
(override));
+ MOCK_METHOD(hal::Error, setBufferSlotsToClear,
+ (const std::vector<uint32_t>& slotsToClear, uint32_t activeBufferSlot), (override));
MOCK_METHOD(hal::Error, setSurfaceDamage, (const android::Region &), (override));
MOCK_METHOD(hal::Error, setBlendMode, (hal::BlendMode), (override));
MOCK_METHOD(hal::Error, setColor, (aidl::android::hardware::graphics::composer3::Color),
@@ -147,8 +156,10 @@
(const std::string &, bool, const std::vector<uint8_t> &), (override));
MOCK_METHOD(hal::Error, setBrightness, (float), (override));
MOCK_METHOD(hal::Error, setBlockingRegion, (const android::Region &), (override));
- MOCK_METHOD(hal::Error, setLuts,
- (std::vector<aidl::android::hardware::graphics::composer3::Lut>&), (override));
+ MOCK_METHOD(hal::Error, setLuts, (aidl::android::hardware::graphics::composer3::Luts&),
+ (override));
+ MOCK_METHOD(hal::Error, setPictureProfileHandle, (const android::PictureProfileHandle&),
+ (override));
};
} // namespace android::HWC2::mock
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.cpp b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWComposer.cpp
similarity index 81%
rename from services/surfaceflinger/CompositionEngine/tests/MockHWComposer.cpp
rename to services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWComposer.cpp
index ae52670..f310633 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.cpp
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWComposer.cpp
@@ -16,17 +16,11 @@
#include "MockHWComposer.h"
-namespace android {
-
-// This will go away once HWComposer is moved into the "backend" library
-HWComposer::~HWComposer() = default;
-
-namespace mock {
+namespace android::mock {
// The Google Mock documentation recommends explicit non-header instantiations
// for better compile time performance.
HWComposer::HWComposer() = default;
HWComposer::~HWComposer() = default;
-} // namespace mock
-} // namespace android
+} // namespace android::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWComposer.h
new file mode 100644
index 0000000..01d078b
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWComposer.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2024 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 <gmock/gmock.h>
+
+#include "DisplayHardware/HWComposer.h"
+
+namespace android::mock {
+
+class HWComposer : public android::HWComposer {
+public:
+ using HWDisplayId = android::hardware::graphics::composer::hal::HWDisplayId;
+ using PowerMode = android::hardware::graphics::composer::hal::PowerMode;
+
+ HWComposer();
+ ~HWComposer() override;
+
+ MOCK_METHOD(void, setCallback, (HWC2::ComposerCallback&), (override));
+ MOCK_METHOD(bool, getDisplayIdentificationData,
+ (HWDisplayId, uint8_t*, DisplayIdentificationData*), (const, override));
+ MOCK_METHOD(bool, hasCapability, (aidl::android::hardware::graphics::composer3::Capability),
+ (const, override));
+ MOCK_METHOD(bool, hasDisplayCapability,
+ (HalDisplayId, aidl::android::hardware::graphics::composer3::DisplayCapability),
+ (const, override));
+
+ MOCK_METHOD(size_t, getMaxVirtualDisplayCount, (), (const, override));
+ MOCK_METHOD(size_t, getMaxVirtualDisplayDimension, (), (const, override));
+ MOCK_METHOD(bool, allocateVirtualDisplay, (HalVirtualDisplayId, ui::Size, ui::PixelFormat*),
+ (override));
+ MOCK_METHOD(void, allocatePhysicalDisplay,
+ (hal::HWDisplayId, PhysicalDisplayId, uint8_t port, std::optional<ui::Size>),
+ (override));
+
+ MOCK_METHOD(std::shared_ptr<HWC2::Layer>, createLayer, (HalDisplayId), (override));
+ MOCK_METHOD(status_t, getDeviceCompositionChanges,
+ (HalDisplayId, bool, std::optional<std::chrono::steady_clock::time_point>, nsecs_t,
+ Fps, std::optional<android::HWComposer::DeviceRequestedChanges>*));
+ MOCK_METHOD(status_t, setClientTarget,
+ (HalDisplayId, uint32_t, const sp<Fence>&, const sp<GraphicBuffer>&, ui::Dataspace,
+ float),
+ (override));
+ MOCK_METHOD(status_t, presentAndGetReleaseFences,
+ (HalDisplayId, std::optional<std::chrono::steady_clock::time_point>), (override));
+ MOCK_METHOD(status_t, executeCommands, (HalDisplayId));
+ MOCK_METHOD(status_t, setPowerMode, (PhysicalDisplayId, PowerMode), (override));
+ MOCK_METHOD(status_t, setColorTransform, (HalDisplayId, const mat4&), (override));
+ MOCK_METHOD(void, disconnectDisplay, (HalDisplayId), (override));
+ MOCK_METHOD(sp<Fence>, getPresentFence, (HalDisplayId), (const, override));
+ MOCK_METHOD(nsecs_t, getPresentTimestamp, (PhysicalDisplayId), (const, override));
+ MOCK_METHOD(sp<Fence>, getLayerReleaseFence, (HalDisplayId, HWC2::Layer*), (const, override));
+ MOCK_METHOD(status_t, setOutputBuffer,
+ (HalVirtualDisplayId, const sp<Fence>&, const sp<GraphicBuffer>&), (override));
+ MOCK_METHOD(void, clearReleaseFences, (HalDisplayId), (override));
+ MOCK_METHOD(status_t, getHdrCapabilities, (HalDisplayId, HdrCapabilities*), (override));
+ MOCK_METHOD(int32_t, getSupportedPerFrameMetadata, (HalDisplayId), (const, override));
+ MOCK_METHOD(std::vector<ui::RenderIntent>, getRenderIntents, (HalDisplayId, ui::ColorMode),
+ (const, override));
+ MOCK_METHOD(mat4, getDataspaceSaturationMatrix, (HalDisplayId, ui::Dataspace), (override));
+ MOCK_METHOD(status_t, getDisplayedContentSamplingAttributes,
+ (HalDisplayId, ui::PixelFormat*, ui::Dataspace*, uint8_t*), (override));
+ MOCK_METHOD(status_t, setDisplayContentSamplingEnabled, (HalDisplayId, bool, uint8_t, uint64_t),
+ (override));
+ MOCK_METHOD(status_t, getDisplayedContentSample,
+ (HalDisplayId, uint64_t, uint64_t, DisplayedFrameStats*), (override));
+ MOCK_METHOD(ftl::Future<status_t>, setDisplayBrightness,
+ (PhysicalDisplayId, float, float, const Hwc2::Composer::DisplayBrightnessOptions&),
+ (override));
+ MOCK_METHOD(std::optional<DisplayIdentificationInfo>, onHotplug,
+ (hal::HWDisplayId, HWComposer::HotplugEvent), (override));
+ MOCK_METHOD(bool, updatesDeviceProductInfoOnHotplugReconnect, (), (const, override));
+ MOCK_METHOD(std::optional<PhysicalDisplayId>, onVsync, (hal::HWDisplayId, int64_t));
+ MOCK_METHOD(void, setVsyncEnabled, (PhysicalDisplayId, hal::Vsync), (override));
+ MOCK_METHOD(bool, isConnected, (PhysicalDisplayId), (const, override));
+ MOCK_METHOD(std::vector<HWComposer::HWCDisplayMode>, getModes, (PhysicalDisplayId, int32_t),
+ (const, override));
+ MOCK_METHOD((ftl::Expected<hal::HWConfigId, status_t>), getActiveMode, (PhysicalDisplayId),
+ (const, override));
+ MOCK_METHOD(std::vector<ui::ColorMode>, getColorModes, (PhysicalDisplayId), (const, override));
+ MOCK_METHOD(status_t, setActiveColorMode, (PhysicalDisplayId, ui::ColorMode, ui::RenderIntent),
+ (override));
+ MOCK_METHOD(ui::DisplayConnectionType, getDisplayConnectionType, (PhysicalDisplayId),
+ (const, override));
+ MOCK_METHOD(bool, isVsyncPeriodSwitchSupported, (PhysicalDisplayId), (const, override));
+ MOCK_METHOD((ftl::Expected<nsecs_t, status_t>), getDisplayVsyncPeriod, (PhysicalDisplayId),
+ (const, override));
+ MOCK_METHOD(status_t, setActiveModeWithConstraints,
+ (PhysicalDisplayId, hal::HWConfigId, const hal::VsyncPeriodChangeConstraints&,
+ hal::VsyncPeriodChangeTimeline*),
+ (override));
+ MOCK_METHOD(status_t, setBootDisplayMode, (PhysicalDisplayId, hal::HWConfigId), (override));
+ MOCK_METHOD(status_t, clearBootDisplayMode, (PhysicalDisplayId), (override));
+ MOCK_METHOD(std::optional<hal::HWConfigId>, getPreferredBootDisplayMode, (PhysicalDisplayId),
+ (override));
+
+ MOCK_METHOD(std::vector<aidl::android::hardware::graphics::common::HdrConversionCapability>,
+ getHdrConversionCapabilities, (), (const, override));
+ MOCK_METHOD(status_t, setHdrConversionStrategy,
+ (aidl::android::hardware::graphics::common::HdrConversionStrategy,
+ aidl::android::hardware::graphics::common::Hdr*),
+ (override));
+ MOCK_METHOD(status_t, setAutoLowLatencyMode, (PhysicalDisplayId, bool), (override));
+ MOCK_METHOD(status_t, getSupportedContentTypes,
+ (PhysicalDisplayId, std::vector<hal::ContentType>*), (const, override));
+ MOCK_METHOD(status_t, setContentType, (PhysicalDisplayId, hal::ContentType)), (override);
+ MOCK_METHOD((const std::unordered_map<std::string, bool>&), getSupportedLayerGenericMetadata,
+ (), (const, override));
+ MOCK_METHOD(void, dump, (std::string&), (const, override));
+ MOCK_METHOD(void, dumpOverlayProperties, (std::string&), (const, override));
+ MOCK_METHOD(android::Hwc2::Composer*, getComposer, (), (const, override));
+
+ MOCK_METHOD(hal::HWDisplayId, getPrimaryHwcDisplayId, (), (const, override));
+ MOCK_METHOD(PhysicalDisplayId, getPrimaryDisplayId, (), (const, override));
+ MOCK_METHOD(bool, isHeadless, (), (const, override));
+
+ MOCK_METHOD(std::optional<PhysicalDisplayId>, toPhysicalDisplayId, (hal::HWDisplayId),
+ (const, override));
+ MOCK_METHOD(std::optional<hal::HWDisplayId>, fromPhysicalDisplayId, (PhysicalDisplayId),
+ (const, override));
+ MOCK_METHOD(status_t, getDisplayDecorationSupport,
+ (PhysicalDisplayId,
+ std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
+ support),
+ (override));
+ MOCK_METHOD(status_t, setIdleTimerEnabled, (PhysicalDisplayId, std::chrono::milliseconds),
+ (override));
+ MOCK_METHOD(bool, hasDisplayIdleTimerCapability, (PhysicalDisplayId), (const, override));
+ MOCK_METHOD(Hwc2::AidlTransform, getPhysicalDisplayOrientation, (PhysicalDisplayId),
+ (const, override));
+ MOCK_METHOD(bool, getValidateSkipped, (HalDisplayId), (const, override));
+ MOCK_METHOD(const aidl::android::hardware::graphics::composer3::OverlayProperties&,
+ getOverlaySupport, (), (const, override));
+ MOCK_METHOD(status_t, setRefreshRateChangedCallbackDebugEnabled, (PhysicalDisplayId, bool));
+ MOCK_METHOD(status_t, notifyExpectedPresent, (PhysicalDisplayId, TimePoint, Fps));
+ MOCK_METHOD(HWC2::Display::LutFileDescriptorMapper&, getLutFileDescriptorMapper, (),
+ (override));
+ MOCK_METHOD(int32_t, getMaxLayerPictureProfiles, (PhysicalDisplayId));
+ MOCK_METHOD(status_t, setDisplayPictureProfileHandle,
+ (PhysicalDisplayId, const PictureProfileHandle&));
+ MOCK_METHOD(status_t, getLuts,
+ (PhysicalDisplayId, const std::vector<sp<GraphicBuffer>>&,
+ std::vector<aidl::android::hardware::graphics::composer3::Luts>*));
+};
+
+} // namespace android::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPower.cpp b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPower.cpp
deleted file mode 100644
index 2323ebb..0000000
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPower.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2022 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 "mock/DisplayHardware/MockIPower.h"
-
-namespace android::Hwc2::mock {
-
-// Explicit default instantiation is recommended.
-MockIPower::MockIPower() = default;
-
-} // namespace android::Hwc2::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPower.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPower.h
deleted file mode 100644
index ed1405b..0000000
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPower.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2022 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 "binder/Status.h"
-
-// FMQ library in IPower does questionable conversions
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-#include <aidl/android/hardware/power/IPower.h>
-#pragma clang diagnostic pop
-
-#include <gmock/gmock.h>
-
-using aidl::android::hardware::power::Boost;
-using aidl::android::hardware::power::ChannelConfig;
-using aidl::android::hardware::power::IPower;
-using aidl::android::hardware::power::IPowerHintSession;
-using aidl::android::hardware::power::SessionConfig;
-using aidl::android::hardware::power::SessionTag;
-
-using aidl::android::hardware::power::Mode;
-using android::binder::Status;
-
-namespace android::Hwc2::mock {
-
-class MockIPower : public IPower {
-public:
- MockIPower();
-
- MOCK_METHOD(ndk::ScopedAStatus, isBoostSupported, (Boost boost, bool* ret), (override));
- MOCK_METHOD(ndk::ScopedAStatus, setBoost, (Boost boost, int32_t durationMs), (override));
- MOCK_METHOD(ndk::ScopedAStatus, isModeSupported, (Mode mode, bool* ret), (override));
- MOCK_METHOD(ndk::ScopedAStatus, setMode, (Mode mode, bool enabled), (override));
- MOCK_METHOD(ndk::ScopedAStatus, createHintSession,
- (int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds,
- int64_t durationNanos, std::shared_ptr<IPowerHintSession>* session),
- (override));
- MOCK_METHOD(ndk::ScopedAStatus, getHintSessionPreferredRate, (int64_t * rate), (override));
- MOCK_METHOD(ndk::ScopedAStatus, createHintSessionWithConfig,
- (int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds,
- int64_t durationNanos, SessionTag tag, SessionConfig* config,
- std::shared_ptr<IPowerHintSession>* _aidl_return),
- (override));
- MOCK_METHOD(ndk::ScopedAStatus, getSessionChannel,
- (int32_t tgid, int32_t uid, ChannelConfig* _aidl_return), (override));
- MOCK_METHOD(ndk::ScopedAStatus, closeSessionChannel, (int32_t tgid, int32_t uid), (override));
- MOCK_METHOD(ndk::ScopedAStatus, getInterfaceVersion, (int32_t * version), (override));
- MOCK_METHOD(ndk::ScopedAStatus, getInterfaceHash, (std::string * hash), (override));
- MOCK_METHOD(ndk::SpAIBinder, asBinder, (), (override));
- MOCK_METHOD(bool, isRemote, (), (override));
-};
-
-} // namespace android::Hwc2::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index 7398cbe..3036fec 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -30,9 +30,12 @@
MOCK_METHOD(sp<EventThreadConnection>, createEventConnection, (EventRegistrationFlags),
(const, override));
MOCK_METHOD(void, enableSyntheticVsync, (bool), (override));
+ MOCK_METHOD(void, omitVsyncDispatching, (bool), (override));
MOCK_METHOD(void, onHotplugReceived, (PhysicalDisplayId, bool), (override));
MOCK_METHOD(void, onHotplugConnectionError, (int32_t), (override));
MOCK_METHOD(void, onModeChanged, (const scheduler::FrameRateMode&), (override));
+ MOCK_METHOD(void, onModeRejected, (PhysicalDisplayId displayId, DisplayModeId modeId),
+ (override));
MOCK_METHOD(void, onFrameRateOverridesChanged,
(PhysicalDisplayId, std::vector<FrameRateOverride>), (override));
MOCK_METHOD(void, dump, (std::string&), (const, override));
@@ -52,6 +55,7 @@
MOCK_METHOD(void, onHdcpLevelsChanged,
(PhysicalDisplayId displayId, int32_t connectedLevel, int32_t maxLevel),
(override));
+ MOCK_METHOD(void, addBufferStuffedUids, (BufferStuffingMap), (override));
};
} // namespace android::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/MockLayer.h b/services/surfaceflinger/tests/unittests/mock/MockLayer.h
index 45f86fa..59f0966 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockLayer.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockLayer.h
@@ -19,6 +19,8 @@
#include <gmock/gmock.h>
#include <optional>
+#include "Layer.h"
+
namespace android::mock {
class MockLayer : public Layer {
@@ -26,8 +28,11 @@
MockLayer(SurfaceFlinger* flinger, std::string name)
: Layer(LayerCreationArgs(flinger, nullptr, std::move(name), 0, {})) {}
- MockLayer(SurfaceFlinger* flinger, std::string name, std::optional<uint32_t> uid)
- : Layer(LayerCreationArgs(flinger, nullptr, std::move(name), 0, {}, uid)) {}
+ MockLayer(SurfaceFlinger* flinger, std::string name, std::optional<uint32_t> id)
+ : Layer(LayerCreationArgs(flinger, nullptr, std::move(name), 0, {}, id)) {}
+
+ MockLayer(SurfaceFlinger* flinger, std::optional<uint32_t> id)
+ : Layer(LayerCreationArgs(flinger, nullptr, "TestLayer", 0, {}, id)) {}
explicit MockLayer(SurfaceFlinger* flinger) : MockLayer(flinger, "TestLayer") {}
diff --git a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
index d45cc66..25dd68e 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
@@ -29,7 +29,7 @@
MOCK_METHOD(void, onChoreographerAttached, (), (override));
MOCK_METHOD(void, onExpectedPresentTimePosted, (TimePoint, ftl::NonNull<DisplayModePtr>, Fps),
(override));
- MOCK_METHOD(void, onCommitNotComposited, (PhysicalDisplayId), (override));
+ MOCK_METHOD(void, onCommitNotComposited, (), (override));
MOCK_METHOD(void, vrrDisplayIdle, (bool), (override));
};
@@ -39,7 +39,7 @@
void kernelTimerChanged(bool) override {}
void onChoreographerAttached() override {}
void onExpectedPresentTimePosted(TimePoint, ftl::NonNull<DisplayModePtr>, Fps) override {}
- void onCommitNotComposited(PhysicalDisplayId) override {}
+ void onCommitNotComposited() override {}
void vrrDisplayIdle(bool) override {}
};
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.cpp b/services/surfaceflinger/tests/unittests/mock/PowerAdvisor/MockPowerAdvisor.cpp
similarity index 91%
rename from services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.cpp
rename to services/surfaceflinger/tests/unittests/mock/PowerAdvisor/MockPowerAdvisor.cpp
index 1ba38a8..f4c1e52 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.cpp
+++ b/services/surfaceflinger/tests/unittests/mock/PowerAdvisor/MockPowerAdvisor.cpp
@@ -16,10 +16,10 @@
#include "MockPowerAdvisor.h"
-namespace android::Hwc2::mock {
+namespace android::adpf::mock {
// Explicit default instantiation is recommended.
PowerAdvisor::PowerAdvisor() = default;
PowerAdvisor::~PowerAdvisor() = default;
-} // namespace android::Hwc2::mock
+} // namespace android::adpf::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h b/services/surfaceflinger/tests/unittests/mock/PowerAdvisor/MockPowerAdvisor.h
similarity index 82%
rename from services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
rename to services/surfaceflinger/tests/unittests/mock/PowerAdvisor/MockPowerAdvisor.h
index 4efdfe8..5abee16 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
+++ b/services/surfaceflinger/tests/unittests/mock/PowerAdvisor/MockPowerAdvisor.h
@@ -18,11 +18,11 @@
#include <gmock/gmock.h>
-#include "DisplayHardware/PowerAdvisor.h"
+#include "PowerAdvisor/PowerAdvisor.h"
-namespace android::Hwc2::mock {
+namespace android::adpf::mock {
-class PowerAdvisor : public android::Hwc2::PowerAdvisor {
+class PowerAdvisor : public android::adpf::PowerAdvisor {
public:
PowerAdvisor();
~PowerAdvisor() override;
@@ -63,6 +63,12 @@
MOCK_METHOD(void, setCompositeEnd, (TimePoint compositeEndTime), (override));
MOCK_METHOD(void, setDisplays, (std::vector<DisplayId> & displayIds), (override));
MOCK_METHOD(void, setTotalFrameTargetWorkDuration, (Duration targetDuration), (override));
+ MOCK_METHOD(std::shared_ptr<SessionManager>, getSessionManager, (), (override));
+ MOCK_METHOD(sp<IBinder>, getOrCreateSessionManagerForBinder, (uid_t uid), (override));
+ MOCK_METHOD(void, setQueuedWorkload, (ftl::Flags<Workload> workload), (override));
+ MOCK_METHOD(void, setScreenshotWorkload, (), (override));
+ MOCK_METHOD(void, setCommittedWorkload, (ftl::Flags<Workload> workload), (override));
+ MOCK_METHOD(void, setCompositedWorkload, (ftl::Flags<Workload> workload), (override));
};
-} // namespace android::Hwc2::mock
+} // namespace android::adpf::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHalController.cpp b/services/surfaceflinger/tests/unittests/mock/PowerAdvisor/MockPowerHalController.cpp
similarity index 91%
rename from services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHalController.cpp
rename to services/surfaceflinger/tests/unittests/mock/PowerAdvisor/MockPowerHalController.cpp
index 3ec5c2d..3b8de55 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHalController.cpp
+++ b/services/surfaceflinger/tests/unittests/mock/PowerAdvisor/MockPowerHalController.cpp
@@ -16,9 +16,9 @@
#include "MockPowerHalController.h"
-namespace android::Hwc2::mock {
+namespace android::adpf::mock {
MockPowerHalController::MockPowerHalController() = default;
MockPowerHalController::~MockPowerHalController() = default;
-} // namespace android::Hwc2::mock
+} // namespace android::adpf::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHalController.h b/services/surfaceflinger/tests/unittests/mock/PowerAdvisor/MockPowerHalController.h
similarity index 92%
rename from services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHalController.h
rename to services/surfaceflinger/tests/unittests/mock/PowerAdvisor/MockPowerHalController.h
index af1862d..891f507 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHalController.h
+++ b/services/surfaceflinger/tests/unittests/mock/PowerAdvisor/MockPowerHalController.h
@@ -19,10 +19,7 @@
#include <gmock/gmock.h>
#include <scheduler/Time.h>
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
#include <powermanager/PowerHalController.h>
-#pragma clang diagnostic pop
namespace android {
namespace hardware {
@@ -32,7 +29,7 @@
} // namespace hardware
} // namespace android
-namespace android::Hwc2::mock {
+namespace android::adpf::mock {
using android::power::HalResult;
@@ -57,6 +54,8 @@
MOCK_METHOD(HalResult<aidl::android::hardware::power::ChannelConfig>, getSessionChannel,
(int tgid, int uid), (override));
MOCK_METHOD(HalResult<void>, closeSessionChannel, (int tgid, int uid), (override));
+ MOCK_METHOD(HalResult<aidl::android::hardware::power::SupportInfo>, getSupportInfo, (),
+ (override));
};
-} // namespace android::Hwc2::mock
\ No newline at end of file
+} // namespace android::adpf::mock
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp b/services/surfaceflinger/tests/unittests/mock/PowerAdvisor/MockPowerHintSessionWrapper.cpp
similarity index 85%
rename from services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp
rename to services/surfaceflinger/tests/unittests/mock/PowerAdvisor/MockPowerHintSessionWrapper.cpp
index d383283..cb39783 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.cpp
+++ b/services/surfaceflinger/tests/unittests/mock/PowerAdvisor/MockPowerHintSessionWrapper.cpp
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-#include "mock/DisplayHardware/MockPowerHintSessionWrapper.h"
+#include "MockPowerHintSessionWrapper.h"
-namespace android::Hwc2::mock {
+namespace android::adpf::mock {
// Explicit default instantiation is recommended.
MockPowerHintSessionWrapper::MockPowerHintSessionWrapper()
: power::PowerHintSessionWrapper(nullptr) {}
-} // namespace android::Hwc2::mock
+} // namespace android::adpf::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.h b/services/surfaceflinger/tests/unittests/mock/PowerAdvisor/MockPowerHintSessionWrapper.h
similarity index 88%
rename from services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.h
rename to services/surfaceflinger/tests/unittests/mock/PowerAdvisor/MockPowerHintSessionWrapper.h
index bc6950c..4518de8 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerHintSessionWrapper.h
+++ b/services/surfaceflinger/tests/unittests/mock/PowerAdvisor/MockPowerHintSessionWrapper.h
@@ -16,13 +16,7 @@
#pragma once
-#include "binder/Status.h"
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-#include <aidl/android/hardware/power/IPower.h>
#include <powermanager/PowerHintSessionWrapper.h>
-#pragma clang diagnostic pop
#include <gmock/gmock.h>
@@ -34,7 +28,7 @@
using namespace aidl::android::hardware::power;
-namespace android::Hwc2::mock {
+namespace android::adpf::mock {
class MockPowerHintSessionWrapper : public power::PowerHintSessionWrapper {
public:
@@ -52,4 +46,4 @@
MOCK_METHOD(power::HalResult<SessionConfig>, getSessionConfig, (), (override));
};
-} // namespace android::Hwc2::mock
+} // namespace android::adpf::mock
diff --git a/services/surfaceflinger/tests/vsync/vsync.cpp b/services/surfaceflinger/tests/vsync/vsync.cpp
index 8b4a6be..77a68d9 100644
--- a/services/surfaceflinger/tests/vsync/vsync.cpp
+++ b/services/surfaceflinger/tests/vsync/vsync.cpp
@@ -41,7 +41,7 @@
while ((n = q->getEvents(buffer, 1)) > 0) {
for (int i=0 ; i<n ; i++) {
- if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
+ if (buffer[i].header.type == DisplayEventType::DISPLAY_EVENT_VSYNC) {
printf("event vsync: count=%d\t", buffer[i].vsync.count);
}
if (oldTimeStamp) {
diff --git a/services/vibratorservice/VibratorHalWrapper.cpp b/services/vibratorservice/VibratorHalWrapper.cpp
index b06ee3b..536a6b3 100644
--- a/services/vibratorservice/VibratorHalWrapper.cpp
+++ b/services/vibratorservice/VibratorHalWrapper.cpp
@@ -29,11 +29,11 @@
using aidl::android::hardware::vibrator::Braking;
using aidl::android::hardware::vibrator::CompositeEffect;
using aidl::android::hardware::vibrator::CompositePrimitive;
+using aidl::android::hardware::vibrator::CompositePwleV2;
using aidl::android::hardware::vibrator::Effect;
using aidl::android::hardware::vibrator::EffectStrength;
+using aidl::android::hardware::vibrator::FrequencyAccelerationMapEntry;
using aidl::android::hardware::vibrator::PrimitivePwle;
-using aidl::android::hardware::vibrator::PwleV2OutputMapEntry;
-using aidl::android::hardware::vibrator::PwleV2Primitive;
using aidl::android::hardware::vibrator::VendorEffect;
using std::chrono::milliseconds;
@@ -131,10 +131,10 @@
return HalResult<void>::unsupported();
}
-HalResult<void> HalWrapper::composePwleV2(const std::vector<PwleV2Primitive>&,
- const std::function<void()>&) {
+HalResult<milliseconds> HalWrapper::composePwleV2(const CompositePwleV2&,
+ const std::function<void()>&) {
ALOGV("Skipped composePwleV2 because it's not available in Vibrator HAL");
- return HalResult<void>::unsupported();
+ return HalResult<milliseconds>::unsupported();
}
HalResult<Capabilities> HalWrapper::getCapabilities() {
@@ -243,11 +243,11 @@
return HalResult<milliseconds>::unsupported();
}
-HalResult<std::vector<PwleV2OutputMapEntry>>
+HalResult<std::vector<FrequencyAccelerationMapEntry>>
HalWrapper::getFrequencyToOutputAccelerationMapInternal() {
ALOGV("Skipped getFrequencyToOutputAccelerationMapInternal because it's not "
"available in Vibrator HAL");
- return HalResult<std::vector<PwleV2OutputMapEntry>>::unsupported();
+ return HalResult<std::vector<FrequencyAccelerationMapEntry>>::unsupported();
}
// -------------------------------------------------------------------------------------------------
@@ -360,11 +360,18 @@
return HalResultFactory::fromStatus(getHal()->composePwle(primitives, cb));
}
-HalResult<void> AidlHalWrapper::composePwleV2(const std::vector<PwleV2Primitive>& composite,
- const std::function<void()>& completionCallback) {
+HalResult<milliseconds> AidlHalWrapper::composePwleV2(
+ const CompositePwleV2& composite, const std::function<void()>& completionCallback) {
// This method should always support callbacks, so no need to double check.
auto cb = ndk::SharedRefBase::make<HalCallbackWrapper>(completionCallback);
- return HalResultFactory::fromStatus(getHal()->composePwleV2(composite, cb));
+
+ milliseconds totalDuration(0);
+ for (const auto& primitive : composite.pwlePrimitives) {
+ totalDuration += milliseconds(primitive.timeMillis);
+ }
+
+ return HalResultFactory::fromStatus<milliseconds>(getHal()->composePwleV2(composite, cb),
+ totalDuration);
}
HalResult<Capabilities> AidlHalWrapper::getCapabilitiesInternal() {
@@ -498,13 +505,13 @@
return HalResultFactory::fromStatus<milliseconds>(std::move(status), milliseconds(durationMs));
}
-HalResult<std::vector<PwleV2OutputMapEntry>>
+HalResult<std::vector<FrequencyAccelerationMapEntry>>
AidlHalWrapper::getFrequencyToOutputAccelerationMapInternal() {
- std::vector<PwleV2OutputMapEntry> frequencyToOutputAccelerationMap;
- auto status =
- getHal()->getPwleV2FrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap);
+ std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap;
+ auto status = getHal()->getFrequencyToOutputAccelerationMap(&frequencyToOutputAccelerationMap);
return HalResultFactory::fromStatus<
- std::vector<PwleV2OutputMapEntry>>(std::move(status), frequencyToOutputAccelerationMap);
+ std::vector<FrequencyAccelerationMapEntry>>(std::move(status),
+ frequencyToOutputAccelerationMap);
}
std::shared_ptr<Aidl::IVibrator> AidlHalWrapper::getHal() {
diff --git a/services/vibratorservice/VibratorManagerHalController.cpp b/services/vibratorservice/VibratorManagerHalController.cpp
index ba35d15..494f88f 100644
--- a/services/vibratorservice/VibratorManagerHalController.cpp
+++ b/services/vibratorservice/VibratorManagerHalController.cpp
@@ -150,6 +150,23 @@
return apply(cancelSyncedFn, "cancelSynced");
}
+HalResult<std::shared_ptr<Aidl::IVibrationSession>> ManagerHalController::startSession(
+ const std::vector<int32_t>& ids, const Aidl::VibrationSessionConfig& config,
+ const std::function<void()>& completionCallback) {
+ hal_fn<std::shared_ptr<Aidl::IVibrationSession>> startSessionFn =
+ [&](std::shared_ptr<ManagerHalWrapper> hal) {
+ return hal->startSession(ids, config, completionCallback);
+ };
+ return apply(startSessionFn, "startSession");
+}
+
+HalResult<void> ManagerHalController::clearSessions() {
+ hal_fn<void> clearSessionsFn = [](std::shared_ptr<ManagerHalWrapper> hal) {
+ return hal->clearSessions();
+ };
+ return apply(clearSessionsFn, "clearSessions");
+}
+
}; // namespace vibrator
}; // namespace android
diff --git a/services/vibratorservice/VibratorManagerHalWrapper.cpp b/services/vibratorservice/VibratorManagerHalWrapper.cpp
index 93ec781..3db8ff8 100644
--- a/services/vibratorservice/VibratorManagerHalWrapper.cpp
+++ b/services/vibratorservice/VibratorManagerHalWrapper.cpp
@@ -29,6 +29,30 @@
constexpr int32_t SINGLE_VIBRATOR_ID = 0;
const constexpr char* MISSING_VIBRATOR_MESSAGE_PREFIX = "No vibrator with id=";
+HalResult<void> ManagerHalWrapper::prepareSynced(const std::vector<int32_t>&) {
+ return HalResult<void>::unsupported();
+}
+
+HalResult<void> ManagerHalWrapper::triggerSynced(const std::function<void()>&) {
+ return HalResult<void>::unsupported();
+}
+
+HalResult<void> ManagerHalWrapper::cancelSynced() {
+ return HalResult<void>::unsupported();
+}
+
+HalResult<std::shared_ptr<Aidl::IVibrationSession>> ManagerHalWrapper::startSession(
+ const std::vector<int32_t>&, const Aidl::VibrationSessionConfig&,
+ const std::function<void()>&) {
+ return HalResult<std::shared_ptr<Aidl::IVibrationSession>>::unsupported();
+}
+
+HalResult<void> ManagerHalWrapper::clearSessions() {
+ return HalResult<void>::unsupported();
+}
+
+// -------------------------------------------------------------------------------------------------
+
HalResult<void> LegacyManagerHalWrapper::ping() {
auto pingFn = [](HalWrapper* hal) { return hal->ping(); };
return mController->doWithRetry<void>(pingFn, "ping");
@@ -59,18 +83,6 @@
(MISSING_VIBRATOR_MESSAGE_PREFIX + std::to_string(id)).c_str());
}
-HalResult<void> LegacyManagerHalWrapper::prepareSynced(const std::vector<int32_t>&) {
- return HalResult<void>::unsupported();
-}
-
-HalResult<void> LegacyManagerHalWrapper::triggerSynced(const std::function<void()>&) {
- return HalResult<void>::unsupported();
-}
-
-HalResult<void> LegacyManagerHalWrapper::cancelSynced() {
- return HalResult<void>::unsupported();
-}
-
// -------------------------------------------------------------------------------------------------
std::shared_ptr<HalWrapper> AidlManagerHalWrapper::connectToVibrator(
@@ -186,6 +198,17 @@
return HalResultFactory::fromStatus(getHal()->triggerSynced(cb));
}
+HalResult<std::shared_ptr<Aidl::IVibrationSession>> AidlManagerHalWrapper::startSession(
+ const std::vector<int32_t>& ids, const Aidl::VibrationSessionConfig& config,
+ const std::function<void()>& completionCallback) {
+ auto cb = ndk::SharedRefBase::make<HalCallbackWrapper>(completionCallback);
+ std::shared_ptr<Aidl::IVibrationSession> session;
+ auto status = getHal()->startSession(ids, config, cb, &session);
+ return HalResultFactory::fromStatus<std::shared_ptr<Aidl::IVibrationSession>>(std::move(status),
+ std::move(
+ session));
+}
+
HalResult<void> AidlManagerHalWrapper::cancelSynced() {
auto ret = HalResultFactory::fromStatus(getHal()->cancelSynced());
if (ret.isOk()) {
@@ -200,6 +223,10 @@
return ret;
}
+HalResult<void> AidlManagerHalWrapper::clearSessions() {
+ return HalResultFactory::fromStatus(getHal()->clearSessions());
+}
+
std::shared_ptr<Aidl::IVibratorManager> AidlManagerHalWrapper::getHal() {
std::lock_guard<std::mutex> lock(mHandleMutex);
return mHandle;
diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
index b2bfffc..9a39ad4 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
@@ -243,7 +243,8 @@
using EffectStrength = aidl::android::hardware::vibrator::EffectStrength;
using CompositePrimitive = aidl::android::hardware::vibrator::CompositePrimitive;
using Braking = aidl::android::hardware::vibrator::Braking;
- using PwleV2OutputMapEntry = aidl::android::hardware::vibrator::PwleV2OutputMapEntry;
+ using FrequencyAccelerationMapEntry =
+ aidl::android::hardware::vibrator::FrequencyAccelerationMapEntry;
const HalResult<Capabilities> capabilities;
const HalResult<std::vector<Effect>> supportedEffects;
@@ -262,7 +263,7 @@
const HalResult<int32_t> maxEnvelopeEffectSize;
const HalResult<std::chrono::milliseconds> minEnvelopeEffectControlPointDuration;
const HalResult<std::chrono::milliseconds> maxEnvelopeEffectControlPointDuration;
- const HalResult<std::vector<PwleV2OutputMapEntry>> frequencyToOutputAccelerationMap;
+ const HalResult<std::vector<FrequencyAccelerationMapEntry>> frequencyToOutputAccelerationMap;
void logFailures() const {
logFailure<Capabilities>(capabilities, "getCapabilities");
@@ -286,8 +287,9 @@
"getMinEnvelopeEffectControlPointDuration");
logFailure<std::chrono::milliseconds>(maxEnvelopeEffectControlPointDuration,
"getMaxEnvelopeEffectControlPointDuration");
- logFailure<std::vector<PwleV2OutputMapEntry>>(frequencyToOutputAccelerationMap,
- "getfrequencyToOutputAccelerationMap");
+ logFailure<
+ std::vector<FrequencyAccelerationMapEntry>>(frequencyToOutputAccelerationMap,
+ "getfrequencyToOutputAccelerationMap");
}
bool shouldRetry() const {
@@ -365,8 +367,8 @@
HalResult<std::chrono::milliseconds>::transactionFailed(MSG);
HalResult<std::chrono::milliseconds> mMaxEnvelopeEffectControlPointDuration =
HalResult<std::chrono::milliseconds>::transactionFailed(MSG);
- HalResult<std::vector<Info::PwleV2OutputMapEntry>> mFrequencyToOutputAccelerationMap =
- HalResult<std::vector<Info::PwleV2OutputMapEntry>>::transactionFailed(MSG);
+ HalResult<std::vector<Info::FrequencyAccelerationMapEntry>> mFrequencyToOutputAccelerationMap =
+ HalResult<std::vector<Info::FrequencyAccelerationMapEntry>>::transactionFailed(MSG);
friend class HalWrapper;
};
@@ -381,8 +383,9 @@
using CompositeEffect = aidl::android::hardware::vibrator::CompositeEffect;
using Braking = aidl::android::hardware::vibrator::Braking;
using PrimitivePwle = aidl::android::hardware::vibrator::PrimitivePwle;
- using PwleV2Primitive = aidl::android::hardware::vibrator::PwleV2Primitive;
- using PwleV2OutputMapEntry = aidl::android::hardware::vibrator::PwleV2OutputMapEntry;
+ using CompositePwleV2 = aidl::android::hardware::vibrator::CompositePwleV2;
+ using FrequencyAccelerationMapEntry =
+ aidl::android::hardware::vibrator::FrequencyAccelerationMapEntry;
explicit HalWrapper(std::shared_ptr<CallbackScheduler> scheduler)
: mCallbackScheduler(std::move(scheduler)) {}
@@ -420,8 +423,8 @@
virtual HalResult<void> performPwleEffect(const std::vector<PrimitivePwle>& primitives,
const std::function<void()>& completionCallback);
- virtual HalResult<void> composePwleV2(const std::vector<PwleV2Primitive>& composite,
- const std::function<void()>& completionCallback);
+ virtual HalResult<std::chrono::milliseconds> composePwleV2(
+ const CompositePwleV2& composite, const std::function<void()>& completionCallback);
protected:
// Shared pointer to allow CallbackScheduler to outlive this wrapper.
@@ -450,7 +453,7 @@
virtual HalResult<int32_t> getMaxEnvelopeEffectSizeInternal();
virtual HalResult<std::chrono::milliseconds> getMinEnvelopeEffectControlPointDurationInternal();
virtual HalResult<std::chrono::milliseconds> getMaxEnvelopeEffectControlPointDurationInternal();
- virtual HalResult<std::vector<PwleV2OutputMapEntry>>
+ virtual HalResult<std::vector<FrequencyAccelerationMapEntry>>
getFrequencyToOutputAccelerationMapInternal();
private:
@@ -508,8 +511,9 @@
const std::vector<PrimitivePwle>& primitives,
const std::function<void()>& completionCallback) override final;
- HalResult<void> composePwleV2(const std::vector<PwleV2Primitive>& composite,
- const std::function<void()>& completionCallback) override final;
+ HalResult<std::chrono::milliseconds> composePwleV2(
+ const CompositePwleV2& composite,
+ const std::function<void()>& completionCallback) override final;
protected:
HalResult<Capabilities> getCapabilitiesInternal() override final;
@@ -532,8 +536,9 @@
override final;
HalResult<std::chrono::milliseconds> getMaxEnvelopeEffectControlPointDurationInternal()
override final;
- HalResult<std::vector<PwleV2OutputMapEntry>> getFrequencyToOutputAccelerationMapInternal()
- override final;
+
+ HalResult<std::vector<FrequencyAccelerationMapEntry>>
+ getFrequencyToOutputAccelerationMapInternal() override final;
private:
const reconnect_fn mReconnectFn;
diff --git a/services/vibratorservice/include/vibratorservice/VibratorManagerHalController.h b/services/vibratorservice/include/vibratorservice/VibratorManagerHalController.h
index 70c846b..72d4752 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorManagerHalController.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorManagerHalController.h
@@ -62,6 +62,10 @@
HalResult<void> prepareSynced(const std::vector<int32_t>& ids) override final;
HalResult<void> triggerSynced(const std::function<void()>& completionCallback) override final;
HalResult<void> cancelSynced() override final;
+ HalResult<std::shared_ptr<IVibrationSession>> startSession(
+ const std::vector<int32_t>& ids, const VibrationSessionConfig& config,
+ const std::function<void()>& completionCallback) override final;
+ HalResult<void> clearSessions() override final;
private:
Connector mConnector;
diff --git a/services/vibratorservice/include/vibratorservice/VibratorManagerHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorManagerHalWrapper.h
index 9e3f221..8d4ca0e 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorManagerHalWrapper.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorManagerHalWrapper.h
@@ -38,7 +38,8 @@
aidl::android::hardware::vibrator::IVibratorManager::CAP_MIXED_TRIGGER_PERFORM,
MIXED_TRIGGER_COMPOSE =
aidl::android::hardware::vibrator::IVibratorManager::CAP_MIXED_TRIGGER_COMPOSE,
- TRIGGER_CALLBACK = aidl::android::hardware::vibrator::IVibratorManager::CAP_TRIGGER_CALLBACK
+ TRIGGER_CALLBACK = aidl::android::hardware::vibrator::IVibratorManager::CAP_TRIGGER_CALLBACK,
+ START_SESSIONS = aidl::android::hardware::vibrator::IVibratorManager::CAP_START_SESSIONS
};
inline ManagerCapabilities operator|(ManagerCapabilities lhs, ManagerCapabilities rhs) {
@@ -64,6 +65,9 @@
// Wrapper for VibratorManager HAL handlers.
class ManagerHalWrapper {
public:
+ using IVibrationSession = aidl::android::hardware::vibrator::IVibrationSession;
+ using VibrationSessionConfig = aidl::android::hardware::vibrator::VibrationSessionConfig;
+
ManagerHalWrapper() = default;
virtual ~ManagerHalWrapper() = default;
@@ -78,9 +82,13 @@
virtual HalResult<std::vector<int32_t>> getVibratorIds() = 0;
virtual HalResult<std::shared_ptr<HalController>> getVibrator(int32_t id) = 0;
- virtual HalResult<void> prepareSynced(const std::vector<int32_t>& ids) = 0;
- virtual HalResult<void> triggerSynced(const std::function<void()>& completionCallback) = 0;
- virtual HalResult<void> cancelSynced() = 0;
+ virtual HalResult<void> prepareSynced(const std::vector<int32_t>& ids);
+ virtual HalResult<void> triggerSynced(const std::function<void()>& completionCallback);
+ virtual HalResult<void> cancelSynced();
+ virtual HalResult<std::shared_ptr<IVibrationSession>> startSession(
+ const std::vector<int32_t>& ids, const VibrationSessionConfig& config,
+ const std::function<void()>& completionCallback);
+ virtual HalResult<void> clearSessions();
};
// Wrapper for the VibratorManager over single Vibrator HAL.
@@ -98,10 +106,6 @@
HalResult<std::vector<int32_t>> getVibratorIds() override final;
HalResult<std::shared_ptr<HalController>> getVibrator(int32_t id) override final;
- HalResult<void> prepareSynced(const std::vector<int32_t>& ids) override final;
- HalResult<void> triggerSynced(const std::function<void()>& completionCallback) override final;
- HalResult<void> cancelSynced() override final;
-
private:
const std::shared_ptr<HalController> mController;
};
@@ -126,6 +130,10 @@
HalResult<void> prepareSynced(const std::vector<int32_t>& ids) override final;
HalResult<void> triggerSynced(const std::function<void()>& completionCallback) override final;
HalResult<void> cancelSynced() override final;
+ HalResult<std::shared_ptr<IVibrationSession>> startSession(
+ const std::vector<int32_t>& ids, const VibrationSessionConfig& config,
+ const std::function<void()>& completionCallback) override final;
+ HalResult<void> clearSessions() override final;
private:
std::mutex mHandleMutex;
diff --git a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
index d42aa56..7545148 100644
--- a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
+++ b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
@@ -34,12 +34,13 @@
using aidl::android::hardware::vibrator::Braking;
using aidl::android::hardware::vibrator::CompositeEffect;
using aidl::android::hardware::vibrator::CompositePrimitive;
+using aidl::android::hardware::vibrator::CompositePwleV2;
using aidl::android::hardware::vibrator::Effect;
using aidl::android::hardware::vibrator::EffectStrength;
+using aidl::android::hardware::vibrator::FrequencyAccelerationMapEntry;
using aidl::android::hardware::vibrator::IVibrator;
using aidl::android::hardware::vibrator::IVibratorCallback;
using aidl::android::hardware::vibrator::PrimitivePwle;
-using aidl::android::hardware::vibrator::PwleV2OutputMapEntry;
using aidl::android::hardware::vibrator::PwleV2Primitive;
using aidl::android::hardware::vibrator::VendorEffect;
using aidl::android::os::PersistableBundle;
@@ -243,11 +244,11 @@
std::vector<CompositePrimitive> supportedPrimitives = {CompositePrimitive::CLICK};
std::vector<Braking> supportedBraking = {Braking::CLAB};
std::vector<float> amplitudes = {0.f, 1.f, 0.f};
- std::vector<PwleV2OutputMapEntry>
- frequencyToOutputAccelerationMap{PwleV2OutputMapEntry(/*frequency=*/30.0f,
- /*maxOutputAcceleration=*/0.2),
- PwleV2OutputMapEntry(/*frequency=*/60.0f,
- /*maxOutputAcceleration=*/0.8)};
+ std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap{
+ FrequencyAccelerationMapEntry(/*frequency=*/30.0f,
+ /*maxOutputAcceleration=*/0.2),
+ FrequencyAccelerationMapEntry(/*frequency=*/60.0f,
+ /*maxOutputAcceleration=*/0.8)};
std::vector<std::chrono::milliseconds> primitiveDurations;
constexpr auto primitiveRange = ndk::enum_range<CompositePrimitive>();
@@ -329,7 +330,7 @@
.WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
.WillOnce(DoAll(SetArgPointee<0>(PWLE_V2_MIN_REQUIRED_PRIMITIVE_MAX_DURATION_MS),
Return(ndk::ScopedAStatus::ok())));
- EXPECT_CALL(*mMockHal.get(), getPwleV2FrequencyToOutputAccelerationMap(_))
+ EXPECT_CALL(*mMockHal.get(), getFrequencyToOutputAccelerationMap(_))
.Times(Exactly(2))
.WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
.WillOnce(DoAll(SetArgPointee<0>(frequencyToOutputAccelerationMap),
@@ -391,11 +392,11 @@
constexpr int32_t PWLE_V2_MAX_ALLOWED_PRIMITIVE_MIN_DURATION_MS = 20;
constexpr int32_t PWLE_V2_MIN_REQUIRED_PRIMITIVE_MAX_DURATION_MS = 1000;
std::vector<Effect> supportedEffects = {Effect::CLICK, Effect::TICK};
- std::vector<PwleV2OutputMapEntry>
- frequencyToOutputAccelerationMap{PwleV2OutputMapEntry(/*frequency=*/30.0f,
- /*maxOutputAcceleration=*/0.2),
- PwleV2OutputMapEntry(/*frequency=*/60.0f,
- /*maxOutputAcceleration=*/0.8)};
+ std::vector<FrequencyAccelerationMapEntry> frequencyToOutputAccelerationMap{
+ FrequencyAccelerationMapEntry(/*frequency=*/30.0f,
+ /*maxOutputAcceleration=*/0.2),
+ FrequencyAccelerationMapEntry(/*frequency=*/60.0f,
+ /*maxOutputAcceleration=*/0.8)};
EXPECT_CALL(*mMockHal.get(), getCapabilities(_))
.Times(Exactly(1))
@@ -451,7 +452,7 @@
.Times(Exactly(1))
.WillOnce(DoAll(SetArgPointee<0>(PWLE_V2_MIN_REQUIRED_PRIMITIVE_MAX_DURATION_MS),
Return(ndk::ScopedAStatus::ok())));
- EXPECT_CALL(*mMockHal.get(), getPwleV2FrequencyToOutputAccelerationMap(_))
+ EXPECT_CALL(*mMockHal.get(), getFrequencyToOutputAccelerationMap(_))
.Times(Exactly(1))
.WillOnce(DoAll(SetArgPointee<0>(frequencyToOutputAccelerationMap),
Return(ndk::ScopedAStatus::ok())));
@@ -754,7 +755,8 @@
}
TEST_F(VibratorHalWrapperAidlTest, TestComposePwleV2) {
- auto pwleEffect = {
+ CompositePwleV2 composite;
+ composite.pwlePrimitives = {
PwleV2Primitive(/*amplitude=*/0.2, /*frequency=*/50, /*time=*/100),
PwleV2Primitive(/*amplitude=*/0.5, /*frequency=*/150, /*time=*/100),
PwleV2Primitive(/*amplitude=*/0.8, /*frequency=*/250, /*time=*/100),
@@ -773,17 +775,18 @@
std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
- auto result = mWrapper->composePwleV2(pwleEffect, callback);
+ auto result = mWrapper->composePwleV2(composite, callback);
ASSERT_TRUE(result.isUnsupported());
// Callback not triggered on failure
ASSERT_EQ(0, *callbackCounter.get());
- result = mWrapper->composePwleV2(pwleEffect, callback);
+ result = mWrapper->composePwleV2(composite, callback);
ASSERT_TRUE(result.isFailed());
// Callback not triggered for unsupported
ASSERT_EQ(0, *callbackCounter.get());
- result = mWrapper->composePwleV2(pwleEffect, callback);
+ result = mWrapper->composePwleV2(composite, callback);
ASSERT_TRUE(result.isOk());
+ ASSERT_EQ(300ms, result.value());
ASSERT_EQ(1, *callbackCounter.get());
}
diff --git a/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp b/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp
index d6dab8d..04dbe4e 100644
--- a/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp
+++ b/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp
@@ -36,6 +36,7 @@
using aidl::android::hardware::vibrator::Braking;
using aidl::android::hardware::vibrator::CompositeEffect;
using aidl::android::hardware::vibrator::CompositePrimitive;
+using aidl::android::hardware::vibrator::CompositePwleV2;
using aidl::android::hardware::vibrator::Effect;
using aidl::android::hardware::vibrator::EffectStrength;
using aidl::android::hardware::vibrator::IVibrator;
@@ -380,7 +381,8 @@
}
TEST_F(VibratorHalWrapperHidlV1_0Test, TestComposePwleV2Unsupported) {
- auto pwleEffect = {
+ CompositePwleV2 composite;
+ composite.pwlePrimitives = {
PwleV2Primitive(/*amplitude=*/0.2, /*frequency=*/50, /*time=*/100),
PwleV2Primitive(/*amplitude=*/0.5, /*frequency=*/150, /*time=*/100),
PwleV2Primitive(/*amplitude=*/0.8, /*frequency=*/250, /*time=*/100),
@@ -389,7 +391,7 @@
std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
- ASSERT_TRUE(mWrapper->composePwleV2(pwleEffect, callback).isUnsupported());
+ ASSERT_TRUE(mWrapper->composePwleV2(composite, callback).isUnsupported());
// No callback is triggered.
ASSERT_EQ(0, *callbackCounter.get());
diff --git a/services/vibratorservice/test/VibratorManagerHalControllerTest.cpp b/services/vibratorservice/test/VibratorManagerHalControllerTest.cpp
index c7214e0..b201670 100644
--- a/services/vibratorservice/test/VibratorManagerHalControllerTest.cpp
+++ b/services/vibratorservice/test/VibratorManagerHalControllerTest.cpp
@@ -27,6 +27,8 @@
#include "test_mocks.h"
#include "test_utils.h"
+using aidl::android::hardware::vibrator::IVibrationSession;
+using aidl::android::hardware::vibrator::VibrationSessionConfig;
using android::vibrator::HalController;
using namespace android;
@@ -34,6 +36,7 @@
static constexpr int MAX_ATTEMPTS = 2;
static const std::vector<int32_t> VIBRATOR_IDS = {1, 2};
+static const VibrationSessionConfig SESSION_CONFIG;
static constexpr int VIBRATOR_ID = 1;
// -------------------------------------------------------------------------------------------------
@@ -52,6 +55,11 @@
MOCK_METHOD(vibrator::HalResult<void>, triggerSynced,
(const std::function<void()>& completionCallback), (override));
MOCK_METHOD(vibrator::HalResult<void>, cancelSynced, (), (override));
+ MOCK_METHOD(vibrator::HalResult<std::shared_ptr<IVibrationSession>>, startSession,
+ (const std::vector<int32_t>& ids, const VibrationSessionConfig& s,
+ const std::function<void()>& completionCallback),
+ (override));
+ MOCK_METHOD(vibrator::HalResult<void>, clearSessions, (), (override));
};
// -------------------------------------------------------------------------------------------------
@@ -79,7 +87,8 @@
void setHalExpectations(int32_t cardinality, vibrator::HalResult<void> voidResult,
vibrator::HalResult<vibrator::ManagerCapabilities> capabilitiesResult,
vibrator::HalResult<std::vector<int32_t>> idsResult,
- vibrator::HalResult<std::shared_ptr<HalController>> vibratorResult) {
+ vibrator::HalResult<std::shared_ptr<HalController>> vibratorResult,
+ vibrator::HalResult<std::shared_ptr<IVibrationSession>> sessionResult) {
EXPECT_CALL(*mMockHal.get(), ping())
.Times(Exactly(cardinality))
.WillRepeatedly(Return(voidResult));
@@ -101,10 +110,16 @@
EXPECT_CALL(*mMockHal.get(), cancelSynced())
.Times(Exactly(cardinality))
.WillRepeatedly(Return(voidResult));
+ EXPECT_CALL(*mMockHal.get(), startSession(_, _, _))
+ .Times(Exactly(cardinality))
+ .WillRepeatedly(Return(sessionResult));
+ EXPECT_CALL(*mMockHal.get(), clearSessions())
+ .Times(Exactly(cardinality))
+ .WillRepeatedly(Return(voidResult));
if (cardinality > 1) {
// One reconnection for each retry.
- EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(7 * (cardinality - 1)));
+ EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(9 * (cardinality - 1)));
} else {
EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(0));
}
@@ -127,7 +142,8 @@
vibrator::HalResult<vibrator::ManagerCapabilities>::ok(
vibrator::ManagerCapabilities::SYNC),
vibrator::HalResult<std::vector<int32_t>>::ok(VIBRATOR_IDS),
- vibrator::HalResult<std::shared_ptr<HalController>>::ok(nullptr));
+ vibrator::HalResult<std::shared_ptr<HalController>>::ok(nullptr),
+ vibrator::HalResult<std::shared_ptr<IVibrationSession>>::ok(nullptr));
ASSERT_TRUE(mController->ping().isOk());
@@ -146,6 +162,8 @@
ASSERT_TRUE(mController->prepareSynced(VIBRATOR_IDS).isOk());
ASSERT_TRUE(mController->triggerSynced([]() {}).isOk());
ASSERT_TRUE(mController->cancelSynced().isOk());
+ ASSERT_TRUE(mController->startSession(VIBRATOR_IDS, SESSION_CONFIG, []() {}).isOk());
+ ASSERT_TRUE(mController->clearSessions().isOk());
ASSERT_EQ(1, mConnectCounter);
}
@@ -154,7 +172,8 @@
setHalExpectations(/* cardinality= */ 1, vibrator::HalResult<void>::unsupported(),
vibrator::HalResult<vibrator::ManagerCapabilities>::unsupported(),
vibrator::HalResult<std::vector<int32_t>>::unsupported(),
- vibrator::HalResult<std::shared_ptr<HalController>>::unsupported());
+ vibrator::HalResult<std::shared_ptr<HalController>>::unsupported(),
+ vibrator::HalResult<std::shared_ptr<IVibrationSession>>::unsupported());
ASSERT_TRUE(mController->ping().isUnsupported());
ASSERT_TRUE(mController->getCapabilities().isUnsupported());
@@ -163,6 +182,8 @@
ASSERT_TRUE(mController->prepareSynced(VIBRATOR_IDS).isUnsupported());
ASSERT_TRUE(mController->triggerSynced([]() {}).isUnsupported());
ASSERT_TRUE(mController->cancelSynced().isUnsupported());
+ ASSERT_TRUE(mController->startSession(VIBRATOR_IDS, SESSION_CONFIG, []() {}).isUnsupported());
+ ASSERT_TRUE(mController->clearSessions().isUnsupported());
ASSERT_EQ(1, mConnectCounter);
}
@@ -171,7 +192,8 @@
setHalExpectations(/* cardinality= */ 1, vibrator::HalResult<void>::failed("msg"),
vibrator::HalResult<vibrator::ManagerCapabilities>::failed("msg"),
vibrator::HalResult<std::vector<int32_t>>::failed("msg"),
- vibrator::HalResult<std::shared_ptr<HalController>>::failed("msg"));
+ vibrator::HalResult<std::shared_ptr<HalController>>::failed("msg"),
+ vibrator::HalResult<std::shared_ptr<IVibrationSession>>::failed("msg"));
ASSERT_TRUE(mController->ping().isFailed());
ASSERT_TRUE(mController->getCapabilities().isFailed());
@@ -180,6 +202,8 @@
ASSERT_TRUE(mController->prepareSynced(VIBRATOR_IDS).isFailed());
ASSERT_TRUE(mController->triggerSynced([]() {}).isFailed());
ASSERT_TRUE(mController->cancelSynced().isFailed());
+ ASSERT_TRUE(mController->startSession(VIBRATOR_IDS, SESSION_CONFIG, []() {}).isFailed());
+ ASSERT_TRUE(mController->clearSessions().isFailed());
ASSERT_EQ(1, mConnectCounter);
}
@@ -188,7 +212,9 @@
setHalExpectations(MAX_ATTEMPTS, vibrator::HalResult<void>::transactionFailed("m"),
vibrator::HalResult<vibrator::ManagerCapabilities>::transactionFailed("m"),
vibrator::HalResult<std::vector<int32_t>>::transactionFailed("m"),
- vibrator::HalResult<std::shared_ptr<HalController>>::transactionFailed("m"));
+ vibrator::HalResult<std::shared_ptr<HalController>>::transactionFailed("m"),
+ vibrator::HalResult<std::shared_ptr<IVibrationSession>>::transactionFailed(
+ "m"));
ASSERT_TRUE(mController->ping().isFailed());
ASSERT_TRUE(mController->getCapabilities().isFailed());
@@ -197,6 +223,8 @@
ASSERT_TRUE(mController->prepareSynced(VIBRATOR_IDS).isFailed());
ASSERT_TRUE(mController->triggerSynced([]() {}).isFailed());
ASSERT_TRUE(mController->cancelSynced().isFailed());
+ ASSERT_TRUE(mController->startSession(VIBRATOR_IDS, SESSION_CONFIG, []() {}).isFailed());
+ ASSERT_TRUE(mController->clearSessions().isFailed());
ASSERT_EQ(1, mConnectCounter);
}
diff --git a/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp b/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp
index ca13c0b..a2f002d 100644
--- a/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp
+++ b/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp
@@ -69,12 +69,25 @@
MOCK_METHOD(bool, isRemote, (), (override));
};
+class MockIVibrationSession : public IVibrationSession {
+public:
+ MockIVibrationSession() = default;
+
+ MOCK_METHOD(ndk::ScopedAStatus, close, (), (override));
+ MOCK_METHOD(ndk::ScopedAStatus, abort, (), (override));
+ MOCK_METHOD(ndk::ScopedAStatus, getInterfaceVersion, (int32_t*), (override));
+ MOCK_METHOD(ndk::ScopedAStatus, getInterfaceHash, (std::string*), (override));
+ MOCK_METHOD(ndk::SpAIBinder, asBinder, (), (override));
+ MOCK_METHOD(bool, isRemote, (), (override));
+};
+
// -------------------------------------------------------------------------------------------------
class VibratorManagerHalWrapperAidlTest : public Test {
public:
void SetUp() override {
mMockVibrator = ndk::SharedRefBase::make<StrictMock<vibrator::MockIVibrator>>();
+ mMockSession = ndk::SharedRefBase::make<StrictMock<MockIVibrationSession>>();
mMockHal = ndk::SharedRefBase::make<StrictMock<MockIVibratorManager>>();
mMockScheduler = std::make_shared<StrictMock<vibrator::MockCallbackScheduler>>();
mWrapper = std::make_unique<vibrator::AidlManagerHalWrapper>(mMockScheduler, mMockHal);
@@ -86,11 +99,13 @@
std::unique_ptr<vibrator::ManagerHalWrapper> mWrapper = nullptr;
std::shared_ptr<StrictMock<MockIVibratorManager>> mMockHal = nullptr;
std::shared_ptr<StrictMock<vibrator::MockIVibrator>> mMockVibrator = nullptr;
+ std::shared_ptr<StrictMock<MockIVibrationSession>> mMockSession = nullptr;
};
// -------------------------------------------------------------------------------------------------
static const std::vector<int32_t> kVibratorIds = {1, 2};
+static const VibrationSessionConfig kSessionConfig;
static constexpr int kVibratorId = 1;
TEST_F(VibratorManagerHalWrapperAidlTest, TestGetCapabilitiesDoesNotCacheFailedResult) {
@@ -319,3 +334,35 @@
ASSERT_TRUE(mWrapper->getVibratorIds().isOk());
ASSERT_TRUE(mWrapper->cancelSynced().isOk());
}
+
+TEST_F(VibratorManagerHalWrapperAidlTest, TestStartSession) {
+ EXPECT_CALL(*mMockHal.get(), startSession(_, _, _, _))
+ .Times(Exactly(3))
+ .WillOnce(Return(ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION)))
+ .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
+ .WillOnce(
+ DoAll(DoAll(SetArgPointee<3>(mMockSession), Return(ndk::ScopedAStatus::ok()))));
+
+ std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
+ auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());
+
+ ASSERT_TRUE(mWrapper->startSession(kVibratorIds, kSessionConfig, callback).isUnsupported());
+ ASSERT_TRUE(mWrapper->startSession(kVibratorIds, kSessionConfig, callback).isFailed());
+
+ auto result = mWrapper->startSession(kVibratorIds, kSessionConfig, callback);
+ ASSERT_TRUE(result.isOk());
+ ASSERT_NE(nullptr, result.value().get());
+ ASSERT_EQ(0, *callbackCounter.get());
+}
+
+TEST_F(VibratorManagerHalWrapperAidlTest, TestClearSessions) {
+ EXPECT_CALL(*mMockHal.get(), clearSessions())
+ .Times(Exactly(3))
+ .WillOnce(Return(ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION)))
+ .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY)))
+ .WillOnce(Return(ndk::ScopedAStatus::ok()));
+
+ ASSERT_TRUE(mWrapper->clearSessions().isUnsupported());
+ ASSERT_TRUE(mWrapper->clearSessions().isFailed());
+ ASSERT_TRUE(mWrapper->clearSessions().isOk());
+}
diff --git a/services/vibratorservice/test/VibratorManagerHalWrapperLegacyTest.cpp b/services/vibratorservice/test/VibratorManagerHalWrapperLegacyTest.cpp
index 7877236..52c865e 100644
--- a/services/vibratorservice/test/VibratorManagerHalWrapperLegacyTest.cpp
+++ b/services/vibratorservice/test/VibratorManagerHalWrapperLegacyTest.cpp
@@ -29,6 +29,8 @@
using aidl::android::hardware::vibrator::CompositePrimitive;
using aidl::android::hardware::vibrator::Effect;
using aidl::android::hardware::vibrator::EffectStrength;
+using aidl::android::hardware::vibrator::IVibrationSession;
+using aidl::android::hardware::vibrator::VibrationSessionConfig;
using std::chrono::milliseconds;
@@ -112,3 +114,12 @@
ASSERT_TRUE(mWrapper->triggerSynced([]() {}).isUnsupported());
ASSERT_TRUE(mWrapper->cancelSynced().isUnsupported());
}
+
+TEST_F(VibratorManagerHalWrapperLegacyTest, TestSessionOperationsUnsupported) {
+ std::vector<int32_t> vibratorIds;
+ vibratorIds.push_back(0);
+ VibrationSessionConfig config;
+
+ ASSERT_TRUE(mWrapper->startSession(vibratorIds, config, []() {}).isUnsupported());
+ ASSERT_TRUE(mWrapper->clearSessions().isUnsupported());
+}
diff --git a/services/vibratorservice/test/test_mocks.h b/services/vibratorservice/test/test_mocks.h
index 5e09084..ba273be 100644
--- a/services/vibratorservice/test/test_mocks.h
+++ b/services/vibratorservice/test/test_mocks.h
@@ -36,13 +36,13 @@
using aidl::android::hardware::vibrator::Braking;
using aidl::android::hardware::vibrator::CompositeEffect;
using aidl::android::hardware::vibrator::CompositePrimitive;
+using aidl::android::hardware::vibrator::CompositePwleV2;
using aidl::android::hardware::vibrator::Effect;
using aidl::android::hardware::vibrator::EffectStrength;
+using aidl::android::hardware::vibrator::FrequencyAccelerationMapEntry;
using aidl::android::hardware::vibrator::IVibrator;
using aidl::android::hardware::vibrator::IVibratorCallback;
using aidl::android::hardware::vibrator::PrimitivePwle;
-using aidl::android::hardware::vibrator::PwleV2OutputMapEntry;
-using aidl::android::hardware::vibrator::PwleV2Primitive;
using aidl::android::hardware::vibrator::VendorEffect;
// -------------------------------------------------------------------------------------------------
@@ -91,16 +91,15 @@
MOCK_METHOD(ndk::ScopedAStatus, getPwlePrimitiveDurationMax, (int32_t * ret), (override));
MOCK_METHOD(ndk::ScopedAStatus, getPwleCompositionSizeMax, (int32_t * ret), (override));
MOCK_METHOD(ndk::ScopedAStatus, getSupportedBraking, (std::vector<Braking> * ret), (override));
- MOCK_METHOD(ndk::ScopedAStatus, getPwleV2FrequencyToOutputAccelerationMap,
- (std::vector<PwleV2OutputMapEntry> * ret), (override));
+ MOCK_METHOD(ndk::ScopedAStatus, getFrequencyToOutputAccelerationMap,
+ (std::vector<FrequencyAccelerationMapEntry> * ret), (override));
MOCK_METHOD(ndk::ScopedAStatus, getPwleV2PrimitiveDurationMaxMillis, (int32_t* ret),
(override));
MOCK_METHOD(ndk::ScopedAStatus, getPwleV2PrimitiveDurationMinMillis, (int32_t* ret),
(override));
MOCK_METHOD(ndk::ScopedAStatus, getPwleV2CompositionSizeMax, (int32_t* ret), (override));
MOCK_METHOD(ndk::ScopedAStatus, composePwleV2,
- (const std::vector<PwleV2Primitive>& e,
- const std::shared_ptr<IVibratorCallback>& cb),
+ (const CompositePwleV2& e, const std::shared_ptr<IVibratorCallback>& cb),
(override));
MOCK_METHOD(ndk::ScopedAStatus, getInterfaceVersion, (int32_t*), (override));
MOCK_METHOD(ndk::ScopedAStatus, getInterfaceHash, (std::string*), (override));
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 879d2d0..be8fb3e 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -22,6 +22,13 @@
default_applicable_licenses: ["frameworks_native_license"],
}
+// Expose internal header files to test testing binary
+cc_library_headers {
+ name: "libvulkanprivate_headers-testing",
+ export_include_dirs: ["."],
+ visibility: ["//frameworks/native/vulkan/tests"],
+}
+
ndk_library {
name: "libvulkan",
symbol_file: "libvulkan.map.txt",
diff --git a/vulkan/libvulkan/TEST_MAPPING b/vulkan/libvulkan/TEST_MAPPING
new file mode 100644
index 0000000..16e342b7
--- /dev/null
+++ b/vulkan/libvulkan/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "libvulkan_test"
+ }
+ ]
+}
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index c335e2a..8451ad1 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -45,6 +45,9 @@
#include "driver.h"
#include "layers_extensions.h"
+#include <com_android_graphics_libvulkan_flags.h>
+
+using namespace com::android::graphics::libvulkan;
namespace vulkan {
namespace api {
@@ -1473,7 +1476,7 @@
if (!EnsureInitialized())
return VK_ERROR_OUT_OF_HOST_MEMORY;
- *pApiVersion = VK_API_VERSION_1_3;
+ *pApiVersion = flags::vulkan_1_4_instance_api() ? VK_API_VERSION_1_4 : VK_API_VERSION_1_3;
return VK_SUCCESS;
}
diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp
index 9ff0b46..131c97c 100644
--- a/vulkan/libvulkan/api_gen.cpp
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -266,6 +266,7 @@
INIT_PROC(true, dev, CreateRenderPass);
INIT_PROC(true, dev, DestroyRenderPass);
INIT_PROC(true, dev, GetRenderAreaGranularity);
+ INIT_PROC(false, dev, GetRenderingAreaGranularity);
INIT_PROC(true, dev, CreateCommandPool);
INIT_PROC(true, dev, DestroyCommandPool);
INIT_PROC(true, dev, ResetCommandPool);
@@ -323,6 +324,7 @@
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(false, dev, CmdPushDescriptorSet);
INIT_PROC(false, dev, TrimCommandPool);
INIT_PROC(false, dev, GetDeviceGroupPeerMemoryFeatures);
INIT_PROC(false, dev, BindBufferMemory2);
@@ -335,6 +337,7 @@
INIT_PROC(false, dev, CreateDescriptorUpdateTemplate);
INIT_PROC(false, dev, DestroyDescriptorUpdateTemplate);
INIT_PROC(false, dev, UpdateDescriptorSetWithTemplate);
+ INIT_PROC(false, dev, CmdPushDescriptorSetWithTemplate);
INIT_PROC(false, dev, GetBufferMemoryRequirements2);
INIT_PROC(false, dev, GetImageMemoryRequirements2);
INIT_PROC(false, dev, GetImageSparseMemoryRequirements2);
@@ -359,11 +362,13 @@
INIT_PROC(false, dev, GetBufferOpaqueCaptureAddress);
INIT_PROC(false, dev, GetBufferDeviceAddress);
INIT_PROC(false, dev, GetDeviceMemoryOpaqueCaptureAddress);
+ INIT_PROC(false, dev, CmdSetLineStipple);
INIT_PROC(false, dev, CmdSetCullMode);
INIT_PROC(false, dev, CmdSetFrontFace);
INIT_PROC(false, dev, CmdSetPrimitiveTopology);
INIT_PROC(false, dev, CmdSetViewportWithCount);
INIT_PROC(false, dev, CmdSetScissorWithCount);
+ INIT_PROC(false, dev, CmdBindIndexBuffer2);
INIT_PROC(false, dev, CmdBindVertexBuffers2);
INIT_PROC(false, dev, CmdSetDepthTestEnable);
INIT_PROC(false, dev, CmdSetDepthWriteEnable);
@@ -390,8 +395,22 @@
INIT_PROC(false, dev, CmdPipelineBarrier2);
INIT_PROC(false, dev, QueueSubmit2);
INIT_PROC(false, dev, CmdWriteTimestamp2);
+ INIT_PROC(false, dev, CopyMemoryToImage);
+ INIT_PROC(false, dev, CopyImageToMemory);
+ INIT_PROC(false, dev, CopyImageToImage);
+ INIT_PROC(false, dev, TransitionImageLayout);
INIT_PROC(false, dev, CmdBeginRendering);
INIT_PROC(false, dev, CmdEndRendering);
+ INIT_PROC(false, dev, GetImageSubresourceLayout2);
+ INIT_PROC(false, dev, GetDeviceImageSubresourceLayout);
+ INIT_PROC(false, dev, MapMemory2);
+ INIT_PROC(false, dev, UnmapMemory2);
+ INIT_PROC(false, dev, CmdBindDescriptorSets2);
+ INIT_PROC(false, dev, CmdPushConstants2);
+ INIT_PROC(false, dev, CmdPushDescriptorSet2);
+ INIT_PROC(false, dev, CmdPushDescriptorSetWithTemplate2);
+ INIT_PROC(false, dev, CmdSetRenderingAttachmentLocations);
+ INIT_PROC(false, dev, CmdSetRenderingInputAttachmentIndices);
// clang-format on
return success;
@@ -480,6 +499,7 @@
VKAPI_ATTR VkResult CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass);
VKAPI_ATTR void DestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator);
VKAPI_ATTR void GetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity);
+VKAPI_ATTR void GetRenderingAreaGranularity(VkDevice device, const VkRenderingAreaInfo* pRenderingAreaInfo, VkExtent2D* pGranularity);
VKAPI_ATTR VkResult CreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool);
VKAPI_ATTR void DestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator);
VKAPI_ATTR VkResult ResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags);
@@ -550,6 +570,7 @@
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 CmdPushDescriptorSet(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites);
VKAPI_ATTR void TrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags);
VKAPI_ATTR void GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties);
VKAPI_ATTR void GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
@@ -567,6 +588,7 @@
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 CmdPushDescriptorSetWithTemplate(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData);
VKAPI_ATTR void GetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
VKAPI_ATTR void GetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
VKAPI_ATTR void GetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
@@ -591,12 +613,14 @@
VKAPI_ATTR uint64_t GetBufferOpaqueCaptureAddress(VkDevice device, const VkBufferDeviceAddressInfo* pInfo);
VKAPI_ATTR VkDeviceAddress GetBufferDeviceAddress(VkDevice device, const VkBufferDeviceAddressInfo* pInfo);
VKAPI_ATTR uint64_t GetDeviceMemoryOpaqueCaptureAddress(VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo);
+VKAPI_ATTR void CmdSetLineStipple(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern);
VKAPI_ATTR VkResult GetPhysicalDeviceToolProperties(VkPhysicalDevice physicalDevice, uint32_t* pToolCount, VkPhysicalDeviceToolProperties* pToolProperties);
VKAPI_ATTR void CmdSetCullMode(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode);
VKAPI_ATTR void CmdSetFrontFace(VkCommandBuffer commandBuffer, VkFrontFace frontFace);
VKAPI_ATTR void CmdSetPrimitiveTopology(VkCommandBuffer commandBuffer, VkPrimitiveTopology primitiveTopology);
VKAPI_ATTR void CmdSetViewportWithCount(VkCommandBuffer commandBuffer, uint32_t viewportCount, const VkViewport* pViewports);
VKAPI_ATTR void CmdSetScissorWithCount(VkCommandBuffer commandBuffer, uint32_t scissorCount, const VkRect2D* pScissors);
+VKAPI_ATTR void CmdBindIndexBuffer2(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size, VkIndexType indexType);
VKAPI_ATTR void CmdBindVertexBuffers2(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes, const VkDeviceSize* pStrides);
VKAPI_ATTR void CmdSetDepthTestEnable(VkCommandBuffer commandBuffer, VkBool32 depthTestEnable);
VKAPI_ATTR void CmdSetDepthWriteEnable(VkCommandBuffer commandBuffer, VkBool32 depthWriteEnable);
@@ -623,8 +647,22 @@
VKAPI_ATTR void CmdPipelineBarrier2(VkCommandBuffer commandBuffer, const VkDependencyInfo* pDependencyInfo);
VKAPI_ATTR VkResult QueueSubmit2(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2* pSubmits, VkFence fence);
VKAPI_ATTR void CmdWriteTimestamp2(VkCommandBuffer commandBuffer, VkPipelineStageFlags2 stage, VkQueryPool queryPool, uint32_t query);
+VKAPI_ATTR VkResult CopyMemoryToImage(VkDevice device, const VkCopyMemoryToImageInfo* pCopyMemoryToImageInfo);
+VKAPI_ATTR VkResult CopyImageToMemory(VkDevice device, const VkCopyImageToMemoryInfo* pCopyImageToMemoryInfo);
+VKAPI_ATTR VkResult CopyImageToImage(VkDevice device, const VkCopyImageToImageInfo* pCopyImageToImageInfo);
+VKAPI_ATTR VkResult TransitionImageLayout(VkDevice device, uint32_t transitionCount, const VkHostImageLayoutTransitionInfo* pTransitions);
VKAPI_ATTR void CmdBeginRendering(VkCommandBuffer commandBuffer, const VkRenderingInfo* pRenderingInfo);
VKAPI_ATTR void CmdEndRendering(VkCommandBuffer commandBuffer);
+VKAPI_ATTR void GetImageSubresourceLayout2(VkDevice device, VkImage image, const VkImageSubresource2* pSubresource, VkSubresourceLayout2* pLayout);
+VKAPI_ATTR void GetDeviceImageSubresourceLayout(VkDevice device, const VkDeviceImageSubresourceInfo* pInfo, VkSubresourceLayout2* pLayout);
+VKAPI_ATTR VkResult MapMemory2(VkDevice device, const VkMemoryMapInfo* pMemoryMapInfo, void** ppData);
+VKAPI_ATTR VkResult UnmapMemory2(VkDevice device, const VkMemoryUnmapInfo* pMemoryUnmapInfo);
+VKAPI_ATTR void CmdBindDescriptorSets2(VkCommandBuffer commandBuffer, const VkBindDescriptorSetsInfo* pBindDescriptorSetsInfo);
+VKAPI_ATTR void CmdPushConstants2(VkCommandBuffer commandBuffer, const VkPushConstantsInfo* pPushConstantsInfo);
+VKAPI_ATTR void CmdPushDescriptorSet2(VkCommandBuffer commandBuffer, const VkPushDescriptorSetInfo* pPushDescriptorSetInfo);
+VKAPI_ATTR void CmdPushDescriptorSetWithTemplate2(VkCommandBuffer commandBuffer, const VkPushDescriptorSetWithTemplateInfo* pPushDescriptorSetWithTemplateInfo);
+VKAPI_ATTR void CmdSetRenderingAttachmentLocations(VkCommandBuffer commandBuffer, const VkRenderingAttachmentLocationInfo* pLocationInfo);
+VKAPI_ATTR void CmdSetRenderingInputAttachmentIndices(VkCommandBuffer commandBuffer, const VkRenderingInputAttachmentIndexInfo* pInputAttachmentIndexInfo);
VKAPI_ATTR VkResult EnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices) {
return GetData(instance).dispatch.EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
@@ -764,7 +802,9 @@
{ "vkCmdBeginRenderPass2", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginRenderPass2) },
{ "vkCmdBeginRendering", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginRendering) },
{ "vkCmdBindDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(CmdBindDescriptorSets) },
+ { "vkCmdBindDescriptorSets2", reinterpret_cast<PFN_vkVoidFunction>(CmdBindDescriptorSets2) },
{ "vkCmdBindIndexBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdBindIndexBuffer) },
+ { "vkCmdBindIndexBuffer2", reinterpret_cast<PFN_vkVoidFunction>(CmdBindIndexBuffer2) },
{ "vkCmdBindPipeline", reinterpret_cast<PFN_vkVoidFunction>(CmdBindPipeline) },
{ "vkCmdBindVertexBuffers", reinterpret_cast<PFN_vkVoidFunction>(CmdBindVertexBuffers) },
{ "vkCmdBindVertexBuffers2", reinterpret_cast<PFN_vkVoidFunction>(CmdBindVertexBuffers2) },
@@ -802,6 +842,11 @@
{ "vkCmdPipelineBarrier", reinterpret_cast<PFN_vkVoidFunction>(CmdPipelineBarrier) },
{ "vkCmdPipelineBarrier2", reinterpret_cast<PFN_vkVoidFunction>(CmdPipelineBarrier2) },
{ "vkCmdPushConstants", reinterpret_cast<PFN_vkVoidFunction>(CmdPushConstants) },
+ { "vkCmdPushConstants2", reinterpret_cast<PFN_vkVoidFunction>(CmdPushConstants2) },
+ { "vkCmdPushDescriptorSet", reinterpret_cast<PFN_vkVoidFunction>(CmdPushDescriptorSet) },
+ { "vkCmdPushDescriptorSet2", reinterpret_cast<PFN_vkVoidFunction>(CmdPushDescriptorSet2) },
+ { "vkCmdPushDescriptorSetWithTemplate", reinterpret_cast<PFN_vkVoidFunction>(CmdPushDescriptorSetWithTemplate) },
+ { "vkCmdPushDescriptorSetWithTemplate2", reinterpret_cast<PFN_vkVoidFunction>(CmdPushDescriptorSetWithTemplate2) },
{ "vkCmdResetEvent", reinterpret_cast<PFN_vkVoidFunction>(CmdResetEvent) },
{ "vkCmdResetEvent2", reinterpret_cast<PFN_vkVoidFunction>(CmdResetEvent2) },
{ "vkCmdResetQueryPool", reinterpret_cast<PFN_vkVoidFunction>(CmdResetQueryPool) },
@@ -820,10 +865,13 @@
{ "vkCmdSetEvent", reinterpret_cast<PFN_vkVoidFunction>(CmdSetEvent) },
{ "vkCmdSetEvent2", reinterpret_cast<PFN_vkVoidFunction>(CmdSetEvent2) },
{ "vkCmdSetFrontFace", reinterpret_cast<PFN_vkVoidFunction>(CmdSetFrontFace) },
+ { "vkCmdSetLineStipple", reinterpret_cast<PFN_vkVoidFunction>(CmdSetLineStipple) },
{ "vkCmdSetLineWidth", reinterpret_cast<PFN_vkVoidFunction>(CmdSetLineWidth) },
{ "vkCmdSetPrimitiveRestartEnable", reinterpret_cast<PFN_vkVoidFunction>(CmdSetPrimitiveRestartEnable) },
{ "vkCmdSetPrimitiveTopology", reinterpret_cast<PFN_vkVoidFunction>(CmdSetPrimitiveTopology) },
{ "vkCmdSetRasterizerDiscardEnable", reinterpret_cast<PFN_vkVoidFunction>(CmdSetRasterizerDiscardEnable) },
+ { "vkCmdSetRenderingAttachmentLocations", reinterpret_cast<PFN_vkVoidFunction>(CmdSetRenderingAttachmentLocations) },
+ { "vkCmdSetRenderingInputAttachmentIndices", reinterpret_cast<PFN_vkVoidFunction>(CmdSetRenderingInputAttachmentIndices) },
{ "vkCmdSetScissor", reinterpret_cast<PFN_vkVoidFunction>(CmdSetScissor) },
{ "vkCmdSetScissorWithCount", reinterpret_cast<PFN_vkVoidFunction>(CmdSetScissorWithCount) },
{ "vkCmdSetStencilCompareMask", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilCompareMask) },
@@ -838,6 +886,9 @@
{ "vkCmdWaitEvents2", reinterpret_cast<PFN_vkVoidFunction>(CmdWaitEvents2) },
{ "vkCmdWriteTimestamp", reinterpret_cast<PFN_vkVoidFunction>(CmdWriteTimestamp) },
{ "vkCmdWriteTimestamp2", reinterpret_cast<PFN_vkVoidFunction>(CmdWriteTimestamp2) },
+ { "vkCopyImageToImage", reinterpret_cast<PFN_vkVoidFunction>(CopyImageToImage) },
+ { "vkCopyImageToMemory", reinterpret_cast<PFN_vkVoidFunction>(CopyImageToMemory) },
+ { "vkCopyMemoryToImage", reinterpret_cast<PFN_vkVoidFunction>(CopyMemoryToImage) },
{ "vkCreateBuffer", reinterpret_cast<PFN_vkVoidFunction>(CreateBuffer) },
{ "vkCreateBufferView", reinterpret_cast<PFN_vkVoidFunction>(CreateBufferView) },
{ "vkCreateCommandPool", reinterpret_cast<PFN_vkVoidFunction>(CreateCommandPool) },
@@ -911,6 +962,7 @@
{ "vkGetDeviceGroupSurfacePresentModesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceGroupSurfacePresentModesKHR) },
{ "vkGetDeviceImageMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceImageMemoryRequirements) },
{ "vkGetDeviceImageSparseMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceImageSparseMemoryRequirements) },
+ { "vkGetDeviceImageSubresourceLayout", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceImageSubresourceLayout) },
{ "vkGetDeviceMemoryCommitment", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceMemoryCommitment) },
{ "vkGetDeviceMemoryOpaqueCaptureAddress", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceMemoryOpaqueCaptureAddress) },
{ "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr) },
@@ -923,16 +975,19 @@
{ "vkGetImageSparseMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(GetImageSparseMemoryRequirements) },
{ "vkGetImageSparseMemoryRequirements2", reinterpret_cast<PFN_vkVoidFunction>(GetImageSparseMemoryRequirements2) },
{ "vkGetImageSubresourceLayout", reinterpret_cast<PFN_vkVoidFunction>(GetImageSubresourceLayout) },
+ { "vkGetImageSubresourceLayout2", reinterpret_cast<PFN_vkVoidFunction>(GetImageSubresourceLayout2) },
{ "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) },
{ "vkGetMemoryAndroidHardwareBufferANDROID", reinterpret_cast<PFN_vkVoidFunction>(GetMemoryAndroidHardwareBufferANDROID) },
{ "vkGetPipelineCacheData", reinterpret_cast<PFN_vkVoidFunction>(GetPipelineCacheData) },
{ "vkGetPrivateData", reinterpret_cast<PFN_vkVoidFunction>(GetPrivateData) },
{ "vkGetQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(GetQueryPoolResults) },
{ "vkGetRenderAreaGranularity", reinterpret_cast<PFN_vkVoidFunction>(GetRenderAreaGranularity) },
+ { "vkGetRenderingAreaGranularity", reinterpret_cast<PFN_vkVoidFunction>(GetRenderingAreaGranularity) },
{ "vkGetSemaphoreCounterValue", reinterpret_cast<PFN_vkVoidFunction>(GetSemaphoreCounterValue) },
{ "vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR) },
{ "vkInvalidateMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(InvalidateMappedMemoryRanges) },
{ "vkMapMemory", reinterpret_cast<PFN_vkVoidFunction>(MapMemory) },
+ { "vkMapMemory2", reinterpret_cast<PFN_vkVoidFunction>(MapMemory2) },
{ "vkMergePipelineCaches", reinterpret_cast<PFN_vkVoidFunction>(MergePipelineCaches) },
{ "vkQueueBindSparse", reinterpret_cast<PFN_vkVoidFunction>(QueueBindSparse) },
{ "vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR) },
@@ -948,8 +1003,10 @@
{ "vkSetEvent", reinterpret_cast<PFN_vkVoidFunction>(SetEvent) },
{ "vkSetPrivateData", reinterpret_cast<PFN_vkVoidFunction>(SetPrivateData) },
{ "vkSignalSemaphore", reinterpret_cast<PFN_vkVoidFunction>(SignalSemaphore) },
+ { "vkTransitionImageLayout", reinterpret_cast<PFN_vkVoidFunction>(TransitionImageLayout) },
{ "vkTrimCommandPool", reinterpret_cast<PFN_vkVoidFunction>(TrimCommandPool) },
{ "vkUnmapMemory", reinterpret_cast<PFN_vkVoidFunction>(UnmapMemory) },
+ { "vkUnmapMemory2", reinterpret_cast<PFN_vkVoidFunction>(UnmapMemory2) },
{ "vkUpdateDescriptorSetWithTemplate", reinterpret_cast<PFN_vkVoidFunction>(UpdateDescriptorSetWithTemplate) },
{ "vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(UpdateDescriptorSets) },
{ "vkWaitForFences", reinterpret_cast<PFN_vkVoidFunction>(WaitForFences) },
@@ -1273,6 +1330,10 @@
GetData(device).dispatch.GetRenderAreaGranularity(device, renderPass, pGranularity);
}
+VKAPI_ATTR void GetRenderingAreaGranularity(VkDevice device, const VkRenderingAreaInfo* pRenderingAreaInfo, VkExtent2D* pGranularity) {
+ GetData(device).dispatch.GetRenderingAreaGranularity(device, pRenderingAreaInfo, pGranularity);
+}
+
VKAPI_ATTR VkResult CreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool) {
return GetData(device).dispatch.CreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool);
}
@@ -1553,6 +1614,10 @@
GetData(physicalDevice).dispatch.GetPhysicalDeviceSparseImageFormatProperties2(physicalDevice, pFormatInfo, pPropertyCount, pProperties);
}
+VKAPI_ATTR void CmdPushDescriptorSet(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites) {
+ GetData(commandBuffer).dispatch.CmdPushDescriptorSet(commandBuffer, pipelineBindPoint, layout, set, descriptorWriteCount, pDescriptorWrites);
+}
+
VKAPI_ATTR void TrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags) {
GetData(device).dispatch.TrimCommandPool(device, commandPool, flags);
}
@@ -1621,6 +1686,10 @@
GetData(device).dispatch.UpdateDescriptorSetWithTemplate(device, descriptorSet, descriptorUpdateTemplate, pData);
}
+VKAPI_ATTR void CmdPushDescriptorSetWithTemplate(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData) {
+ GetData(commandBuffer).dispatch.CmdPushDescriptorSetWithTemplate(commandBuffer, descriptorUpdateTemplate, layout, set, pData);
+}
+
VKAPI_ATTR void GetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
GetData(device).dispatch.GetBufferMemoryRequirements2(device, pInfo, pMemoryRequirements);
}
@@ -1717,6 +1786,10 @@
return GetData(device).dispatch.GetDeviceMemoryOpaqueCaptureAddress(device, pInfo);
}
+VKAPI_ATTR void CmdSetLineStipple(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern) {
+ GetData(commandBuffer).dispatch.CmdSetLineStipple(commandBuffer, lineStippleFactor, lineStipplePattern);
+}
+
VKAPI_ATTR VkResult GetPhysicalDeviceToolProperties(VkPhysicalDevice physicalDevice, uint32_t* pToolCount, VkPhysicalDeviceToolProperties* pToolProperties) {
return GetData(physicalDevice).dispatch.GetPhysicalDeviceToolProperties(physicalDevice, pToolCount, pToolProperties);
}
@@ -1741,6 +1814,10 @@
GetData(commandBuffer).dispatch.CmdSetScissorWithCount(commandBuffer, scissorCount, pScissors);
}
+VKAPI_ATTR void CmdBindIndexBuffer2(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size, VkIndexType indexType) {
+ GetData(commandBuffer).dispatch.CmdBindIndexBuffer2(commandBuffer, buffer, offset, size, indexType);
+}
+
VKAPI_ATTR void CmdBindVertexBuffers2(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes, const VkDeviceSize* pStrides) {
GetData(commandBuffer).dispatch.CmdBindVertexBuffers2(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets, pSizes, pStrides);
}
@@ -1845,6 +1922,22 @@
GetData(commandBuffer).dispatch.CmdWriteTimestamp2(commandBuffer, stage, queryPool, query);
}
+VKAPI_ATTR VkResult CopyMemoryToImage(VkDevice device, const VkCopyMemoryToImageInfo* pCopyMemoryToImageInfo) {
+ return GetData(device).dispatch.CopyMemoryToImage(device, pCopyMemoryToImageInfo);
+}
+
+VKAPI_ATTR VkResult CopyImageToMemory(VkDevice device, const VkCopyImageToMemoryInfo* pCopyImageToMemoryInfo) {
+ return GetData(device).dispatch.CopyImageToMemory(device, pCopyImageToMemoryInfo);
+}
+
+VKAPI_ATTR VkResult CopyImageToImage(VkDevice device, const VkCopyImageToImageInfo* pCopyImageToImageInfo) {
+ return GetData(device).dispatch.CopyImageToImage(device, pCopyImageToImageInfo);
+}
+
+VKAPI_ATTR VkResult TransitionImageLayout(VkDevice device, uint32_t transitionCount, const VkHostImageLayoutTransitionInfo* pTransitions) {
+ return GetData(device).dispatch.TransitionImageLayout(device, transitionCount, pTransitions);
+}
+
VKAPI_ATTR void CmdBeginRendering(VkCommandBuffer commandBuffer, const VkRenderingInfo* pRenderingInfo) {
GetData(commandBuffer).dispatch.CmdBeginRendering(commandBuffer, pRenderingInfo);
}
@@ -1853,6 +1946,46 @@
GetData(commandBuffer).dispatch.CmdEndRendering(commandBuffer);
}
+VKAPI_ATTR void GetImageSubresourceLayout2(VkDevice device, VkImage image, const VkImageSubresource2* pSubresource, VkSubresourceLayout2* pLayout) {
+ GetData(device).dispatch.GetImageSubresourceLayout2(device, image, pSubresource, pLayout);
+}
+
+VKAPI_ATTR void GetDeviceImageSubresourceLayout(VkDevice device, const VkDeviceImageSubresourceInfo* pInfo, VkSubresourceLayout2* pLayout) {
+ GetData(device).dispatch.GetDeviceImageSubresourceLayout(device, pInfo, pLayout);
+}
+
+VKAPI_ATTR VkResult MapMemory2(VkDevice device, const VkMemoryMapInfo* pMemoryMapInfo, void** ppData) {
+ return GetData(device).dispatch.MapMemory2(device, pMemoryMapInfo, ppData);
+}
+
+VKAPI_ATTR VkResult UnmapMemory2(VkDevice device, const VkMemoryUnmapInfo* pMemoryUnmapInfo) {
+ return GetData(device).dispatch.UnmapMemory2(device, pMemoryUnmapInfo);
+}
+
+VKAPI_ATTR void CmdBindDescriptorSets2(VkCommandBuffer commandBuffer, const VkBindDescriptorSetsInfo* pBindDescriptorSetsInfo) {
+ GetData(commandBuffer).dispatch.CmdBindDescriptorSets2(commandBuffer, pBindDescriptorSetsInfo);
+}
+
+VKAPI_ATTR void CmdPushConstants2(VkCommandBuffer commandBuffer, const VkPushConstantsInfo* pPushConstantsInfo) {
+ GetData(commandBuffer).dispatch.CmdPushConstants2(commandBuffer, pPushConstantsInfo);
+}
+
+VKAPI_ATTR void CmdPushDescriptorSet2(VkCommandBuffer commandBuffer, const VkPushDescriptorSetInfo* pPushDescriptorSetInfo) {
+ GetData(commandBuffer).dispatch.CmdPushDescriptorSet2(commandBuffer, pPushDescriptorSetInfo);
+}
+
+VKAPI_ATTR void CmdPushDescriptorSetWithTemplate2(VkCommandBuffer commandBuffer, const VkPushDescriptorSetWithTemplateInfo* pPushDescriptorSetWithTemplateInfo) {
+ GetData(commandBuffer).dispatch.CmdPushDescriptorSetWithTemplate2(commandBuffer, pPushDescriptorSetWithTemplateInfo);
+}
+
+VKAPI_ATTR void CmdSetRenderingAttachmentLocations(VkCommandBuffer commandBuffer, const VkRenderingAttachmentLocationInfo* pLocationInfo) {
+ GetData(commandBuffer).dispatch.CmdSetRenderingAttachmentLocations(commandBuffer, pLocationInfo);
+}
+
+VKAPI_ATTR void CmdSetRenderingInputAttachmentIndices(VkCommandBuffer commandBuffer, const VkRenderingInputAttachmentIndexInfo* pInputAttachmentIndexInfo) {
+ GetData(commandBuffer).dispatch.CmdSetRenderingInputAttachmentIndices(commandBuffer, pInputAttachmentIndexInfo);
+}
+
} // anonymous namespace
@@ -2299,6 +2432,11 @@
}
__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetRenderingAreaGranularity(VkDevice device, const VkRenderingAreaInfo* pRenderingAreaInfo, VkExtent2D* pGranularity) {
+ vulkan::api::GetRenderingAreaGranularity(device, pRenderingAreaInfo, pGranularity);
+}
+
+__attribute__((visibility("default")))
VKAPI_ATTR VkResult vkCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool) {
return vulkan::api::CreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool);
}
@@ -2649,6 +2787,11 @@
}
__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdPushDescriptorSet(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites) {
+ vulkan::api::CmdPushDescriptorSet(commandBuffer, pipelineBindPoint, layout, set, descriptorWriteCount, pDescriptorWrites);
+}
+
+__attribute__((visibility("default")))
VKAPI_ATTR void vkTrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags) {
vulkan::api::TrimCommandPool(device, commandPool, flags);
}
@@ -2734,6 +2877,11 @@
}
__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdPushDescriptorSetWithTemplate(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData) {
+ vulkan::api::CmdPushDescriptorSetWithTemplate(commandBuffer, descriptorUpdateTemplate, layout, set, pData);
+}
+
+__attribute__((visibility("default")))
VKAPI_ATTR void vkGetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements) {
vulkan::api::GetBufferMemoryRequirements2(device, pInfo, pMemoryRequirements);
}
@@ -2854,6 +3002,11 @@
}
__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetLineStipple(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern) {
+ vulkan::api::CmdSetLineStipple(commandBuffer, lineStippleFactor, lineStipplePattern);
+}
+
+__attribute__((visibility("default")))
VKAPI_ATTR VkResult vkGetPhysicalDeviceToolProperties(VkPhysicalDevice physicalDevice, uint32_t* pToolCount, VkPhysicalDeviceToolProperties* pToolProperties) {
return vulkan::api::GetPhysicalDeviceToolProperties(physicalDevice, pToolCount, pToolProperties);
}
@@ -2884,6 +3037,11 @@
}
__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdBindIndexBuffer2(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size, VkIndexType indexType) {
+ vulkan::api::CmdBindIndexBuffer2(commandBuffer, buffer, offset, size, indexType);
+}
+
+__attribute__((visibility("default")))
VKAPI_ATTR void vkCmdBindVertexBuffers2(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes, const VkDeviceSize* pStrides) {
vulkan::api::CmdBindVertexBuffers2(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets, pSizes, pStrides);
}
@@ -3014,6 +3172,26 @@
}
__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCopyMemoryToImage(VkDevice device, const VkCopyMemoryToImageInfo* pCopyMemoryToImageInfo) {
+ return vulkan::api::CopyMemoryToImage(device, pCopyMemoryToImageInfo);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCopyImageToMemory(VkDevice device, const VkCopyImageToMemoryInfo* pCopyImageToMemoryInfo) {
+ return vulkan::api::CopyImageToMemory(device, pCopyImageToMemoryInfo);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCopyImageToImage(VkDevice device, const VkCopyImageToImageInfo* pCopyImageToImageInfo) {
+ return vulkan::api::CopyImageToImage(device, pCopyImageToImageInfo);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkTransitionImageLayout(VkDevice device, uint32_t transitionCount, const VkHostImageLayoutTransitionInfo* pTransitions) {
+ return vulkan::api::TransitionImageLayout(device, transitionCount, pTransitions);
+}
+
+__attribute__((visibility("default")))
VKAPI_ATTR void vkCmdBeginRendering(VkCommandBuffer commandBuffer, const VkRenderingInfo* pRenderingInfo) {
vulkan::api::CmdBeginRendering(commandBuffer, pRenderingInfo);
}
@@ -3023,4 +3201,54 @@
vulkan::api::CmdEndRendering(commandBuffer);
}
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetImageSubresourceLayout2(VkDevice device, VkImage image, const VkImageSubresource2* pSubresource, VkSubresourceLayout2* pLayout) {
+ vulkan::api::GetImageSubresourceLayout2(device, image, pSubresource, pLayout);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetDeviceImageSubresourceLayout(VkDevice device, const VkDeviceImageSubresourceInfo* pInfo, VkSubresourceLayout2* pLayout) {
+ vulkan::api::GetDeviceImageSubresourceLayout(device, pInfo, pLayout);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkMapMemory2(VkDevice device, const VkMemoryMapInfo* pMemoryMapInfo, void** ppData) {
+ return vulkan::api::MapMemory2(device, pMemoryMapInfo, ppData);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkUnmapMemory2(VkDevice device, const VkMemoryUnmapInfo* pMemoryUnmapInfo) {
+ return vulkan::api::UnmapMemory2(device, pMemoryUnmapInfo);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdBindDescriptorSets2(VkCommandBuffer commandBuffer, const VkBindDescriptorSetsInfo* pBindDescriptorSetsInfo) {
+ vulkan::api::CmdBindDescriptorSets2(commandBuffer, pBindDescriptorSetsInfo);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdPushConstants2(VkCommandBuffer commandBuffer, const VkPushConstantsInfo* pPushConstantsInfo) {
+ vulkan::api::CmdPushConstants2(commandBuffer, pPushConstantsInfo);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdPushDescriptorSet2(VkCommandBuffer commandBuffer, const VkPushDescriptorSetInfo* pPushDescriptorSetInfo) {
+ vulkan::api::CmdPushDescriptorSet2(commandBuffer, pPushDescriptorSetInfo);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdPushDescriptorSetWithTemplate2(VkCommandBuffer commandBuffer, const VkPushDescriptorSetWithTemplateInfo* pPushDescriptorSetWithTemplateInfo) {
+ vulkan::api::CmdPushDescriptorSetWithTemplate2(commandBuffer, pPushDescriptorSetWithTemplateInfo);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetRenderingAttachmentLocations(VkCommandBuffer commandBuffer, const VkRenderingAttachmentLocationInfo* pLocationInfo) {
+ vulkan::api::CmdSetRenderingAttachmentLocations(commandBuffer, pLocationInfo);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetRenderingInputAttachmentIndices(VkCommandBuffer commandBuffer, const VkRenderingInputAttachmentIndexInfo* pInputAttachmentIndexInfo) {
+ vulkan::api::CmdSetRenderingInputAttachmentIndices(commandBuffer, pInputAttachmentIndexInfo);
+}
+
// clang-format on
diff --git a/vulkan/libvulkan/api_gen.h b/vulkan/libvulkan/api_gen.h
index b468a89..17dc62f 100644
--- a/vulkan/libvulkan/api_gen.h
+++ b/vulkan/libvulkan/api_gen.h
@@ -139,6 +139,7 @@
PFN_vkCreateRenderPass CreateRenderPass;
PFN_vkDestroyRenderPass DestroyRenderPass;
PFN_vkGetRenderAreaGranularity GetRenderAreaGranularity;
+ PFN_vkGetRenderingAreaGranularity GetRenderingAreaGranularity;
PFN_vkCreateCommandPool CreateCommandPool;
PFN_vkDestroyCommandPool DestroyCommandPool;
PFN_vkResetCommandPool ResetCommandPool;
@@ -196,6 +197,7 @@
PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR;
PFN_vkAcquireNextImageKHR AcquireNextImageKHR;
PFN_vkQueuePresentKHR QueuePresentKHR;
+ PFN_vkCmdPushDescriptorSet CmdPushDescriptorSet;
PFN_vkTrimCommandPool TrimCommandPool;
PFN_vkGetDeviceGroupPeerMemoryFeatures GetDeviceGroupPeerMemoryFeatures;
PFN_vkBindBufferMemory2 BindBufferMemory2;
@@ -208,6 +210,7 @@
PFN_vkCreateDescriptorUpdateTemplate CreateDescriptorUpdateTemplate;
PFN_vkDestroyDescriptorUpdateTemplate DestroyDescriptorUpdateTemplate;
PFN_vkUpdateDescriptorSetWithTemplate UpdateDescriptorSetWithTemplate;
+ PFN_vkCmdPushDescriptorSetWithTemplate CmdPushDescriptorSetWithTemplate;
PFN_vkGetBufferMemoryRequirements2 GetBufferMemoryRequirements2;
PFN_vkGetImageMemoryRequirements2 GetImageMemoryRequirements2;
PFN_vkGetImageSparseMemoryRequirements2 GetImageSparseMemoryRequirements2;
@@ -232,11 +235,13 @@
PFN_vkGetBufferOpaqueCaptureAddress GetBufferOpaqueCaptureAddress;
PFN_vkGetBufferDeviceAddress GetBufferDeviceAddress;
PFN_vkGetDeviceMemoryOpaqueCaptureAddress GetDeviceMemoryOpaqueCaptureAddress;
+ PFN_vkCmdSetLineStipple CmdSetLineStipple;
PFN_vkCmdSetCullMode CmdSetCullMode;
PFN_vkCmdSetFrontFace CmdSetFrontFace;
PFN_vkCmdSetPrimitiveTopology CmdSetPrimitiveTopology;
PFN_vkCmdSetViewportWithCount CmdSetViewportWithCount;
PFN_vkCmdSetScissorWithCount CmdSetScissorWithCount;
+ PFN_vkCmdBindIndexBuffer2 CmdBindIndexBuffer2;
PFN_vkCmdBindVertexBuffers2 CmdBindVertexBuffers2;
PFN_vkCmdSetDepthTestEnable CmdSetDepthTestEnable;
PFN_vkCmdSetDepthWriteEnable CmdSetDepthWriteEnable;
@@ -263,8 +268,22 @@
PFN_vkCmdPipelineBarrier2 CmdPipelineBarrier2;
PFN_vkQueueSubmit2 QueueSubmit2;
PFN_vkCmdWriteTimestamp2 CmdWriteTimestamp2;
+ PFN_vkCopyMemoryToImage CopyMemoryToImage;
+ PFN_vkCopyImageToMemory CopyImageToMemory;
+ PFN_vkCopyImageToImage CopyImageToImage;
+ PFN_vkTransitionImageLayout TransitionImageLayout;
PFN_vkCmdBeginRendering CmdBeginRendering;
PFN_vkCmdEndRendering CmdEndRendering;
+ PFN_vkGetImageSubresourceLayout2 GetImageSubresourceLayout2;
+ PFN_vkGetDeviceImageSubresourceLayout GetDeviceImageSubresourceLayout;
+ PFN_vkMapMemory2 MapMemory2;
+ PFN_vkUnmapMemory2 UnmapMemory2;
+ PFN_vkCmdBindDescriptorSets2 CmdBindDescriptorSets2;
+ PFN_vkCmdPushConstants2 CmdPushConstants2;
+ PFN_vkCmdPushDescriptorSet2 CmdPushDescriptorSet2;
+ PFN_vkCmdPushDescriptorSetWithTemplate2 CmdPushDescriptorSetWithTemplate2;
+ PFN_vkCmdSetRenderingAttachmentLocations CmdSetRenderingAttachmentLocations;
+ PFN_vkCmdSetRenderingInputAttachmentIndices CmdSetRenderingInputAttachmentIndices;
// clang-format on
};
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 01436db..7d0f545 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -398,7 +398,7 @@
const VkAllocationCallbacks& allocator)
: is_instance_(true),
allocator_(allocator),
- loader_api_version_(VK_API_VERSION_1_3),
+ loader_api_version_(flags::vulkan_1_4_instance_api() ? VK_API_VERSION_1_4 : VK_API_VERSION_1_3),
icd_api_version_(icd_api_version),
physical_dev_(VK_NULL_HANDLE),
instance_info_(create_info),
@@ -410,7 +410,7 @@
const VkAllocationCallbacks& allocator)
: is_instance_(false),
allocator_(allocator),
- loader_api_version_(VK_API_VERSION_1_3),
+ loader_api_version_(flags::vulkan_1_4_instance_api() ? VK_API_VERSION_1_4 : VK_API_VERSION_1_3),
icd_api_version_(icd_api_version),
physical_dev_(physical_dev),
dev_info_(create_info),
@@ -552,6 +552,10 @@
is_instance_ ? loader_api_version_
: std::min(icd_api_version_, loader_api_version_);
switch (api_version) {
+ case VK_API_VERSION_1_4:
+ hook_extensions_.set(ProcHook::EXTENSION_CORE_1_4);
+ hal_extensions_.set(ProcHook::EXTENSION_CORE_1_4);
+ [[clang::fallthrough]];
case VK_API_VERSION_1_3:
hook_extensions_.set(ProcHook::EXTENSION_CORE_1_3);
hal_extensions_.set(ProcHook::EXTENSION_CORE_1_3);
@@ -701,6 +705,7 @@
case ProcHook::EXTENSION_CORE_1_1:
case ProcHook::EXTENSION_CORE_1_2:
case ProcHook::EXTENSION_CORE_1_3:
+ case ProcHook::EXTENSION_CORE_1_4:
case ProcHook::EXTENSION_COUNT:
// Device and meta extensions. If we ever get here it's a bug in
// our code. But enumerating them lets us avoid having a default
@@ -766,6 +771,7 @@
case ProcHook::EXTENSION_CORE_1_1:
case ProcHook::EXTENSION_CORE_1_2:
case ProcHook::EXTENSION_CORE_1_3:
+ case ProcHook::EXTENSION_CORE_1_4:
case ProcHook::EXTENSION_COUNT:
// Instance and meta extensions. If we ever get here it's a bug
// in our code. But enumerating them lets us avoid having a
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index 649c0f1..204b16f 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -68,6 +68,7 @@
EXTENSION_CORE_1_1,
EXTENSION_CORE_1_2,
EXTENSION_CORE_1_3,
+ EXTENSION_CORE_1_4,
EXTENSION_COUNT,
EXTENSION_UNKNOWN,
};
diff --git a/vulkan/libvulkan/libvulkan.map.txt b/vulkan/libvulkan/libvulkan.map.txt
index b189c68..ffe46f7 100644
--- a/vulkan/libvulkan/libvulkan.map.txt
+++ b/vulkan/libvulkan/libvulkan.map.txt
@@ -6,32 +6,34 @@
vkAllocateDescriptorSets;
vkAllocateMemory;
vkBeginCommandBuffer;
- vkBindBufferMemory;
vkBindBufferMemory2; # introduced=28
- vkBindImageMemory;
+ vkBindBufferMemory;
vkBindImageMemory2; # introduced=28
+ vkBindImageMemory;
vkCmdBeginQuery;
- vkCmdBeginRendering; # introduced=33
- vkCmdBeginRenderPass;
vkCmdBeginRenderPass2; # introduced=31
+ vkCmdBeginRenderPass;
+ vkCmdBeginRendering; # introduced=33
+ vkCmdBindDescriptorSets2; #introduced=36
vkCmdBindDescriptorSets;
+ vkCmdBindIndexBuffer2; #introduced=36
vkCmdBindIndexBuffer;
vkCmdBindPipeline;
- vkCmdBindVertexBuffers;
vkCmdBindVertexBuffers2; #introduced=33
- vkCmdBlitImage;
+ vkCmdBindVertexBuffers;
vkCmdBlitImage2; #introduced=33
+ vkCmdBlitImage;
vkCmdClearAttachments;
vkCmdClearColorImage;
vkCmdClearDepthStencilImage;
- vkCmdCopyBuffer;
vkCmdCopyBuffer2; #introduced=33
- vkCmdCopyBufferToImage;
+ vkCmdCopyBuffer;
vkCmdCopyBufferToImage2; #introduced=33
- vkCmdCopyImage;
+ vkCmdCopyBufferToImage;
vkCmdCopyImage2; #introduced=33
- vkCmdCopyImageToBuffer;
+ vkCmdCopyImage;
vkCmdCopyImageToBuffer2; #introduced=33
+ vkCmdCopyImageToBuffer;
vkCmdCopyQueryPoolResults;
vkCmdDispatch;
vkCmdDispatchBase; # introduced=28
@@ -43,21 +45,26 @@
vkCmdDrawIndirect;
vkCmdDrawIndirectCount; # introduced=31
vkCmdEndQuery;
- vkCmdEndRendering; #introduced=33
- vkCmdEndRenderPass;
vkCmdEndRenderPass2; # introduced=31
+ vkCmdEndRenderPass;
+ vkCmdEndRendering; #introduced=33
vkCmdExecuteCommands;
vkCmdFillBuffer;
- vkCmdNextSubpass;
vkCmdNextSubpass2; # introduced=31
- vkCmdPipelineBarrier;
+ vkCmdNextSubpass;
vkCmdPipelineBarrier2; #introduced=33
+ vkCmdPipelineBarrier;
+ vkCmdPushConstants2; #introduced=36
vkCmdPushConstants;
- vkCmdResetEvent;
+ vkCmdPushDescriptorSet2; #introduced=36
+ vkCmdPushDescriptorSet; #introduced=36
+ vkCmdPushDescriptorSetWithTemplate2; #introduced=36
+ vkCmdPushDescriptorSetWithTemplate; #introduced=36
vkCmdResetEvent2; #introduced=33
+ vkCmdResetEvent;
vkCmdResetQueryPool;
- vkCmdResolveImage;
vkCmdResolveImage2; #introduced=33
+ vkCmdResolveImage;
vkCmdSetBlendConstants;
vkCmdSetCullMode; #introduced=33
vkCmdSetDepthBias;
@@ -68,13 +75,16 @@
vkCmdSetDepthTestEnable; #introduced=33
vkCmdSetDepthWriteEnable; #introduced=33
vkCmdSetDeviceMask; # introduced=28
- vkCmdSetEvent;
vkCmdSetEvent2; #introduced=33
+ vkCmdSetEvent;
vkCmdSetFrontFace; #introduced=33
+ vkCmdSetLineStipple; #introduced=36
vkCmdSetLineWidth;
vkCmdSetPrimitiveRestartEnable; #introduced=33
vkCmdSetPrimitiveTopology; #introduced=33
vkCmdSetRasterizerDiscardEnable; #introduced=33
+ vkCmdSetRenderingAttachmentLocations; #introduced=36
+ vkCmdSetRenderingInputAttachmentIndices; #introduced=36
vkCmdSetScissor;
vkCmdSetScissorWithCount; #introduced=33
vkCmdSetStencilCompareMask;
@@ -85,10 +95,12 @@
vkCmdSetViewport;
vkCmdSetViewportWithCount; #introduced=33
vkCmdUpdateBuffer;
- vkCmdWaitEvents;
vkCmdWaitEvents2; #introduced=33
- vkCmdWriteTimestamp;
+ vkCmdWaitEvents;
vkCmdWriteTimestamp2; #introduced=33
+ vkCmdWriteTimestamp;
+ vkCopyImageToMemory; #introduced=36
+ vkCopyMemoryToImage; #introduced=36
vkCreateAndroidSurfaceKHR;
vkCreateBuffer;
vkCreateBufferView;
@@ -109,8 +121,8 @@
vkCreatePipelineLayout;
vkCreatePrivateDataSlot; #introduced=33
vkCreateQueryPool;
- vkCreateRenderPass;
vkCreateRenderPass2; # introduced=31
+ vkCreateRenderPass;
vkCreateSampler;
vkCreateSamplerYcbcrConversion; # introduced=28
vkCreateSemaphore;
@@ -156,8 +168,8 @@
vkFreeMemory;
vkGetAndroidHardwareBufferPropertiesANDROID; # introduced=28
vkGetBufferDeviceAddress; # introduced=31
- vkGetBufferMemoryRequirements;
vkGetBufferMemoryRequirements2; # introduced=28
+ vkGetBufferMemoryRequirements;
vkGetBufferOpaqueCaptureAddress; # introduced=31
vkGetDescriptorSetLayoutSupport; # introduced=28
vkGetDeviceBufferMemoryRequirements; #introduced=33
@@ -166,39 +178,41 @@
vkGetDeviceGroupSurfacePresentModesKHR; # introduced=28
vkGetDeviceImageMemoryRequirements; #introduced=33
vkGetDeviceImageSparseMemoryRequirements; #introduced=33
+ vkGetDeviceImageSubresourceLayout; #introduced=36
vkGetDeviceMemoryCommitment;
vkGetDeviceMemoryOpaqueCaptureAddress; # introduced=31
vkGetDeviceProcAddr;
- vkGetDeviceQueue;
vkGetDeviceQueue2; # introduced=28
+ vkGetDeviceQueue;
vkGetEventStatus;
vkGetFenceStatus;
- vkGetImageMemoryRequirements;
vkGetImageMemoryRequirements2; # introduced=28
- vkGetImageSparseMemoryRequirements;
+ vkGetImageMemoryRequirements;
vkGetImageSparseMemoryRequirements2; # introduced=28
- vkGetImageSubresourceLayout;
+ vkGetImageSparseMemoryRequirements;
+ vkGetImageSubresourceLayout2; #introduced=36
vkGetImageSubresourceLayout2EXT; # introduced=UpsideDownCake
+ vkGetImageSubresourceLayout;
vkGetInstanceProcAddr;
vkGetMemoryAndroidHardwareBufferANDROID; # introduced=28
vkGetPhysicalDeviceExternalBufferProperties; # introduced=28
vkGetPhysicalDeviceExternalFenceProperties; # introduced=28
vkGetPhysicalDeviceExternalSemaphoreProperties; # introduced=28
- vkGetPhysicalDeviceFeatures;
vkGetPhysicalDeviceFeatures2; # introduced=28
- vkGetPhysicalDeviceFormatProperties;
+ vkGetPhysicalDeviceFeatures;
vkGetPhysicalDeviceFormatProperties2; # introduced=28
- vkGetPhysicalDeviceImageFormatProperties;
+ vkGetPhysicalDeviceFormatProperties;
vkGetPhysicalDeviceImageFormatProperties2; # introduced=28
- vkGetPhysicalDeviceMemoryProperties;
+ vkGetPhysicalDeviceImageFormatProperties;
vkGetPhysicalDeviceMemoryProperties2; # introduced=28
+ vkGetPhysicalDeviceMemoryProperties;
vkGetPhysicalDevicePresentRectanglesKHR; # introduced=28
- vkGetPhysicalDeviceProperties;
vkGetPhysicalDeviceProperties2; # introduced=28
- vkGetPhysicalDeviceQueueFamilyProperties;
+ vkGetPhysicalDeviceProperties;
vkGetPhysicalDeviceQueueFamilyProperties2; # introduced=28
- vkGetPhysicalDeviceSparseImageFormatProperties;
+ vkGetPhysicalDeviceQueueFamilyProperties;
vkGetPhysicalDeviceSparseImageFormatProperties2; # introduced=28
+ vkGetPhysicalDeviceSparseImageFormatProperties;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR;
vkGetPhysicalDeviceSurfaceFormatsKHR;
vkGetPhysicalDeviceSurfacePresentModesKHR;
@@ -208,15 +222,17 @@
vkGetPrivateData; #introduced=33
vkGetQueryPoolResults;
vkGetRenderAreaGranularity;
+ vkGetRenderingAreaGranularity; #introduced=36
vkGetSemaphoreCounterValue; # introduced=31
vkGetSwapchainImagesKHR;
vkInvalidateMappedMemoryRanges;
+ vkMapMemory2; #introduced=36
vkMapMemory;
vkMergePipelineCaches;
vkQueueBindSparse;
vkQueuePresentKHR;
- vkQueueSubmit;
vkQueueSubmit2; #introduced=33
+ vkQueueSubmit;
vkQueueWaitIdle;
vkResetCommandBuffer;
vkResetCommandPool;
@@ -227,10 +243,12 @@
vkSetEvent;
vkSetPrivateData; # introduced=33
vkSignalSemaphore; # introduced=31
+ vkTransitionImageLayout; #introduced=36
vkTrimCommandPool; # introduced=28
+ vkUnmapMemory2; #introduced=36
vkUnmapMemory;
- vkUpdateDescriptorSets;
vkUpdateDescriptorSetWithTemplate; # introduced=28
+ vkUpdateDescriptorSets;
vkWaitForFences;
vkWaitSemaphores; # introduced=31
local:
diff --git a/vulkan/libvulkan/libvulkan_flags.aconfig b/vulkan/libvulkan/libvulkan_flags.aconfig
index 891bc02..dae5b52 100644
--- a/vulkan/libvulkan/libvulkan_flags.aconfig
+++ b/vulkan/libvulkan/libvulkan_flags.aconfig
@@ -8,3 +8,11 @@
bug: "341978292"
is_fixed_read_only: true
}
+
+flag {
+ name: "vulkan_1_4_instance_api"
+ namespace: "core_graphics"
+ description: "Enable support for the Vulkan 1.4 instance API"
+ bug: "370568136"
+ is_fixed_read_only: true
+}
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 09b0a14..5e2b55e 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -1413,6 +1413,119 @@
allocator->pfnFree(allocator->pUserData, swapchain);
}
+static VkResult getProducerUsageGPDIFP2(
+ const VkPhysicalDevice& pdev,
+ const VkSwapchainCreateInfoKHR* create_info,
+ const VkSwapchainImageUsageFlagsANDROID swapchain_image_usage,
+ bool create_protected_swapchain,
+ uint64_t* producer_usage) {
+ // Look through the create_info pNext chain passed to createSwapchainKHR
+ // for an image compression control struct.
+ // if one is found AND the appropriate extensions are enabled, create a
+ // VkImageCompressionControlEXT structure to pass on to
+ // GetPhysicalDeviceImageFormatProperties2
+ void* compression_control_pNext = nullptr;
+ VkImageCompressionControlEXT image_compression = {};
+ const VkSwapchainCreateInfoKHR* create_infos = create_info;
+ while (create_infos->pNext) {
+ create_infos = reinterpret_cast<const VkSwapchainCreateInfoKHR*>(
+ create_infos->pNext);
+ switch (create_infos->sType) {
+ case VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT: {
+ const VkImageCompressionControlEXT* compression_infos =
+ reinterpret_cast<const VkImageCompressionControlEXT*>(
+ create_infos);
+ image_compression = *compression_infos;
+ image_compression.pNext = nullptr;
+ compression_control_pNext = &image_compression;
+ } break;
+ default:
+ // Ignore all other info structs
+ break;
+ }
+ }
+
+ // call GetPhysicalDeviceImageFormatProperties2KHR
+ VkPhysicalDeviceExternalImageFormatInfo external_image_format_info = {
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
+ .pNext = compression_control_pNext,
+ .handleType =
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
+ };
+
+ // AHB does not have an sRGB format so we can't pass it to GPDIFP
+ // We need to convert the format to unorm if it is srgb
+ VkFormat format = create_info->imageFormat;
+ if (format == VK_FORMAT_R8G8B8A8_SRGB) {
+ format = VK_FORMAT_R8G8B8A8_UNORM;
+ }
+
+ VkPhysicalDeviceImageFormatInfo2 image_format_info = {
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
+ .pNext = &external_image_format_info,
+ .format = format,
+ .type = VK_IMAGE_TYPE_2D,
+ .tiling = VK_IMAGE_TILING_OPTIMAL,
+ .usage = create_info->imageUsage,
+ .flags =
+ create_protected_swapchain ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u,
+ };
+
+ // If supporting mutable format swapchain add the mutable format flag
+ if (create_info->flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR) {
+ image_format_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
+ image_format_info.flags |= VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR;
+ }
+
+ VkAndroidHardwareBufferUsageANDROID ahb_usage;
+ ahb_usage.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID;
+ ahb_usage.pNext = nullptr;
+
+ VkImageFormatProperties2 image_format_properties;
+ image_format_properties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
+ image_format_properties.pNext = &ahb_usage;
+
+ VkResult result = GetPhysicalDeviceImageFormatProperties2(
+ pdev, &image_format_info, &image_format_properties);
+ if (result != VK_SUCCESS) {
+ ALOGE(
+ "VkGetPhysicalDeviceImageFormatProperties2 for AHB usage "
+ "failed: %d",
+ result);
+ return VK_ERROR_SURFACE_LOST_KHR;
+ }
+ // Determine if USAGE_FRONT_BUFFER is needed.
+ // GPDIFP2 has no means of using VkSwapchainImageUsageFlagsANDROID when
+ // querying for producer_usage. So androidHardwareBufferUsage will not
+ // contain USAGE_FRONT_BUFFER. We need to manually check for usage here.
+ if (!(swapchain_image_usage &
+ VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID)) {
+ *producer_usage = ahb_usage.androidHardwareBufferUsage;
+ return VK_SUCCESS;
+ }
+
+ // Check if USAGE_FRONT_BUFFER is supported for this swapchain
+ AHardwareBuffer_Desc ahb_desc = {
+ .width = create_info->imageExtent.width,
+ .height = create_info->imageExtent.height,
+ .layers = create_info->imageArrayLayers,
+ .format = create_info->imageFormat,
+ .usage = ahb_usage.androidHardwareBufferUsage |
+ AHARDWAREBUFFER_USAGE_FRONT_BUFFER,
+ .stride = 0, // stride is always ignored when calling isSupported()
+ };
+
+ // If FRONT_BUFFER is not supported in the GPDIFP2 path
+ // then we need to fallback to GetSwapchainGrallocUsageXAndroid
+ if (AHardwareBuffer_isSupported(&ahb_desc)) {
+ *producer_usage = ahb_usage.androidHardwareBufferUsage;
+ *producer_usage |= AHARDWAREBUFFER_USAGE_FRONT_BUFFER;
+ return VK_SUCCESS;
+ }
+
+ return VK_ERROR_FORMAT_NOT_SUPPORTED;
+}
+
static VkResult getProducerUsage(const VkDevice& device,
const VkSwapchainCreateInfoKHR* create_info,
const VkSwapchainImageUsageFlagsANDROID swapchain_image_usage,
@@ -1422,106 +1535,16 @@
const VkPhysicalDevice& pdev = GetData(device).driver_physical_device;
const InstanceData& instance_data = GetData(pdev);
const InstanceDriverTable& instance_dispatch = instance_data.driver;
+
if (instance_dispatch.GetPhysicalDeviceImageFormatProperties2 ||
instance_dispatch.GetPhysicalDeviceImageFormatProperties2KHR) {
- // Look through the create_info pNext chain passed to createSwapchainKHR
- // for an image compression control struct.
- // if one is found AND the appropriate extensions are enabled, create a
- // VkImageCompressionControlEXT structure to pass on to
- // GetPhysicalDeviceImageFormatProperties2
- void* compression_control_pNext = nullptr;
- VkImageCompressionControlEXT image_compression = {};
- const VkSwapchainCreateInfoKHR* create_infos = create_info;
- while (create_infos->pNext) {
- create_infos = reinterpret_cast<const VkSwapchainCreateInfoKHR*>(create_infos->pNext);
- switch (create_infos->sType) {
- case VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT: {
- const VkImageCompressionControlEXT* compression_infos =
- reinterpret_cast<const VkImageCompressionControlEXT*>(create_infos);
- image_compression = *compression_infos;
- image_compression.pNext = nullptr;
- compression_control_pNext = &image_compression;
- } break;
- default:
- // Ignore all other info structs
- break;
- }
- }
-
- // call GetPhysicalDeviceImageFormatProperties2KHR
- VkPhysicalDeviceExternalImageFormatInfo external_image_format_info = {
- .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
- .pNext = compression_control_pNext,
- .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
- };
-
- // AHB does not have an sRGB format so we can't pass it to GPDIFP
- // We need to convert the format to unorm if it is srgb
- VkFormat format = create_info->imageFormat;
- if (format == VK_FORMAT_R8G8B8A8_SRGB) {
- format = VK_FORMAT_R8G8B8A8_UNORM;
- }
-
- VkPhysicalDeviceImageFormatInfo2 image_format_info = {
- .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
- .pNext = &external_image_format_info,
- .format = format,
- .type = VK_IMAGE_TYPE_2D,
- .tiling = VK_IMAGE_TILING_OPTIMAL,
- .usage = create_info->imageUsage,
- .flags = create_protected_swapchain ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u,
- };
-
- // If supporting mutable format swapchain add the mutable format flag
- if (create_info->flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR) {
- image_format_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
- image_format_info.flags |= VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR;
- }
-
- VkAndroidHardwareBufferUsageANDROID ahb_usage;
- ahb_usage.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID;
- ahb_usage.pNext = nullptr;
-
- VkImageFormatProperties2 image_format_properties;
- image_format_properties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
- image_format_properties.pNext = &ahb_usage;
-
- VkResult result = GetPhysicalDeviceImageFormatProperties2(
- pdev, &image_format_info, &image_format_properties);
- if (result != VK_SUCCESS) {
- ALOGE(
- "VkGetPhysicalDeviceImageFormatProperties2 for AHB usage "
- "failed: %d",
- result);
- return VK_ERROR_SURFACE_LOST_KHR;
- }
-
- // Determine if USAGE_FRONT_BUFFER is needed.
- // GPDIFP2 has no means of using VkSwapchainImageUsageFlagsANDROID when
- // querying for producer_usage. So androidHardwareBufferUsage will not
- // contain USAGE_FRONT_BUFFER. We need to manually check for usage here.
- if (!(swapchain_image_usage & VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID)) {
- *producer_usage = ahb_usage.androidHardwareBufferUsage;
+ VkResult result =
+ getProducerUsageGPDIFP2(pdev, create_info, swapchain_image_usage,
+ create_protected_swapchain, producer_usage);
+ if (result == VK_SUCCESS) {
return VK_SUCCESS;
}
-
- // Check if USAGE_FRONT_BUFFER is supported for this swapchain
- AHardwareBuffer_Desc ahb_desc = {
- .width = create_info->imageExtent.width,
- .height = create_info->imageExtent.height,
- .layers = create_info->imageArrayLayers,
- .format = create_info->imageFormat,
- .usage = ahb_usage.androidHardwareBufferUsage | AHARDWAREBUFFER_USAGE_FRONT_BUFFER,
- .stride = 0, // stride is always ignored when calling isSupported()
- };
-
- // If FRONT_BUFFER is not supported,
- // then we need to call GetSwapchainGrallocUsageXAndroid below
- if (AHardwareBuffer_isSupported(&ahb_desc)) {
- *producer_usage = ahb_usage.androidHardwareBufferUsage;
- *producer_usage |= AHARDWAREBUFFER_USAGE_FRONT_BUFFER;
- return VK_SUCCESS;
- }
+ // Fall through to gralloc path on error
}
uint64_t native_usage = 0;
diff --git a/vulkan/nulldrv/null_driver.cpp b/vulkan/nulldrv/null_driver.cpp
index 973e71c..48de3d6 100644
--- a/vulkan/nulldrv/null_driver.cpp
+++ b/vulkan/nulldrv/null_driver.cpp
@@ -1767,6 +1767,69 @@
return VK_SUCCESS;
}
+void GetRenderingAreaGranularity(VkDevice device, const VkRenderingAreaInfo* pRenderingAreaInfo, VkExtent2D* pGranularity) {
+}
+
+void CmdPushDescriptorSet(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites) {
+}
+
+void CmdPushDescriptorSetWithTemplate(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData) {
+}
+
+void CmdSetLineStipple(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern) {
+}
+
+void CmdBindIndexBuffer2(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size, VkIndexType indexType) {
+}
+
+VkResult CopyMemoryToImage(VkDevice device, const VkCopyMemoryToImageInfo* pCopyMemoryToImageInfo) {
+ return VK_SUCCESS;
+}
+
+VkResult CopyImageToMemory(VkDevice device, const VkCopyImageToMemoryInfo* pCopyImageToMemoryInfo) {
+ return VK_SUCCESS;
+}
+
+VkResult CopyImageToImage(VkDevice device, const VkCopyImageToImageInfo* pCopyImageToImageInfo) {
+ return VK_SUCCESS;
+}
+
+VkResult TransitionImageLayout(VkDevice device, uint32_t transitionCount, const VkHostImageLayoutTransitionInfo* pTransitions) {
+ return VK_SUCCESS;
+}
+
+void GetImageSubresourceLayout2(VkDevice device, VkImage image, const VkImageSubresource2* pSubresource, VkSubresourceLayout2* pLayout) {
+}
+
+void GetDeviceImageSubresourceLayout(VkDevice device, const VkDeviceImageSubresourceInfo* pInfo, VkSubresourceLayout2* pLayout) {
+}
+
+VkResult MapMemory2(VkDevice device, const VkMemoryMapInfo* pMemoryMapInfo, void** ppData) {
+ return VK_SUCCESS;
+}
+
+VkResult UnmapMemory2(VkDevice device, const VkMemoryUnmapInfo* pMemoryUnmapInfo) {
+ return VK_SUCCESS;
+}
+
+void CmdBindDescriptorSets2(VkCommandBuffer commandBuffer, const VkBindDescriptorSetsInfo* pBindDescriptorSetsInfo) {
+}
+
+void CmdPushConstants2(VkCommandBuffer commandBuffer, const VkPushConstantsInfo* pPushConstantsInfo) {
+}
+
+void CmdPushDescriptorSet2(VkCommandBuffer commandBuffer, const VkPushDescriptorSetInfo* pPushDescriptorSetInfo) {
+}
+
+void CmdPushDescriptorSetWithTemplate2(VkCommandBuffer commandBuffer, const VkPushDescriptorSetWithTemplateInfo* pPushDescriptorSetWithTemplateInfo) {
+}
+
+void CmdSetRenderingAttachmentLocations(VkCommandBuffer commandBuffer, const VkRenderingAttachmentLocationInfo* pLocationInfo) {
+}
+
+void CmdSetRenderingInputAttachmentIndices(VkCommandBuffer commandBuffer, const VkRenderingInputAttachmentIndexInfo* pInputAttachmentIndexInfo) {
+}
+
#pragma clang diagnostic pop
// clang-format on
diff --git a/vulkan/nulldrv/null_driver_gen.cpp b/vulkan/nulldrv/null_driver_gen.cpp
index 40a45af..30967c2 100644
--- a/vulkan/nulldrv/null_driver_gen.cpp
+++ b/vulkan/nulldrv/null_driver_gen.cpp
@@ -75,7 +75,9 @@
{"vkCmdBeginRenderPass2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBeginRenderPass2>(CmdBeginRenderPass2))},
{"vkCmdBeginRendering", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBeginRendering>(CmdBeginRendering))},
{"vkCmdBindDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBindDescriptorSets>(CmdBindDescriptorSets))},
+ {"vkCmdBindDescriptorSets2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBindDescriptorSets2>(CmdBindDescriptorSets2))},
{"vkCmdBindIndexBuffer", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBindIndexBuffer>(CmdBindIndexBuffer))},
+ {"vkCmdBindIndexBuffer2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBindIndexBuffer2>(CmdBindIndexBuffer2))},
{"vkCmdBindPipeline", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBindPipeline>(CmdBindPipeline))},
{"vkCmdBindVertexBuffers", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBindVertexBuffers>(CmdBindVertexBuffers))},
{"vkCmdBindVertexBuffers2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBindVertexBuffers2>(CmdBindVertexBuffers2))},
@@ -113,6 +115,11 @@
{"vkCmdPipelineBarrier", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdPipelineBarrier>(CmdPipelineBarrier))},
{"vkCmdPipelineBarrier2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdPipelineBarrier2>(CmdPipelineBarrier2))},
{"vkCmdPushConstants", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdPushConstants>(CmdPushConstants))},
+ {"vkCmdPushConstants2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdPushConstants2>(CmdPushConstants2))},
+ {"vkCmdPushDescriptorSet", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdPushDescriptorSet>(CmdPushDescriptorSet))},
+ {"vkCmdPushDescriptorSet2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdPushDescriptorSet2>(CmdPushDescriptorSet2))},
+ {"vkCmdPushDescriptorSetWithTemplate", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdPushDescriptorSetWithTemplate>(CmdPushDescriptorSetWithTemplate))},
+ {"vkCmdPushDescriptorSetWithTemplate2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdPushDescriptorSetWithTemplate2>(CmdPushDescriptorSetWithTemplate2))},
{"vkCmdResetEvent", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdResetEvent>(CmdResetEvent))},
{"vkCmdResetEvent2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdResetEvent2>(CmdResetEvent2))},
{"vkCmdResetQueryPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdResetQueryPool>(CmdResetQueryPool))},
@@ -131,10 +138,13 @@
{"vkCmdSetEvent", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetEvent>(CmdSetEvent))},
{"vkCmdSetEvent2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetEvent2>(CmdSetEvent2))},
{"vkCmdSetFrontFace", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetFrontFace>(CmdSetFrontFace))},
+ {"vkCmdSetLineStipple", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetLineStipple>(CmdSetLineStipple))},
{"vkCmdSetLineWidth", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetLineWidth>(CmdSetLineWidth))},
{"vkCmdSetPrimitiveRestartEnable", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetPrimitiveRestartEnable>(CmdSetPrimitiveRestartEnable))},
{"vkCmdSetPrimitiveTopology", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetPrimitiveTopology>(CmdSetPrimitiveTopology))},
{"vkCmdSetRasterizerDiscardEnable", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetRasterizerDiscardEnable>(CmdSetRasterizerDiscardEnable))},
+ {"vkCmdSetRenderingAttachmentLocations", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetRenderingAttachmentLocations>(CmdSetRenderingAttachmentLocations))},
+ {"vkCmdSetRenderingInputAttachmentIndices", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetRenderingInputAttachmentIndices>(CmdSetRenderingInputAttachmentIndices))},
{"vkCmdSetScissor", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetScissor>(CmdSetScissor))},
{"vkCmdSetScissorWithCount", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetScissorWithCount>(CmdSetScissorWithCount))},
{"vkCmdSetStencilCompareMask", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetStencilCompareMask>(CmdSetStencilCompareMask))},
@@ -149,6 +159,9 @@
{"vkCmdWaitEvents2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdWaitEvents2>(CmdWaitEvents2))},
{"vkCmdWriteTimestamp", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdWriteTimestamp>(CmdWriteTimestamp))},
{"vkCmdWriteTimestamp2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdWriteTimestamp2>(CmdWriteTimestamp2))},
+ {"vkCopyImageToImage", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCopyImageToImage>(CopyImageToImage))},
+ {"vkCopyImageToMemory", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCopyImageToMemory>(CopyImageToMemory))},
+ {"vkCopyMemoryToImage", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCopyMemoryToImage>(CopyMemoryToImage))},
{"vkCreateBuffer", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateBuffer>(CreateBuffer))},
{"vkCreateBufferView", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateBufferView>(CreateBufferView))},
{"vkCreateCommandPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateCommandPool>(CreateCommandPool))},
@@ -222,6 +235,7 @@
{"vkGetDeviceGroupPeerMemoryFeatures", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceGroupPeerMemoryFeatures>(GetDeviceGroupPeerMemoryFeatures))},
{"vkGetDeviceImageMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceImageMemoryRequirements>(GetDeviceImageMemoryRequirements))},
{"vkGetDeviceImageSparseMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceImageSparseMemoryRequirements>(GetDeviceImageSparseMemoryRequirements))},
+ {"vkGetDeviceImageSubresourceLayout", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceImageSubresourceLayout>(GetDeviceImageSubresourceLayout))},
{"vkGetDeviceMemoryCommitment", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceMemoryCommitment>(GetDeviceMemoryCommitment))},
{"vkGetDeviceMemoryOpaqueCaptureAddress", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceMemoryOpaqueCaptureAddress>(GetDeviceMemoryOpaqueCaptureAddress))},
{"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceProcAddr>(GetDeviceProcAddr))},
@@ -234,6 +248,7 @@
{"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))},
+ {"vkGetImageSubresourceLayout2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetImageSubresourceLayout2>(GetImageSubresourceLayout2))},
{"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))},
@@ -264,6 +279,7 @@
{"vkGetPrivateData", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPrivateData>(GetPrivateData))},
{"vkGetQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetQueryPoolResults>(GetQueryPoolResults))},
{"vkGetRenderAreaGranularity", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetRenderAreaGranularity>(GetRenderAreaGranularity))},
+ {"vkGetRenderingAreaGranularity", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetRenderingAreaGranularity>(GetRenderingAreaGranularity))},
{"vkGetSemaphoreCounterValue", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetSemaphoreCounterValue>(GetSemaphoreCounterValue))},
{"vkGetSwapchainGrallocUsage2ANDROID", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetSwapchainGrallocUsage2ANDROID>(GetSwapchainGrallocUsage2ANDROID))},
{"vkGetSwapchainGrallocUsage3ANDROID", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetSwapchainGrallocUsage3ANDROID>(GetSwapchainGrallocUsage3ANDROID))},
@@ -271,6 +287,7 @@
{"vkGetSwapchainGrallocUsageANDROID", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetSwapchainGrallocUsageANDROID>(GetSwapchainGrallocUsageANDROID))},
{"vkInvalidateMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkInvalidateMappedMemoryRanges>(InvalidateMappedMemoryRanges))},
{"vkMapMemory", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkMapMemory>(MapMemory))},
+ {"vkMapMemory2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkMapMemory2>(MapMemory2))},
{"vkMergePipelineCaches", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkMergePipelineCaches>(MergePipelineCaches))},
{"vkQueueBindSparse", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkQueueBindSparse>(QueueBindSparse))},
{"vkQueueSignalReleaseImageANDROID", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkQueueSignalReleaseImageANDROID>(QueueSignalReleaseImageANDROID))},
@@ -286,8 +303,10 @@
{"vkSetEvent", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkSetEvent>(SetEvent))},
{"vkSetPrivateData", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkSetPrivateData>(SetPrivateData))},
{"vkSignalSemaphore", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkSignalSemaphore>(SignalSemaphore))},
+ {"vkTransitionImageLayout", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkTransitionImageLayout>(TransitionImageLayout))},
{"vkTrimCommandPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkTrimCommandPool>(TrimCommandPool))},
{"vkUnmapMemory", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkUnmapMemory>(UnmapMemory))},
+ {"vkUnmapMemory2", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkUnmapMemory2>(UnmapMemory2))},
{"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))},
diff --git a/vulkan/nulldrv/null_driver_gen.h b/vulkan/nulldrv/null_driver_gen.h
index 0d1e223..f609e7e 100644
--- a/vulkan/nulldrv/null_driver_gen.h
+++ b/vulkan/nulldrv/null_driver_gen.h
@@ -118,6 +118,7 @@
VKAPI_ATTR VkResult CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass);
VKAPI_ATTR void DestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator);
VKAPI_ATTR void GetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity);
+VKAPI_ATTR void GetRenderingAreaGranularity(VkDevice device, const VkRenderingAreaInfo* pRenderingAreaInfo, VkExtent2D* pGranularity);
VKAPI_ATTR VkResult CreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool);
VKAPI_ATTR void DestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator);
VKAPI_ATTR VkResult ResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags);
@@ -187,6 +188,7 @@
VKAPI_ATTR void GetPhysicalDeviceMemoryProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties);
VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2* pProperties);
+VKAPI_ATTR void CmdPushDescriptorSet(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites);
VKAPI_ATTR void TrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags);
VKAPI_ATTR void GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties);
VKAPI_ATTR void GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VkExternalSemaphoreProperties* pExternalSemaphoreProperties);
@@ -200,6 +202,7 @@
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 CmdPushDescriptorSetWithTemplate(VkCommandBuffer commandBuffer, VkDescriptorUpdateTemplate descriptorUpdateTemplate, VkPipelineLayout layout, uint32_t set, const void* pData);
VKAPI_ATTR void GetBufferMemoryRequirements2(VkDevice device, const VkBufferMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
VKAPI_ATTR void GetImageMemoryRequirements2(VkDevice device, const VkImageMemoryRequirementsInfo2* pInfo, VkMemoryRequirements2* pMemoryRequirements);
VKAPI_ATTR void GetImageSparseMemoryRequirements2(VkDevice device, const VkImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2* pSparseMemoryRequirements);
@@ -228,12 +231,14 @@
VKAPI_ATTR uint64_t GetBufferOpaqueCaptureAddress(VkDevice device, const VkBufferDeviceAddressInfo* pInfo);
VKAPI_ATTR VkDeviceAddress GetBufferDeviceAddress(VkDevice device, const VkBufferDeviceAddressInfo* pInfo);
VKAPI_ATTR uint64_t GetDeviceMemoryOpaqueCaptureAddress(VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo);
+VKAPI_ATTR void CmdSetLineStipple(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor, uint16_t lineStipplePattern);
VKAPI_ATTR VkResult GetPhysicalDeviceToolProperties(VkPhysicalDevice physicalDevice, uint32_t* pToolCount, VkPhysicalDeviceToolProperties* pToolProperties);
VKAPI_ATTR void CmdSetCullMode(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode);
VKAPI_ATTR void CmdSetFrontFace(VkCommandBuffer commandBuffer, VkFrontFace frontFace);
VKAPI_ATTR void CmdSetPrimitiveTopology(VkCommandBuffer commandBuffer, VkPrimitiveTopology primitiveTopology);
VKAPI_ATTR void CmdSetViewportWithCount(VkCommandBuffer commandBuffer, uint32_t viewportCount, const VkViewport* pViewports);
VKAPI_ATTR void CmdSetScissorWithCount(VkCommandBuffer commandBuffer, uint32_t scissorCount, const VkRect2D* pScissors);
+VKAPI_ATTR void CmdBindIndexBuffer2(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size, VkIndexType indexType);
VKAPI_ATTR void CmdBindVertexBuffers2(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes, const VkDeviceSize* pStrides);
VKAPI_ATTR void CmdSetDepthTestEnable(VkCommandBuffer commandBuffer, VkBool32 depthTestEnable);
VKAPI_ATTR void CmdSetDepthWriteEnable(VkCommandBuffer commandBuffer, VkBool32 depthWriteEnable);
@@ -260,8 +265,22 @@
VKAPI_ATTR void CmdPipelineBarrier2(VkCommandBuffer commandBuffer, const VkDependencyInfo* pDependencyInfo);
VKAPI_ATTR VkResult QueueSubmit2(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2* pSubmits, VkFence fence);
VKAPI_ATTR void CmdWriteTimestamp2(VkCommandBuffer commandBuffer, VkPipelineStageFlags2 stage, VkQueryPool queryPool, uint32_t query);
+VKAPI_ATTR VkResult CopyMemoryToImage(VkDevice device, const VkCopyMemoryToImageInfo* pCopyMemoryToImageInfo);
+VKAPI_ATTR VkResult CopyImageToMemory(VkDevice device, const VkCopyImageToMemoryInfo* pCopyImageToMemoryInfo);
+VKAPI_ATTR VkResult CopyImageToImage(VkDevice device, const VkCopyImageToImageInfo* pCopyImageToImageInfo);
+VKAPI_ATTR VkResult TransitionImageLayout(VkDevice device, uint32_t transitionCount, const VkHostImageLayoutTransitionInfo* pTransitions);
VKAPI_ATTR void CmdBeginRendering(VkCommandBuffer commandBuffer, const VkRenderingInfo* pRenderingInfo);
VKAPI_ATTR void CmdEndRendering(VkCommandBuffer commandBuffer);
+VKAPI_ATTR void GetImageSubresourceLayout2(VkDevice device, VkImage image, const VkImageSubresource2* pSubresource, VkSubresourceLayout2* pLayout);
+VKAPI_ATTR void GetDeviceImageSubresourceLayout(VkDevice device, const VkDeviceImageSubresourceInfo* pInfo, VkSubresourceLayout2* pLayout);
+VKAPI_ATTR VkResult MapMemory2(VkDevice device, const VkMemoryMapInfo* pMemoryMapInfo, void** ppData);
+VKAPI_ATTR VkResult UnmapMemory2(VkDevice device, const VkMemoryUnmapInfo* pMemoryUnmapInfo);
+VKAPI_ATTR void CmdBindDescriptorSets2(VkCommandBuffer commandBuffer, const VkBindDescriptorSetsInfo* pBindDescriptorSetsInfo);
+VKAPI_ATTR void CmdPushConstants2(VkCommandBuffer commandBuffer, const VkPushConstantsInfo* pPushConstantsInfo);
+VKAPI_ATTR void CmdPushDescriptorSet2(VkCommandBuffer commandBuffer, const VkPushDescriptorSetInfo* pPushDescriptorSetInfo);
+VKAPI_ATTR void CmdPushDescriptorSetWithTemplate2(VkCommandBuffer commandBuffer, const VkPushDescriptorSetWithTemplateInfo* pPushDescriptorSetWithTemplateInfo);
+VKAPI_ATTR void CmdSetRenderingAttachmentLocations(VkCommandBuffer commandBuffer, const VkRenderingAttachmentLocationInfo* pLocationInfo);
+VKAPI_ATTR void CmdSetRenderingInputAttachmentIndices(VkCommandBuffer commandBuffer, const VkRenderingInputAttachmentIndexInfo* pInputAttachmentIndexInfo);
// clang-format on
} // namespace null_driver
diff --git a/vulkan/scripts/generator_common.py b/vulkan/scripts/generator_common.py
index 6b4cbad..aa1e7f2 100644
--- a/vulkan/scripts/generator_common.py
+++ b/vulkan/scripts/generator_common.py
@@ -379,6 +379,9 @@
version_dict[cmd_name] = apiversion
for feature in root.iter('feature'):
+ # hack, 'feature' element has multiple meanings.. should be more precise with path match
+ if feature.get('api') is None:
+ continue
if 'vulkan' not in feature.get('api').split(','):
continue
diff --git a/vulkan/tests/Android.bp b/vulkan/tests/Android.bp
new file mode 100644
index 0000000..db218c1
--- /dev/null
+++ b/vulkan/tests/Android.bp
@@ -0,0 +1,57 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
+cc_test {
+ name: "libvulkan_test",
+ test_suites: ["general-tests"],
+
+ srcs: [
+ "libvulkan_test.cpp",
+ ],
+
+ strip: {
+ none: true,
+ },
+
+ cflags: [
+ "-DVK_USE_PLATFORM_ANDROID_KHR",
+ "-Wall",
+ "-Werror",
+ ],
+
+ header_libs: [
+ "hwvulkan_headers",
+ "libvulkanprivate_headers-testing",
+ "vulkan_headers",
+ ],
+
+ cppflags: [
+ "-Wno-c++98-compat-pedantic",
+ "-Wno-c99-extensions",
+ "-Wno-exit-time-destructors",
+ "-Wno-float-equal",
+ "-Wno-global-constructors",
+ "-Wno-zero-length-array",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libgraphicsenv",
+ "liblog",
+ "libmediandk",
+ "libvulkan",
+ ],
+
+ static_libs: [
+ "libgmock",
+ "libgtest",
+ "liblog",
+ ],
+
+}
diff --git a/vulkan/tests/README.md b/vulkan/tests/README.md
new file mode 100644
index 0000000..3c9b66c
--- /dev/null
+++ b/vulkan/tests/README.md
@@ -0,0 +1,24 @@
+#libvulkan_test
+
+This binary contains the unit tests for testing libvulkan (The Vulkan Loader).
+
+These tests rely on the underlying GPU driver to be able to successfully create a valid
+swapchain. These tests are design to run on an Android emulator to give us a consistent GPU
+driver to test against. YMMV when running this on a physical device with an arbitrary GPU
+driver.
+
+To run these tests run:
+```
+atest libvulkan_test
+```
+
+If using an acloud device the full command list for the root of a freshly cloned repo would be:
+```
+source build/envsetup.sh
+lunch aosp_cf_x86_64_phone-trunk_staging-eng
+m
+acloud create --local-image
+atest libvulkan_test
+```
+
+
diff --git a/vulkan/tests/libvulkan_test.cpp b/vulkan/tests/libvulkan_test.cpp
new file mode 100644
index 0000000..7e4bfd8
--- /dev/null
+++ b/vulkan/tests/libvulkan_test.cpp
@@ -0,0 +1,607 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/log.h>
+#include <driver.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <media/NdkImageReader.h>
+#include <vulkan/vulkan.h>
+
+#define LOGI(...) \
+ __android_log_print(ANDROID_LOG_INFO, "libvulkan_test", __VA_ARGS__)
+#define LOGE(...) \
+ __android_log_print(ANDROID_LOG_ERROR, "libvulkan_test", __VA_ARGS__)
+
+#define VK_CHECK(result) ASSERT_EQ(VK_SUCCESS, result)
+
+namespace android {
+
+namespace libvulkantest {
+
+class AImageReaderVulkanSwapchainTest : public ::testing::Test {
+ public:
+ AImageReaderVulkanSwapchainTest() {}
+
+ AImageReader* mReader = nullptr;
+ ANativeWindow* mWindow = nullptr;
+ VkInstance mVkInstance = VK_NULL_HANDLE;
+ VkPhysicalDevice mPhysicalDev = VK_NULL_HANDLE;
+ VkDevice mDevice = VK_NULL_HANDLE;
+ VkSurfaceKHR mSurface = VK_NULL_HANDLE;
+ VkQueue mPresentQueue = VK_NULL_HANDLE;
+ uint32_t mPresentQueueFamily = UINT32_MAX;
+ VkSwapchainKHR mSwapchain = VK_NULL_HANDLE;
+
+ void SetUp() override {}
+
+ void TearDown() override {}
+
+ // ------------------------------------------------------
+ // Helper methods
+ // ------------------------------------------------------
+
+ void createVulkanInstance(std::vector<const char*>& layers) {
+ const char* extensions[] = {
+ VK_KHR_SURFACE_EXTENSION_NAME,
+ VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
+ VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
+ VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
+ };
+
+ VkApplicationInfo appInfo{};
+ appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
+ appInfo.pApplicationName = "AImageReader Vulkan Swapchain Test";
+ appInfo.applicationVersion = 1;
+ appInfo.pEngineName = "TestEngine";
+ appInfo.engineVersion = 1;
+ appInfo.apiVersion = VK_API_VERSION_1_0;
+
+ VkInstanceCreateInfo instInfo{};
+ instInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+ instInfo.pApplicationInfo = &appInfo;
+ instInfo.enabledExtensionCount =
+ sizeof(extensions) / sizeof(extensions[0]);
+ instInfo.ppEnabledExtensionNames = extensions;
+ instInfo.enabledLayerCount = layers.size();
+ instInfo.ppEnabledLayerNames = layers.data();
+ VkResult res = vkCreateInstance(&instInfo, nullptr, &mVkInstance);
+ VK_CHECK(res);
+ LOGE("Vulkan instance created");
+ }
+
+ void createAImageReader(int width, int height, int format, int maxImages) {
+ media_status_t status =
+ AImageReader_new(width, height, format, maxImages, &mReader);
+ ASSERT_EQ(AMEDIA_OK, status) << "Failed to create AImageReader";
+ ASSERT_NE(nullptr, mReader) << "AImageReader is null";
+
+ // Optionally set a listener
+ AImageReader_ImageListener listener{};
+ listener.context = this;
+ listener.onImageAvailable =
+ &AImageReaderVulkanSwapchainTest::onImageAvailable;
+ AImageReader_setImageListener(mReader, &listener);
+
+ LOGI("AImageReader created with %dx%d, format=%d", width, height,
+ format);
+ }
+
+ void getANativeWindowFromReader() {
+ ASSERT_NE(nullptr, mReader);
+
+ media_status_t status = AImageReader_getWindow(mReader, &mWindow);
+ ASSERT_EQ(AMEDIA_OK, status)
+ << "Failed to get ANativeWindow from AImageReader";
+ ASSERT_NE(nullptr, mWindow) << "ANativeWindow is null";
+ LOGI("ANativeWindow obtained from AImageReader");
+ }
+
+ void createVulkanSurface() {
+ ASSERT_NE((VkInstance)VK_NULL_HANDLE, mVkInstance);
+ ASSERT_NE((ANativeWindow*)nullptr, mWindow);
+
+ VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo{};
+ surfaceCreateInfo.sType =
+ VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
+ surfaceCreateInfo.window = mWindow;
+
+ VkResult res = vkCreateAndroidSurfaceKHR(
+ mVkInstance, &surfaceCreateInfo, nullptr, &mSurface);
+ VK_CHECK(res);
+ LOGI("Vulkan surface created from ANativeWindow");
+ }
+
+ void pickPhysicalDeviceAndQueueFamily() {
+ ASSERT_NE((VkInstance)VK_NULL_HANDLE, mVkInstance);
+
+ uint32_t deviceCount = 0;
+ vkEnumeratePhysicalDevices(mVkInstance, &deviceCount, nullptr);
+ ASSERT_GT(deviceCount, 0U) << "No Vulkan physical devices found!";
+
+ std::vector<VkPhysicalDevice> devices(deviceCount);
+ vkEnumeratePhysicalDevices(mVkInstance, &deviceCount, devices.data());
+
+ for (auto& dev : devices) {
+ uint32_t queueFamilyCount = 0;
+ vkGetPhysicalDeviceQueueFamilyProperties(dev, &queueFamilyCount,
+ nullptr);
+ std::vector<VkQueueFamilyProperties> queueProps(queueFamilyCount);
+ vkGetPhysicalDeviceQueueFamilyProperties(dev, &queueFamilyCount,
+ queueProps.data());
+
+ for (uint32_t i = 0; i < queueFamilyCount; i++) {
+ VkBool32 support = VK_FALSE;
+ vkGetPhysicalDeviceSurfaceSupportKHR(dev, i, mSurface,
+ &support);
+ if (support == VK_TRUE) {
+ // Found a queue family that can present
+ mPhysicalDev = dev;
+ mPresentQueueFamily = i;
+
+ LOGI(
+ "Physical device found with queue family %u supporting "
+ "present",
+ i);
+ return;
+ }
+ }
+ }
+
+ FAIL()
+ << "No physical device found that supports present to the surface!";
+ }
+
+ void createDeviceAndGetQueue(std::vector<const char*>& layers,
+ std::vector<const char*> inExtensions = {}) {
+ ASSERT_NE((void*)VK_NULL_HANDLE, mPhysicalDev);
+ ASSERT_NE(UINT32_MAX, mPresentQueueFamily);
+
+ float queuePriority = 1.0f;
+ VkDeviceQueueCreateInfo queueInfo{};
+ queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ queueInfo.queueFamilyIndex = mPresentQueueFamily;
+ queueInfo.queueCount = 1;
+ queueInfo.pQueuePriorities = &queuePriority;
+
+ VkDeviceCreateInfo deviceInfo{};
+ deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+ deviceInfo.queueCreateInfoCount = 1;
+ deviceInfo.pQueueCreateInfos = &queueInfo;
+ deviceInfo.enabledLayerCount = layers.size();
+ deviceInfo.ppEnabledLayerNames = layers.data();
+
+ std::vector<const char*> extensions = {
+ VK_KHR_SWAPCHAIN_EXTENSION_NAME,
+ };
+ for (auto extension : inExtensions) {
+ extensions.push_back(extension);
+ }
+ deviceInfo.enabledExtensionCount = extensions.size();
+ deviceInfo.ppEnabledExtensionNames = extensions.data();
+
+ VkResult res =
+ vkCreateDevice(mPhysicalDev, &deviceInfo, nullptr, &mDevice);
+ VK_CHECK(res);
+ LOGI("Logical device created");
+
+ vkGetDeviceQueue(mDevice, mPresentQueueFamily, 0, &mPresentQueue);
+ ASSERT_NE((VkQueue)VK_NULL_HANDLE, mPresentQueue);
+ LOGI("Acquired present-capable queue");
+ }
+
+ void createSwapchain() {
+ ASSERT_NE((VkDevice)VK_NULL_HANDLE, mDevice);
+ ASSERT_NE((VkSurfaceKHR)VK_NULL_HANDLE, mSurface);
+
+ VkSurfaceCapabilitiesKHR surfaceCaps{};
+ VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
+ mPhysicalDev, mSurface, &surfaceCaps));
+
+ uint32_t formatCount = 0;
+ vkGetPhysicalDeviceSurfaceFormatsKHR(mPhysicalDev, mSurface,
+ &formatCount, nullptr);
+ ASSERT_GT(formatCount, 0U);
+ std::vector<VkSurfaceFormatKHR> formats(formatCount);
+ vkGetPhysicalDeviceSurfaceFormatsKHR(mPhysicalDev, mSurface,
+ &formatCount, formats.data());
+
+ VkSurfaceFormatKHR chosenFormat = formats[0];
+ LOGI("Chosen surface format: %d", chosenFormat.format);
+
+ uint32_t presentModeCount = 0;
+ vkGetPhysicalDeviceSurfacePresentModesKHR(mPhysicalDev, mSurface,
+ &presentModeCount, nullptr);
+ ASSERT_GT(presentModeCount, 0U);
+ std::vector<VkPresentModeKHR> presentModes(presentModeCount);
+ vkGetPhysicalDeviceSurfacePresentModesKHR(
+ mPhysicalDev, mSurface, &presentModeCount, presentModes.data());
+
+ VkPresentModeKHR chosenPresentMode = VK_PRESENT_MODE_FIFO_KHR;
+ for (auto mode : presentModes) {
+ if (mode == VK_PRESENT_MODE_FIFO_KHR) {
+ chosenPresentMode = mode;
+ break;
+ }
+ }
+ LOGI("Chosen present mode: %d", chosenPresentMode);
+
+ VkExtent2D swapchainExtent{};
+ if (surfaceCaps.currentExtent.width == 0xFFFFFFFF) {
+ swapchainExtent.width = 640; // fallback
+ swapchainExtent.height = 480; // fallback
+ } else {
+ swapchainExtent = surfaceCaps.currentExtent;
+ }
+ LOGI("Swapchain extent: %d x %d", swapchainExtent.width,
+ swapchainExtent.height);
+
+ uint32_t desiredImageCount = surfaceCaps.minImageCount + 1;
+ if (surfaceCaps.maxImageCount > 0 &&
+ desiredImageCount > surfaceCaps.maxImageCount) {
+ desiredImageCount = surfaceCaps.maxImageCount;
+ }
+
+ VkSwapchainCreateInfoKHR swapchainInfo{};
+ swapchainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
+ swapchainInfo.surface = mSurface;
+ swapchainInfo.minImageCount = desiredImageCount;
+ swapchainInfo.imageFormat = chosenFormat.format;
+ swapchainInfo.imageColorSpace = chosenFormat.colorSpace;
+ swapchainInfo.imageExtent = swapchainExtent;
+ swapchainInfo.imageArrayLayers = 1;
+ swapchainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+ swapchainInfo.preTransform = surfaceCaps.currentTransform;
+ swapchainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
+ swapchainInfo.presentMode = chosenPresentMode;
+ swapchainInfo.clipped = VK_TRUE;
+ swapchainInfo.oldSwapchain = VK_NULL_HANDLE;
+
+ uint32_t queueFamilyIndices[] = {mPresentQueueFamily};
+ swapchainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ swapchainInfo.queueFamilyIndexCount = 1;
+ swapchainInfo.pQueueFamilyIndices = queueFamilyIndices;
+
+ VkResult res =
+ vkCreateSwapchainKHR(mDevice, &swapchainInfo, nullptr, &mSwapchain);
+ if (res == VK_SUCCESS) {
+ LOGI("Swapchain created successfully");
+
+ uint32_t swapchainImageCount = 0;
+ vkGetSwapchainImagesKHR(mDevice, mSwapchain, &swapchainImageCount,
+ nullptr);
+ std::vector<VkImage> swapchainImages(swapchainImageCount);
+ vkGetSwapchainImagesKHR(mDevice, mSwapchain, &swapchainImageCount,
+ swapchainImages.data());
+
+ LOGI("Swapchain has %u images", swapchainImageCount);
+ } else {
+ LOGI("Swapchain creation failed");
+ }
+ }
+
+ // Image available callback (AImageReader)
+ static void onImageAvailable(void*, AImageReader* reader) {
+ LOGI("onImageAvailable callback triggered");
+ AImage* image = nullptr;
+ media_status_t status = AImageReader_acquireLatestImage(reader, &image);
+ if (status != AMEDIA_OK || !image) {
+ LOGE("Failed to acquire latest image");
+ return;
+ }
+ AImage_delete(image);
+ LOGI("Released acquired image");
+ }
+
+ void cleanUpSwapchainForTest() {
+ if (mSwapchain != VK_NULL_HANDLE) {
+ vkDestroySwapchainKHR(mDevice, mSwapchain, nullptr);
+ mSwapchain = VK_NULL_HANDLE;
+ }
+ if (mDevice != VK_NULL_HANDLE) {
+ vkDestroyDevice(mDevice, nullptr);
+ mDevice = VK_NULL_HANDLE;
+ }
+ if (mSurface != VK_NULL_HANDLE) {
+ vkDestroySurfaceKHR(mVkInstance, mSurface, nullptr);
+ mSurface = VK_NULL_HANDLE;
+ }
+ if (mVkInstance != VK_NULL_HANDLE) {
+ vkDestroyInstance(mVkInstance, nullptr);
+ mVkInstance = VK_NULL_HANDLE;
+ }
+ if (mReader) {
+ // AImageReader_delete(mReader);
+ mReader = nullptr;
+ }
+ // Note: The ANativeWindow from AImageReader is implicitly
+ // managed by the reader, so we don't explicitly delete it.
+ mWindow = nullptr;
+ }
+
+ void buildSwapchianForTest(std::vector<const char*>& instanceLayers,
+ std::vector<const char*>& deviceLayers) {
+ createVulkanInstance(instanceLayers);
+
+ // the "atest libvulkan_test" command will execute this test as a binary
+ // (not apk) on the device. Consequently we can't render to the screen
+ // and need to work around this by using AImageReader*
+ createAImageReader(640, 480, AIMAGE_FORMAT_PRIVATE, 3);
+ getANativeWindowFromReader();
+ createVulkanSurface();
+ pickPhysicalDeviceAndQueueFamily();
+
+ createDeviceAndGetQueue(deviceLayers);
+ createSwapchain();
+ }
+};
+
+TEST_F(AImageReaderVulkanSwapchainTest, TestHelperMethods) {
+ // Verify that the basic plumbing/helper functions of these tests is
+ // working. This doesn't directly test any of the layer code. It only
+ // verifies that we can successfully create a swapchain with an AImageReader
+
+ std::vector<const char*> instanceLayers;
+ std::vector<const char*> deviceLayers;
+ buildSwapchianForTest(deviceLayers, instanceLayers);
+
+ ASSERT_NE(mVkInstance, (VkInstance)VK_NULL_HANDLE);
+ ASSERT_NE(mPhysicalDev, (VkPhysicalDevice)VK_NULL_HANDLE);
+ ASSERT_NE(mDevice, (VkDevice)VK_NULL_HANDLE);
+ ASSERT_NE(mSurface, (VkSurfaceKHR)VK_NULL_HANDLE);
+ ASSERT_NE(mSwapchain, (VkSwapchainKHR)VK_NULL_HANDLE);
+ cleanUpSwapchainForTest();
+}
+
+// Passing state in these tests requires global state. Wrap each test in an
+// anonymous namespace to prevent conflicting names.
+namespace {
+
+VKAPI_ATTR VkResult VKAPI_CALL hookedGetPhysicalDeviceImageFormatProperties2KHR(
+ VkPhysicalDevice,
+ const VkPhysicalDeviceImageFormatInfo2*,
+ VkImageFormatProperties2*) {
+ return VK_ERROR_SURFACE_LOST_KHR;
+}
+
+static PFN_vkGetSwapchainGrallocUsage2ANDROID
+ pfnNextGetSwapchainGrallocUsage2ANDROID = nullptr;
+
+static bool g_grallocCalled = false;
+
+VKAPI_ATTR VkResult VKAPI_CALL hookGetSwapchainGrallocUsage2ANDROID(
+ VkDevice device,
+ VkFormat format,
+ VkImageUsageFlags imageUsage,
+ VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
+ uint64_t* grallocConsumerUsage,
+ uint64_t* grallocProducerUsage) {
+ g_grallocCalled = true;
+ if (pfnNextGetSwapchainGrallocUsage2ANDROID) {
+ return pfnNextGetSwapchainGrallocUsage2ANDROID(
+ device, format, imageUsage, swapchainImageUsage,
+ grallocConsumerUsage, grallocProducerUsage);
+ }
+
+ return VK_ERROR_INITIALIZATION_FAILED;
+}
+
+TEST_F(AImageReaderVulkanSwapchainTest, getProducerUsageFallbackTest1) {
+ // BUG: 379230826
+ // Verify that getProducerUsage falls back to
+ // GetSwapchainGrallocUsage*ANDROID if GPDIFP2 fails
+ std::vector<const char*> instanceLayers = {};
+ std::vector<const char*> deviceLayers = {};
+ createVulkanInstance(instanceLayers);
+
+ createAImageReader(640, 480, AIMAGE_FORMAT_PRIVATE, 3);
+ getANativeWindowFromReader();
+ createVulkanSurface();
+ pickPhysicalDeviceAndQueueFamily();
+
+ createDeviceAndGetQueue(deviceLayers);
+ auto& pdev = vulkan::driver::GetData(mDevice).driver_physical_device;
+ auto& pdevDispatchTable = vulkan::driver::GetData(pdev).driver;
+ auto& deviceDispatchTable = vulkan::driver::GetData(mDevice).driver;
+
+ ASSERT_NE(deviceDispatchTable.GetSwapchainGrallocUsage2ANDROID, nullptr);
+
+ pdevDispatchTable.GetPhysicalDeviceImageFormatProperties2 =
+ hookedGetPhysicalDeviceImageFormatProperties2KHR;
+ deviceDispatchTable.GetSwapchainGrallocUsage2ANDROID =
+ hookGetSwapchainGrallocUsage2ANDROID;
+
+ ASSERT_FALSE(g_grallocCalled);
+
+ createSwapchain();
+
+ ASSERT_TRUE(g_grallocCalled);
+
+ ASSERT_NE(mVkInstance, (VkInstance)VK_NULL_HANDLE);
+ ASSERT_NE(mPhysicalDev, (VkPhysicalDevice)VK_NULL_HANDLE);
+ ASSERT_NE(mDevice, (VkDevice)VK_NULL_HANDLE);
+ ASSERT_NE(mSurface, (VkSurfaceKHR)VK_NULL_HANDLE);
+ cleanUpSwapchainForTest();
+}
+
+} // namespace
+
+// Passing state in these tests requires global state. Wrap each test in an
+// anonymous namespace to prevent conflicting names.
+namespace {
+
+static bool g_returnNotSupportedOnce = true;
+
+VKAPI_ATTR VkResult VKAPI_CALL
+Hook_GetPhysicalDeviceImageFormatProperties2_NotSupportedOnce(
+ VkPhysicalDevice /*physicalDevice*/,
+ const VkPhysicalDeviceImageFormatInfo2* /*pImageFormatInfo*/,
+ VkImageFormatProperties2* /*pImageFormatProperties*/) {
+ if (g_returnNotSupportedOnce) {
+ g_returnNotSupportedOnce = false;
+ return VK_ERROR_FORMAT_NOT_SUPPORTED;
+ }
+ return VK_SUCCESS;
+}
+
+TEST_F(AImageReaderVulkanSwapchainTest, SurfaceFormats2KHR_IgnoreNotSupported) {
+ // BUG: 357903074
+ // Verify that vkGetPhysicalDeviceSurfaceFormats2KHR properly
+ // ignores VK_ERROR_FORMAT_NOT_SUPPORTED and continues enumerating formats.
+ std::vector<const char*> instanceLayers;
+ createVulkanInstance(instanceLayers);
+ createAImageReader(640, 480, AIMAGE_FORMAT_PRIVATE, 3);
+ getANativeWindowFromReader();
+ createVulkanSurface();
+ pickPhysicalDeviceAndQueueFamily();
+
+ auto& pdevDispatchTable = vulkan::driver::GetData(mPhysicalDev).driver;
+ pdevDispatchTable.GetPhysicalDeviceImageFormatProperties2 =
+ Hook_GetPhysicalDeviceImageFormatProperties2_NotSupportedOnce;
+
+ PFN_vkGetPhysicalDeviceSurfaceFormats2KHR
+ pfnGetPhysicalDeviceSurfaceFormats2KHR =
+ reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormats2KHR>(
+ vkGetInstanceProcAddr(mVkInstance,
+ "vkGetPhysicalDeviceSurfaceFormats2KHR"));
+ ASSERT_NE(nullptr, pfnGetPhysicalDeviceSurfaceFormats2KHR)
+ << "Could not get pointer to vkGetPhysicalDeviceSurfaceFormats2KHR";
+
+ VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo2{};
+ surfaceInfo2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR;
+ surfaceInfo2.pNext = nullptr;
+ surfaceInfo2.surface = mSurface;
+
+ uint32_t formatCount = 0;
+ VkResult res = pfnGetPhysicalDeviceSurfaceFormats2KHR(
+ mPhysicalDev, &surfaceInfo2, &formatCount, nullptr);
+
+ // If the loader never tries a second format, it might fail or 0-out the
+ // formatCount. The patch ensures it continues to the next format rather
+ // than bailing out on the first NOT_SUPPORTED.
+ ASSERT_EQ(VK_SUCCESS, res)
+ << "vkGetPhysicalDeviceSurfaceFormats2KHR failed unexpectedly";
+ ASSERT_GT(formatCount, 0U)
+ << "No surface formats found; the loader may have bailed early.";
+
+ std::vector<VkSurfaceFormat2KHR> formats(formatCount);
+ for (auto& f : formats) {
+ f.sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR;
+ f.pNext = nullptr;
+ }
+ res = pfnGetPhysicalDeviceSurfaceFormats2KHR(mPhysicalDev, &surfaceInfo2,
+ &formatCount, formats.data());
+ ASSERT_EQ(VK_SUCCESS, res) << "Failed to retrieve surface formats";
+
+ LOGI(
+ "SurfaceFormats2KHR_IgnoreNotSupported test: found %u formats after "
+ "ignoring NOT_SUPPORTED",
+ formatCount);
+
+ cleanUpSwapchainForTest();
+}
+
+} // namespace
+
+namespace {
+
+TEST_F(AImageReaderVulkanSwapchainTest, MutableFormatSwapchainTest) {
+ // Test swapchain with mutable format extension
+ std::vector<const char*> instanceLayers;
+ std::vector<const char*> deviceLayers;
+ std::vector<const char*> deviceExtensions = {
+ VK_KHR_SWAPCHAIN_EXTENSION_NAME,
+ VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME,
+ VK_KHR_MAINTENANCE2_EXTENSION_NAME,
+ VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME};
+
+ createVulkanInstance(instanceLayers);
+ createAImageReader(640, 480, AIMAGE_FORMAT_PRIVATE, 3);
+ getANativeWindowFromReader();
+ createVulkanSurface();
+ pickPhysicalDeviceAndQueueFamily();
+ createDeviceAndGetQueue(deviceLayers, deviceExtensions);
+
+ ASSERT_NE((VkDevice)VK_NULL_HANDLE, mDevice);
+ ASSERT_NE((VkSurfaceKHR)VK_NULL_HANDLE, mSurface);
+
+ VkSurfaceCapabilitiesKHR surfaceCaps{};
+ VK_CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(mPhysicalDev, mSurface,
+ &surfaceCaps));
+
+ uint32_t formatCount = 0;
+ vkGetPhysicalDeviceSurfaceFormatsKHR(mPhysicalDev, mSurface, &formatCount,
+ nullptr);
+ ASSERT_GT(formatCount, 0U);
+ std::vector<VkSurfaceFormatKHR> formats(formatCount);
+ vkGetPhysicalDeviceSurfaceFormatsKHR(mPhysicalDev, mSurface, &formatCount,
+ formats.data());
+
+ VkFormat viewFormats[2] = {formats[0].format, formats[0].format};
+ if (formatCount > 1) {
+ viewFormats[1] = formats[1].format;
+ }
+
+ VkImageFormatListCreateInfoKHR formatList{};
+ formatList.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR;
+ formatList.viewFormatCount = 2;
+ formatList.pViewFormats = viewFormats;
+
+ VkSwapchainCreateInfoKHR swapchainInfo{};
+ swapchainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
+ swapchainInfo.pNext = &formatList;
+ swapchainInfo.surface = mSurface;
+ swapchainInfo.minImageCount = surfaceCaps.minImageCount + 1;
+ swapchainInfo.imageFormat = formats[0].format;
+ swapchainInfo.imageColorSpace = formats[0].colorSpace;
+ swapchainInfo.imageExtent = surfaceCaps.currentExtent;
+ swapchainInfo.imageArrayLayers = 1;
+ swapchainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ swapchainInfo.preTransform = surfaceCaps.currentTransform;
+ swapchainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
+ swapchainInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR;
+ swapchainInfo.clipped = VK_TRUE;
+
+ swapchainInfo.flags = VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR;
+
+ uint32_t queueFamilyIndices[] = {mPresentQueueFamily};
+ swapchainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ swapchainInfo.queueFamilyIndexCount = 1;
+ swapchainInfo.pQueueFamilyIndices = queueFamilyIndices;
+
+ VkResult res =
+ vkCreateSwapchainKHR(mDevice, &swapchainInfo, nullptr, &mSwapchain);
+ if (res == VK_SUCCESS) {
+ LOGI("Mutable format swapchain created successfully");
+
+ uint32_t imageCount = 0;
+ vkGetSwapchainImagesKHR(mDevice, mSwapchain, &imageCount, nullptr);
+ ASSERT_GT(imageCount, 0U);
+ } else {
+ LOGI(
+ "Mutable format swapchain creation failed (extension may not be "
+ "supported)");
+ }
+
+ cleanUpSwapchainForTest();
+}
+
+} // namespace
+
+} // namespace libvulkantest
+
+} // namespace android
diff --git a/vulkan/vkjson/vkjson.cc b/vulkan/vkjson/vkjson.cc
index 0284192..18fef2b 100644
--- a/vulkan/vkjson/vkjson.cc
+++ b/vulkan/vkjson/vkjson.cc
@@ -38,6 +38,12 @@
namespace {
+/*
+ * Annotation to tell clang that we intend to fall through from one case to
+ * another in a switch. Sourced from android-base/macros.h.
+ */
+#define FALLTHROUGH_INTENDED [[clang::fallthrough]]
+
inline bool IsIntegral(double value) {
#if defined(ANDROID)
// Android NDK doesn't provide std::trunc yet
@@ -400,6 +406,78 @@
}
};
+template <>
+struct EnumTraits<VkPipelineRobustnessBufferBehavior> {
+ static bool exist(uint32_t e) {
+ switch (e) {
+ case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT:
+ case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED:
+ case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS:
+ case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2:
+ return true;
+ }
+ return false;
+ }
+};
+
+template <>
+struct EnumTraits<VkPipelineRobustnessImageBehavior> {
+ static bool exist(uint32_t e) {
+ switch (e) {
+ case VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DEVICE_DEFAULT:
+ case VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DISABLED:
+ case VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS:
+ case VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_2:
+ return true;
+ }
+ return false;
+ }
+};
+
+template <>
+struct EnumTraits<VkImageLayout> {
+ static bool exist(uint32_t e) {
+ switch (e) {
+ case VK_IMAGE_LAYOUT_UNDEFINED:
+ case VK_IMAGE_LAYOUT_GENERAL:
+ case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
+ case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
+ case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
+ case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
+ case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
+ case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
+ case VK_IMAGE_LAYOUT_PREINITIALIZED:
+ case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
+ case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
+ case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL:
+ case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL:
+ case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL:
+ case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL:
+ case VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL:
+ case VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL:
+ case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
+ case VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR:
+ case VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR:
+ case VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR:
+ case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR:
+ case VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT:
+ case VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR:
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+ case VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR:
+#endif
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+ case VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR:
+#endif
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+ case VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR:
+#endif
+ case VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT:
+ return true;
+ }
+ return false;
+ }
+};
+
// VkSparseImageFormatProperties
template <typename Visitor>
@@ -810,6 +888,68 @@
visitor->Visit("shaderIntegerDotProduct", &features->shaderIntegerDotProduct) &&
visitor->Visit("maintenance4", &features->maintenance4);
}
+
+template <typename Visitor>
+inline bool Iterate(Visitor* visitor, VkJsonCore14* core) {
+ return
+ visitor->Visit("features", &core->features) &&
+ visitor->Visit("properties", &core->properties);
+}
+
+template <typename Visitor>
+inline bool Iterate(Visitor* visitor, VkPhysicalDeviceVulkan14Properties* properties) {
+ return
+ visitor->Visit("lineSubPixelPrecisionBits", &properties->lineSubPixelPrecisionBits) &&
+ visitor->Visit("maxVertexAttribDivisor", &properties->maxVertexAttribDivisor) &&
+ visitor->Visit("supportsNonZeroFirstInstance", &properties->supportsNonZeroFirstInstance) &&
+ visitor->Visit("maxPushDescriptors", &properties->maxPushDescriptors) &&
+ visitor->Visit("dynamicRenderingLocalReadDepthStencilAttachments", &properties->dynamicRenderingLocalReadDepthStencilAttachments) &&
+ visitor->Visit("dynamicRenderingLocalReadMultisampledAttachments", &properties->dynamicRenderingLocalReadMultisampledAttachments) &&
+ visitor->Visit("earlyFragmentMultisampleCoverageAfterSampleCounting", &properties->earlyFragmentMultisampleCoverageAfterSampleCounting) &&
+ visitor->Visit("earlyFragmentSampleMaskTestBeforeSampleCounting", &properties->earlyFragmentSampleMaskTestBeforeSampleCounting) &&
+ visitor->Visit("depthStencilSwizzleOneSupport", &properties->depthStencilSwizzleOneSupport) &&
+ visitor->Visit("polygonModePointSize", &properties->polygonModePointSize) &&
+ visitor->Visit("nonStrictSinglePixelWideLinesUseParallelogram", &properties->nonStrictSinglePixelWideLinesUseParallelogram) &&
+ visitor->Visit("nonStrictWideLinesUseParallelogram", &properties->nonStrictWideLinesUseParallelogram) &&
+ visitor->Visit("blockTexelViewCompatibleMultipleLayers", &properties->blockTexelViewCompatibleMultipleLayers) &&
+ visitor->Visit("maxCombinedImageSamplerDescriptorCount", &properties->maxCombinedImageSamplerDescriptorCount) &&
+ visitor->Visit("fragmentShadingRateClampCombinerInputs", &properties->fragmentShadingRateClampCombinerInputs) &&
+ visitor->Visit("defaultRobustnessStorageBuffers", &properties->defaultRobustnessStorageBuffers) &&
+ visitor->Visit("defaultRobustnessUniformBuffers", &properties->defaultRobustnessUniformBuffers) &&
+ visitor->Visit("defaultRobustnessVertexInputs", &properties->defaultRobustnessVertexInputs) &&
+ visitor->Visit("defaultRobustnessImages", &properties->defaultRobustnessImages) &&
+ visitor->Visit("copySrcLayoutCount", &properties->copySrcLayoutCount) &&
+ visitor->VisitArray("pCopySrcLayouts", properties->copySrcLayoutCount, &properties->pCopySrcLayouts) &&
+ visitor->Visit("copyDstLayoutCount", &properties->copyDstLayoutCount) &&
+ visitor->VisitArray("pCopyDstLayouts", properties->copyDstLayoutCount, &properties->pCopyDstLayouts) &&
+ visitor->Visit("optimalTilingLayoutUUID", &properties->optimalTilingLayoutUUID) &&
+ visitor->Visit("identicalMemoryTypeRequirements", &properties->identicalMemoryTypeRequirements);
+}
+
+template <typename Visitor>
+inline bool Iterate(Visitor* visitor, VkPhysicalDeviceVulkan14Features* features) {
+ return
+ visitor->Visit("globalPriorityQuery", &features->globalPriorityQuery) &&
+ visitor->Visit("shaderSubgroupRotate", &features->shaderSubgroupRotate) &&
+ visitor->Visit("shaderSubgroupRotateClustered", &features->shaderSubgroupRotateClustered) &&
+ visitor->Visit("shaderFloatControls2", &features->shaderFloatControls2) &&
+ visitor->Visit("shaderExpectAssume", &features->shaderExpectAssume) &&
+ visitor->Visit("rectangularLines", &features->rectangularLines) &&
+ visitor->Visit("bresenhamLines", &features->bresenhamLines) &&
+ visitor->Visit("smoothLines", &features->smoothLines) &&
+ visitor->Visit("stippledRectangularLines", &features->stippledRectangularLines) &&
+ visitor->Visit("stippledBresenhamLines", &features->stippledBresenhamLines) &&
+ visitor->Visit("stippledSmoothLines", &features->stippledSmoothLines) &&
+ visitor->Visit("vertexAttributeInstanceRateDivisor", &features->vertexAttributeInstanceRateDivisor) &&
+ visitor->Visit("vertexAttributeInstanceRateZeroDivisor", &features->vertexAttributeInstanceRateZeroDivisor) &&
+ visitor->Visit("indexTypeUint8", &features->indexTypeUint8) &&
+ visitor->Visit("dynamicRenderingLocalRead", &features->dynamicRenderingLocalRead) &&
+ visitor->Visit("maintenance5", &features->maintenance5) &&
+ visitor->Visit("maintenance6", &features->maintenance6) &&
+ visitor->Visit("pipelineProtectedAccess", &features->pipelineProtectedAccess) &&
+ visitor->Visit("pipelineRobustness", &features->pipelineRobustness) &&
+ visitor->Visit("hostImageCopy", &features->hostImageCopy);
+}
// clang-format on
template <typename Visitor>
@@ -846,6 +986,13 @@
template <typename Visitor>
inline bool Iterate(Visitor* visitor,
+ VkJsonExtImage2DViewOf3DFeatures* features) {
+ return visitor->Visit("image2DViewOf3DFeaturesEXT",
+ &features->image_2D_view_of_3D_features_EXT);
+}
+
+template <typename Visitor>
+inline bool Iterate(Visitor* visitor,
VkJsonExtShaderFloat16Int8Features* features) {
return visitor->Visit("shaderFloat16Int8FeaturesKHR",
&features->shader_float16_int8_features_khr);
@@ -953,6 +1100,13 @@
template <typename Visitor>
inline bool Iterate(Visitor* visitor,
+ VkPhysicalDeviceImage2DViewOf3DFeaturesEXT* features) {
+ return visitor->Visit("image2DViewOf3D", &features->image2DViewOf3D) &&
+ visitor->Visit("sampler2DViewOf3D", &features->sampler2DViewOf3D);
+}
+
+template <typename Visitor>
+inline bool Iterate(Visitor* visitor,
VkPhysicalDeviceShaderFloat16Int8FeaturesKHR* features) {
return visitor->Visit("shaderFloat16", &features->shaderFloat16) &&
visitor->Visit("shaderInt8", &features->shaderInt8);
@@ -1050,6 +1204,9 @@
bool ret = true;
switch (device->properties.apiVersion ^
VK_API_VERSION_PATCH(device->properties.apiVersion)) {
+ case VK_API_VERSION_1_4:
+ ret &= visitor->Visit("core14", &device->core14);
+ FALLTHROUGH_INTENDED;
case VK_API_VERSION_1_3:
ret &= visitor->Visit("core13", &device->core13);
FALLTHROUGH_INTENDED;
@@ -1098,6 +1255,10 @@
ret &= visitor->Visit("VK_KHR_variable_pointers",
&device->ext_variable_pointer_features);
}
+ if (device->ext_image_2d_view_of_3d_features.reported) {
+ ret &= visitor->Visit("VK_EXT_image_2d_view_of_3d",
+ &device->ext_image_2d_view_of_3d_features);
+ }
if (device->ext_shader_float16_int8_features.reported) {
ret &= visitor->Visit("VK_KHR_shader_float16_int8",
&device->ext_shader_float16_int8_features);
@@ -1110,6 +1271,8 @@
inline bool Iterate(Visitor* visitor, VkJsonInstance* instance) {
bool ret = true;
switch (instance->api_version ^ VK_API_VERSION_PATCH(instance->api_version)) {
+ case VK_API_VERSION_1_4:
+ FALLTHROUGH_INTENDED;
case VK_API_VERSION_1_3:
FALLTHROUGH_INTENDED;
case VK_API_VERSION_1_2:
@@ -1169,7 +1332,7 @@
return array;
}
-template <typename T, unsigned int N>
+template <typename T, size_t N>
inline Json::Value ToJsonValue(const T (&value)[N]) {
return ArrayToJsonValue(N, value);
}
@@ -1219,6 +1382,12 @@
return true;
}
+ template <typename T>
+ bool VisitArray(const char* key, uint32_t count, const T *value) {
+ object_[key] = ArrayToJsonValue(count, *value);
+ return true;
+ }
+
Json::Value get_object() const { return object_; }
private:
@@ -1283,6 +1452,15 @@
return true;
}
+inline bool AsValue(Json::Value* json_value, VkImageLayout* t) {
+ uint32_t value = 0;
+ if (!AsValue(json_value, &value))
+ return false;
+ if (!EnumTraits<VkImageLayout>::exist(value)) return false;
+ *t = static_cast<VkImageLayout>(value);
+ return true;
+}
+
template <typename T>
inline bool AsArray(Json::Value* json_value, uint32_t count, T* values) {
if (json_value->type() != Json::arrayValue || json_value->size() != count)
@@ -1293,7 +1471,7 @@
return true;
}
-template <typename T, unsigned int N>
+template <typename T, size_t N>
inline bool AsValue(Json::Value* json_value, T (*value)[N]) {
return AsArray(json_value, N, *value);
}
@@ -1393,6 +1571,20 @@
return false;
}
+ template <typename T>
+ bool VisitArray(const char* key, uint32_t count, T *value) {
+ Json::Value json_value = (*object_)[key];
+ if (!json_value) {
+ if (errors_)
+ *errors_ = std::string(key) + " missing.";
+ return false;
+ }
+ if (AsArray(&json_value, count, *value)) return true;
+ if (errors_)
+ *errors_ = std::string("Wrong type for ") + std::string(key) + ".";
+ return false;
+ }
+
private:
Json::Value* object_;
diff --git a/vulkan/vkjson/vkjson.h b/vulkan/vkjson/vkjson.h
index 88f6e7d..87a76c1 100644
--- a/vulkan/vkjson/vkjson.h
+++ b/vulkan/vkjson/vkjson.h
@@ -33,12 +33,6 @@
#undef max
#endif
-/*
- * Annotation to tell clang that we intend to fall through from one case to
- * another in a switch. Sourced from android-base/macros.h.
- */
-#define FALLTHROUGH_INTENDED [[clang::fallthrough]]
-
struct VkJsonLayer {
VkLayerProperties properties;
std::vector<VkExtensionProperties> extensions;
@@ -64,6 +58,16 @@
VkPhysicalDeviceVariablePointerFeaturesKHR variable_pointer_features_khr;
};
+struct VkJsonExtImage2DViewOf3DFeatures {
+ VkJsonExtImage2DViewOf3DFeatures() {
+ reported = false;
+ memset(&image_2D_view_of_3D_features_EXT, 0,
+ sizeof(VkPhysicalDeviceImage2DViewOf3DFeaturesEXT));
+ }
+ bool reported;
+ VkPhysicalDeviceImage2DViewOf3DFeaturesEXT image_2D_view_of_3D_features_EXT;
+};
+
struct VkJsonExtShaderFloat16Int8Features {
VkJsonExtShaderFloat16Int8Features() {
reported = false;
@@ -84,6 +88,11 @@
VkPhysicalDeviceVulkan13Features features;
};
+struct VkJsonCore14 {
+ VkPhysicalDeviceVulkan14Properties properties;
+ VkPhysicalDeviceVulkan14Features features;
+};
+
struct VkJsonDevice {
VkJsonDevice() {
memset(&properties, 0, sizeof(VkPhysicalDeviceProperties));
@@ -110,11 +119,13 @@
sizeof(VkPhysicalDeviceShaderDrawParameterFeatures));
memset(&core12, 0, sizeof(VkJsonCore12));
memset(&core13, 0, sizeof(VkJsonCore13));
+ memset(&core14, 0, sizeof(VkJsonCore14));
}
VkPhysicalDeviceProperties properties;
VkPhysicalDeviceFeatures features;
VkJsonExtDriverProperties ext_driver_properties;
VkJsonExtVariablePointerFeatures ext_variable_pointer_features;
+ VkJsonExtImage2DViewOf3DFeatures ext_image_2d_view_of_3d_features;
VkJsonExtShaderFloat16Int8Features ext_shader_float16_int8_features;
VkPhysicalDeviceMemoryProperties memory;
std::vector<VkQueueFamilyProperties> queues;
@@ -139,6 +150,7 @@
external_semaphore_properties;
VkJsonCore12 core12;
VkJsonCore13 core13;
+ VkJsonCore14 core14;
};
struct VkJsonDeviceGroup {
diff --git a/vulkan/vkjson/vkjson_instance.cc b/vulkan/vkjson/vkjson_instance.cc
index 0ffe7e0..04bb446 100644
--- a/vulkan/vkjson/vkjson_instance.cc
+++ b/vulkan/vkjson/vkjson_instance.cc
@@ -103,6 +103,16 @@
features.pNext =
&device.ext_variable_pointer_features.variable_pointer_features_khr;
}
+ if (HasExtension("VK_EXT_image_2d_view_of_3d", device.extensions)) {
+ device.ext_image_2d_view_of_3d_features.reported = true;
+ device.ext_image_2d_view_of_3d_features.image_2D_view_of_3D_features_EXT
+ .sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT;
+ device.ext_image_2d_view_of_3d_features.image_2D_view_of_3D_features_EXT
+ .pNext = features.pNext;
+ features.pNext = &device.ext_image_2d_view_of_3d_features
+ .image_2D_view_of_3D_features_EXT;
+ }
if (HasExtension("VK_KHR_shader_float16_int8", device.extensions)) {
device.ext_shader_float16_int8_features.reported = true;
device.ext_shader_float16_int8_features.shader_float16_int8_features_khr
@@ -292,6 +302,22 @@
vkGetPhysicalDeviceFeatures2(physical_device, &features);
}
+ if (device.properties.apiVersion >= VK_API_VERSION_1_4) {
+ device.core14.properties.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_4_PROPERTIES;
+ device.core14.properties.pNext = properties.pNext;
+ properties.pNext = &device.core14.properties;
+
+ vkGetPhysicalDeviceProperties2(physical_device, &properties);
+
+ device.core14.features.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_4_FEATURES;
+ device.core14.features.pNext = features.pNext;
+ features.pNext = &device.core14.features;
+
+ vkGetPhysicalDeviceFeatures2(physical_device, &features);
+ }
+
return device;
}
diff --git a/vulkan/vkprofiles/generated/vulkan_profiles.cpp b/vulkan/vkprofiles/generated/vulkan_profiles.cpp
index ce08b4e..d6ed1c7 100644
--- a/vulkan/vkprofiles/generated/vulkan_profiles.cpp
+++ b/vulkan/vkprofiles/generated/vulkan_profiles.cpp
@@ -150,7 +150,7 @@
VPAPI_ATTR bool isMultiple(double source, double multiple) {
double mod = std::fmod(source, multiple);
- return std::abs(mod) < 0.0001;
+ return std::abs(mod) < 0.0001;
}
VPAPI_ATTR bool isPowerOfTwo(double source) {
@@ -163,8 +163,10 @@
using PFN_vpStructFiller = void(*)(VkBaseOutStructure* p);
using PFN_vpStructComparator = bool(*)(VkBaseOutStructure* p);
-using PFN_vpStructChainerCb = void(*)(VkBaseOutStructure* p, void* pUser);
+using PFN_vpStructChainerCb = void(*)(VkBaseOutStructure* p, void* pUser);
using PFN_vpStructChainer = void(*)(VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb);
+using PFN_vpStructArrayChainerCb = void(*)(uint32_t count, VkBaseOutStructure* p, void* pUser);
+using PFN_vpStructArrayChainer = void(*)(uint32_t count, VkBaseOutStructure* p, void* pUser, PFN_vpStructArrayChainerCb pfnCb);
struct VpFeatureDesc {
PFN_vpStructFiller pfnFiller;
@@ -190,10 +192,50 @@
struct VpStructChainerDesc {
PFN_vpStructChainer pfnFeature;
PFN_vpStructChainer pfnProperty;
- PFN_vpStructChainer pfnQueueFamily;
+ PFN_vpStructArrayChainer pfnQueueFamily;
PFN_vpStructChainer pfnFormat;
};
+struct VpVideoProfileInfoDesc {
+ PFN_vpStructFiller pfnFiller;
+ PFN_vpStructComparator pfnComparator;
+};
+
+struct VpVideoCapabilityDesc {
+ PFN_vpStructFiller pfnFiller;
+ PFN_vpStructComparator pfnComparator;
+};
+
+struct VpVideoFormatDesc {
+ PFN_vpStructFiller pfnFiller;
+ PFN_vpStructComparator pfnComparator;
+};
+
+struct VpVideoProfileStructChainerDesc {
+ PFN_vpStructChainer pfnInfo;
+ PFN_vpStructChainer pfnCapability;
+ PFN_vpStructArrayChainer pfnFormat;
+};
+
+struct VpVideoProfileDesc {
+ VpVideoProfileProperties properties;
+
+ uint32_t infoStructTypeCount;
+ const VkStructureType* pInfoStructTypes;
+ VpVideoProfileInfoDesc info;
+
+ uint32_t capabilityStructTypeCount;
+ const VkStructureType* pCapabilityStructTypes;
+ VpVideoCapabilityDesc capability;
+
+ uint32_t formatStructTypeCount;
+ const VkStructureType* pFormatStructTypes;
+ uint32_t formatCount;
+ const VpVideoFormatDesc* pFormats;
+
+ VpVideoProfileStructChainerDesc chainers;
+};
+
struct VpVariantDesc {
char blockName[VP_MAX_PROFILE_NAME_SIZE];
@@ -222,6 +264,9 @@
const VpFormatDesc* pFormats;
VpStructChainerDesc chainers;
+
+ uint32_t videoProfileCount;
+ const VpVideoProfileDesc* pVideoProfiles;
};
struct VpCapabilitiesDesc {
@@ -234,7 +279,7 @@
uint32_t minApiVersion;
const detail::VpVariantDesc* pMergedCapabilities;
-
+
uint32_t requiredProfileCount;
const VpProfileProperties* pRequiredProfiles;
@@ -249,6 +294,139 @@
VPAPI_ATTR bool vpCheckFlags(const T& actual, const uint64_t expected) {
return (actual & expected) == expected;
}
+
+
+#ifdef VK_KHR_video_queue
+VPAPI_ATTR void vpForEachMatchingVideoProfiles(
+ VkVideoProfileInfoKHR* pVideoProfileInfo,
+ void* pUser,
+ PFN_vpStructChainerCb pfnCb) {
+ const VkVideoChromaSubsamplingFlagsKHR chroma_subsampling_list[] = {
+ VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR,
+ VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR,
+ VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR,
+ VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR
+ };
+ const VkVideoComponentBitDepthFlagsKHR bit_depth_list[] = {
+ VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR,
+ VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR,
+ VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR
+ };
+ for (size_t chromaSubsampling_idx = 0; chromaSubsampling_idx < std::size(chroma_subsampling_list); ++chromaSubsampling_idx) {
+ pVideoProfileInfo->chromaSubsampling = chroma_subsampling_list[chromaSubsampling_idx];
+ for (size_t lumaBitDepth_idx = 0; lumaBitDepth_idx < std::size(bit_depth_list); ++lumaBitDepth_idx) {
+ pVideoProfileInfo->lumaBitDepth = bit_depth_list[lumaBitDepth_idx];
+ for (size_t chromaBitDepth_idx = 0; chromaBitDepth_idx < std::size(bit_depth_list); ++chromaBitDepth_idx) {
+ pVideoProfileInfo->chromaBitDepth = bit_depth_list[chromaBitDepth_idx];
+ {
+ pVideoProfileInfo->pNext = nullptr;
+ pVideoProfileInfo->videoCodecOperation = VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR;
+ VkVideoDecodeH264ProfileInfoKHR var_VideoDecodeH264ProfileInfoKHR = { VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR };
+ var_VideoDecodeH264ProfileInfoKHR.pNext = pVideoProfileInfo->pNext;
+ pVideoProfileInfo->pNext = &var_VideoDecodeH264ProfileInfoKHR;
+ var_VideoDecodeH264ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_BASELINE;
+ var_VideoDecodeH264ProfileInfoKHR.pictureLayout = VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoDecodeH264ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_MAIN;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoDecodeH264ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_HIGH;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoDecodeH264ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_HIGH_444_PREDICTIVE;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoDecodeH264ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_BASELINE;
+ var_VideoDecodeH264ProfileInfoKHR.pictureLayout = VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoDecodeH264ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_MAIN;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoDecodeH264ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_HIGH;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoDecodeH264ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_HIGH_444_PREDICTIVE;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoDecodeH264ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_BASELINE;
+ var_VideoDecodeH264ProfileInfoKHR.pictureLayout = VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_SEPARATE_PLANES_BIT_KHR;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoDecodeH264ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_MAIN;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoDecodeH264ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_HIGH;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoDecodeH264ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_HIGH_444_PREDICTIVE;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ }
+ {
+ pVideoProfileInfo->pNext = nullptr;
+ pVideoProfileInfo->videoCodecOperation = VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR;
+ VkVideoDecodeH265ProfileInfoKHR var_VideoDecodeH265ProfileInfoKHR = { VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR };
+ var_VideoDecodeH265ProfileInfoKHR.pNext = pVideoProfileInfo->pNext;
+ pVideoProfileInfo->pNext = &var_VideoDecodeH265ProfileInfoKHR;
+ var_VideoDecodeH265ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H265_PROFILE_IDC_MAIN;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoDecodeH265ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H265_PROFILE_IDC_MAIN_10;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoDecodeH265ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H265_PROFILE_IDC_MAIN_STILL_PICTURE;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoDecodeH265ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H265_PROFILE_IDC_FORMAT_RANGE_EXTENSIONS;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoDecodeH265ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H265_PROFILE_IDC_SCC_EXTENSIONS;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ }
+ {
+ pVideoProfileInfo->pNext = nullptr;
+ pVideoProfileInfo->videoCodecOperation = VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR;
+ VkVideoDecodeAV1ProfileInfoKHR var_VideoDecodeAV1ProfileInfoKHR = { VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_KHR };
+ var_VideoDecodeAV1ProfileInfoKHR.pNext = pVideoProfileInfo->pNext;
+ pVideoProfileInfo->pNext = &var_VideoDecodeAV1ProfileInfoKHR;
+ var_VideoDecodeAV1ProfileInfoKHR.stdProfile = STD_VIDEO_AV1_PROFILE_MAIN;
+ var_VideoDecodeAV1ProfileInfoKHR.filmGrainSupport = VK_TRUE;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoDecodeAV1ProfileInfoKHR.stdProfile = STD_VIDEO_AV1_PROFILE_HIGH;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoDecodeAV1ProfileInfoKHR.stdProfile = STD_VIDEO_AV1_PROFILE_PROFESSIONAL;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoDecodeAV1ProfileInfoKHR.stdProfile = STD_VIDEO_AV1_PROFILE_MAIN;
+ var_VideoDecodeAV1ProfileInfoKHR.filmGrainSupport = VK_FALSE;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoDecodeAV1ProfileInfoKHR.stdProfile = STD_VIDEO_AV1_PROFILE_HIGH;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoDecodeAV1ProfileInfoKHR.stdProfile = STD_VIDEO_AV1_PROFILE_PROFESSIONAL;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ }
+ {
+ pVideoProfileInfo->pNext = nullptr;
+ pVideoProfileInfo->videoCodecOperation = VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR;
+ VkVideoEncodeH264ProfileInfoKHR var_VideoEncodeH264ProfileInfoKHR = { VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_KHR };
+ var_VideoEncodeH264ProfileInfoKHR.pNext = pVideoProfileInfo->pNext;
+ pVideoProfileInfo->pNext = &var_VideoEncodeH264ProfileInfoKHR;
+ var_VideoEncodeH264ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_BASELINE;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoEncodeH264ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_MAIN;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoEncodeH264ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_HIGH;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoEncodeH264ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H264_PROFILE_IDC_HIGH_444_PREDICTIVE;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ }
+ {
+ pVideoProfileInfo->pNext = nullptr;
+ pVideoProfileInfo->videoCodecOperation = VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR;
+ VkVideoEncodeH265ProfileInfoKHR var_VideoEncodeH265ProfileInfoKHR = { VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_INFO_KHR };
+ var_VideoEncodeH265ProfileInfoKHR.pNext = pVideoProfileInfo->pNext;
+ pVideoProfileInfo->pNext = &var_VideoEncodeH265ProfileInfoKHR;
+ var_VideoEncodeH265ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H265_PROFILE_IDC_MAIN;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoEncodeH265ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H265_PROFILE_IDC_MAIN_10;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoEncodeH265ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H265_PROFILE_IDC_MAIN_STILL_PICTURE;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoEncodeH265ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H265_PROFILE_IDC_FORMAT_RANGE_EXTENSIONS;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ var_VideoEncodeH265ProfileInfoKHR.stdProfileIdc = STD_VIDEO_H265_PROFILE_IDC_SCC_EXTENSIONS;
+ pfnCb(reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo), pUser);
+ }
+ }
+ }
+ }
+}
+#endif // VK_KHR_video_queue
#ifdef VP_ANDROID_15_minimums
namespace VP_ANDROID_15_MINIMUMS {
@@ -280,7 +458,9 @@
VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR,
};
+namespace blocks {
namespace MUST {
+
static const VkExtensionProperties instanceExtensions[] = {
VkExtensionProperties{ VK_EXT_SURFACE_MAINTENANCE_1_EXTENSION_NAME, 1 },
VkExtensionProperties{ VK_GOOGLE_SURFACELESS_QUERY_EXTENSION_NAME, 1 },
@@ -305,7 +485,7 @@
};
static const VpFeatureDesc featureDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: {
VkPhysicalDeviceFeatures2KHR* s = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
@@ -365,63 +545,63 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: {
- VkPhysicalDeviceFeatures2KHR* prettify_VkPhysicalDeviceFeatures2KHR = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.drawIndirectFirstInstance == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.drawIndirectFirstInstance == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.drawIndirectFirstInstance == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.samplerAnisotropy == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.samplerAnisotropy == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.samplerAnisotropy == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderImageGatherExtended == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderImageGatherExtended == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderImageGatherExtended == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageImageExtendedFormats == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageImageExtendedFormats == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderStorageImageExtendedFormats == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageImageReadWithoutFormat == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageImageReadWithoutFormat == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderStorageImageReadWithoutFormat == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageImageWriteWithoutFormat == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageImageWriteWithoutFormat == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderStorageImageWriteWithoutFormat == VK_TRUE");
+ VkPhysicalDeviceFeatures2KHR* s = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
+ ret = ret && (s->features.drawIndirectFirstInstance == VK_TRUE);
+ ret = ret && (s->features.samplerAnisotropy == VK_TRUE);
+ ret = ret && (s->features.shaderImageGatherExtended == VK_TRUE);
+ ret = ret && (s->features.shaderStorageImageExtendedFormats == VK_TRUE);
+ ret = ret && (s->features.shaderStorageImageReadWithoutFormat == VK_TRUE);
+ ret = ret && (s->features.shaderStorageImageWriteWithoutFormat == VK_TRUE);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES: {
- VkPhysicalDeviceVulkan12Features* prettify_VkPhysicalDeviceVulkan12Features = static_cast<VkPhysicalDeviceVulkan12Features*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceVulkan12Features->shaderFloat16 == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceVulkan12Features->shaderFloat16 == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceVulkan12Features::shaderFloat16 == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceVulkan12Features->shaderInt8 == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceVulkan12Features->shaderInt8 == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceVulkan12Features::shaderInt8 == VK_TRUE");
+ VkPhysicalDeviceVulkan12Features* s = static_cast<VkPhysicalDeviceVulkan12Features*>(static_cast<void*>(p));
+ ret = ret && (s->shaderFloat16 == VK_TRUE);
+ ret = ret && (s->shaderInt8 == VK_TRUE);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: {
- VkPhysicalDeviceCustomBorderColorFeaturesEXT* prettify_VkPhysicalDeviceCustomBorderColorFeaturesEXT = static_cast<VkPhysicalDeviceCustomBorderColorFeaturesEXT*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceCustomBorderColorFeaturesEXT->customBorderColors == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceCustomBorderColorFeaturesEXT->customBorderColors == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceCustomBorderColorFeaturesEXT::customBorderColors == VK_TRUE");
+ VkPhysicalDeviceCustomBorderColorFeaturesEXT* s = static_cast<VkPhysicalDeviceCustomBorderColorFeaturesEXT*>(static_cast<void*>(p));
+ ret = ret && (s->customBorderColors == VK_TRUE);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT: {
- VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT* prettify_VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT = static_cast<VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT->primitiveTopologyListRestart == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT->primitiveTopologyListRestart == VK_TRUE), "Unsupported feature condition: VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT::primitiveTopologyListRestart == VK_TRUE");
+ VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT* s = static_cast<VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT*>(static_cast<void*>(p));
+ ret = ret && (s->primitiveTopologyListRestart == VK_TRUE);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT: {
- VkPhysicalDeviceProvokingVertexFeaturesEXT* prettify_VkPhysicalDeviceProvokingVertexFeaturesEXT = static_cast<VkPhysicalDeviceProvokingVertexFeaturesEXT*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceProvokingVertexFeaturesEXT->provokingVertexLast == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProvokingVertexFeaturesEXT->provokingVertexLast == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceProvokingVertexFeaturesEXT::provokingVertexLast == VK_TRUE");
+ VkPhysicalDeviceProvokingVertexFeaturesEXT* s = static_cast<VkPhysicalDeviceProvokingVertexFeaturesEXT*>(static_cast<void*>(p));
+ ret = ret && (s->provokingVertexLast == VK_TRUE);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT: {
- VkPhysicalDeviceIndexTypeUint8FeaturesEXT* prettify_VkPhysicalDeviceIndexTypeUint8FeaturesEXT = static_cast<VkPhysicalDeviceIndexTypeUint8FeaturesEXT*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceIndexTypeUint8FeaturesEXT->indexTypeUint8 == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceIndexTypeUint8FeaturesEXT->indexTypeUint8 == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceIndexTypeUint8FeaturesEXT::indexTypeUint8 == VK_TRUE");
+ VkPhysicalDeviceIndexTypeUint8FeaturesEXT* s = static_cast<VkPhysicalDeviceIndexTypeUint8FeaturesEXT*>(static_cast<void*>(p));
+ ret = ret && (s->indexTypeUint8 == VK_TRUE);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_KHR: {
- VkPhysicalDeviceVertexAttributeDivisorFeaturesKHR* prettify_VkPhysicalDeviceVertexAttributeDivisorFeaturesKHR = static_cast<VkPhysicalDeviceVertexAttributeDivisorFeaturesKHR*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceVertexAttributeDivisorFeaturesKHR->vertexAttributeInstanceRateDivisor == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceVertexAttributeDivisorFeaturesKHR->vertexAttributeInstanceRateDivisor == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceVertexAttributeDivisorFeaturesKHR::vertexAttributeInstanceRateDivisor == VK_TRUE");
+ VkPhysicalDeviceVertexAttributeDivisorFeaturesKHR* s = static_cast<VkPhysicalDeviceVertexAttributeDivisorFeaturesKHR*>(static_cast<void*>(p));
+ ret = ret && (s->vertexAttributeInstanceRateDivisor == VK_TRUE);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: {
- VkPhysicalDeviceSamplerYcbcrConversionFeatures* prettify_VkPhysicalDeviceSamplerYcbcrConversionFeatures = static_cast<VkPhysicalDeviceSamplerYcbcrConversionFeatures*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceSamplerYcbcrConversionFeatures->samplerYcbcrConversion == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceSamplerYcbcrConversionFeatures->samplerYcbcrConversion == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceSamplerYcbcrConversionFeatures::samplerYcbcrConversion == VK_TRUE");
+ VkPhysicalDeviceSamplerYcbcrConversionFeatures* s = static_cast<VkPhysicalDeviceSamplerYcbcrConversionFeatures*>(static_cast<void*>(p));
+ ret = ret && (s->samplerYcbcrConversion == VK_TRUE);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES: {
- VkPhysicalDeviceShaderFloat16Int8Features* prettify_VkPhysicalDeviceShaderFloat16Int8Features = static_cast<VkPhysicalDeviceShaderFloat16Int8Features*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceShaderFloat16Int8Features->shaderFloat16 == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceShaderFloat16Int8Features->shaderFloat16 == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceShaderFloat16Int8Features::shaderFloat16 == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceShaderFloat16Int8Features->shaderInt8 == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceShaderFloat16Int8Features->shaderInt8 == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceShaderFloat16Int8Features::shaderInt8 == VK_TRUE");
+ VkPhysicalDeviceShaderFloat16Int8Features* s = static_cast<VkPhysicalDeviceShaderFloat16Int8Features*>(static_cast<void*>(p));
+ ret = ret && (s->shaderFloat16 == VK_TRUE);
+ ret = ret && (s->shaderInt8 == VK_TRUE);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES: {
- VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures* prettify_VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures = static_cast<VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures->shaderSubgroupExtendedTypes == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures->shaderSubgroupExtendedTypes == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures::shaderSubgroupExtendedTypes == VK_TRUE");
+ VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures* s = static_cast<VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures*>(static_cast<void*>(p));
+ ret = ret && (s->shaderSubgroupExtendedTypes == VK_TRUE);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES: {
- VkPhysicalDevice8BitStorageFeatures* prettify_VkPhysicalDevice8BitStorageFeatures = static_cast<VkPhysicalDevice8BitStorageFeatures*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDevice8BitStorageFeatures->storageBuffer8BitAccess == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDevice8BitStorageFeatures->storageBuffer8BitAccess == VK_TRUE), "Unsupported feature condition: VkPhysicalDevice8BitStorageFeatures::storageBuffer8BitAccess == VK_TRUE");
+ VkPhysicalDevice8BitStorageFeatures* s = static_cast<VkPhysicalDevice8BitStorageFeatures*>(static_cast<void*>(p));
+ ret = ret && (s->storageBuffer8BitAccess == VK_TRUE);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: {
- VkPhysicalDevice16BitStorageFeatures* prettify_VkPhysicalDevice16BitStorageFeatures = static_cast<VkPhysicalDevice16BitStorageFeatures*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDevice16BitStorageFeatures->storageBuffer16BitAccess == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDevice16BitStorageFeatures->storageBuffer16BitAccess == VK_TRUE), "Unsupported feature condition: VkPhysicalDevice16BitStorageFeatures::storageBuffer16BitAccess == VK_TRUE");
+ VkPhysicalDevice16BitStorageFeatures* s = static_cast<VkPhysicalDevice16BitStorageFeatures*>(static_cast<void*>(p));
+ ret = ret && (s->storageBuffer16BitAccess == VK_TRUE);
} break;
default: break;
}
@@ -430,7 +610,7 @@
};
static const VpPropertyDesc propertyDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR: {
VkPhysicalDeviceProperties2KHR* s = static_cast<VkPhysicalDeviceProperties2KHR*>(static_cast<void*>(p));
@@ -447,20 +627,20 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR: {
- VkPhysicalDeviceProperties2KHR* prettify_VkPhysicalDeviceProperties2KHR = static_cast<VkPhysicalDeviceProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxColorAttachments >= 8); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxColorAttachments >= 8), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxColorAttachments >= 8");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorSampledImages >= 128); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorSampledImages >= 128), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorSampledImages >= 128");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorSamplers >= 128); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorSamplers >= 128), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorSamplers >= 128");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorStorageBuffers >= 12); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorStorageBuffers >= 12), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorStorageBuffers >= 12");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorUniformBuffers >= 13); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorUniformBuffers >= 13), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorUniformBuffers >= 13");
+ VkPhysicalDeviceProperties2KHR* s = static_cast<VkPhysicalDeviceProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (s->properties.limits.maxColorAttachments >= 8);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorSampledImages >= 128);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorSamplers >= 128);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorStorageBuffers >= 12);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorUniformBuffers >= 13);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES: {
- VkPhysicalDeviceVulkan11Properties* prettify_VkPhysicalDeviceVulkan11Properties = static_cast<VkPhysicalDeviceVulkan11Properties*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceVulkan11Properties->subgroupSupportedOperations, (VK_SUBGROUP_FEATURE_BASIC_BIT | VK_SUBGROUP_FEATURE_VOTE_BIT | VK_SUBGROUP_FEATURE_ARITHMETIC_BIT | VK_SUBGROUP_FEATURE_BALLOT_BIT | VK_SUBGROUP_FEATURE_SHUFFLE_BIT | VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceVulkan11Properties->subgroupSupportedOperations, (VK_SUBGROUP_FEATURE_BASIC_BIT | VK_SUBGROUP_FEATURE_VOTE_BIT | VK_SUBGROUP_FEATURE_ARITHMETIC_BIT | VK_SUBGROUP_FEATURE_BALLOT_BIT | VK_SUBGROUP_FEATURE_SHUFFLE_BIT | VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT))), "Unsupported properties condition: VkPhysicalDeviceVulkan11Properties::subgroupSupportedOperations contains (VK_SUBGROUP_FEATURE_BASIC_BIT | VK_SUBGROUP_FEATURE_VOTE_BIT | VK_SUBGROUP_FEATURE_ARITHMETIC_BIT | VK_SUBGROUP_FEATURE_BALLOT_BIT | VK_SUBGROUP_FEATURE_SHUFFLE_BIT | VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT)");
+ VkPhysicalDeviceVulkan11Properties* s = static_cast<VkPhysicalDeviceVulkan11Properties*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->subgroupSupportedOperations, (VK_SUBGROUP_FEATURE_BASIC_BIT | VK_SUBGROUP_FEATURE_VOTE_BIT | VK_SUBGROUP_FEATURE_ARITHMETIC_BIT | VK_SUBGROUP_FEATURE_BALLOT_BIT | VK_SUBGROUP_FEATURE_SHUFFLE_BIT | VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT)));
} break;
default: break;
}
@@ -471,7 +651,7 @@
static const VpFormatDesc formatDesc[] = {
{
VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -481,13 +661,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -496,7 +676,7 @@
},
{
VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -506,13 +686,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -545,8 +725,8 @@
p->pNext = static_cast<VkBaseOutStructure*>(static_cast<void*>(&physicalDeviceVulkan11Properties));
pfnCb(p, pUser);
},
- [](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
- pfnCb(p, pUser);
+ [](uint32_t count, VkBaseOutStructure* p, void* pUser, PFN_vpStructArrayChainerCb pfnCb) {
+ pfnCb(count, p, pUser);
},
[](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
VkFormatProperties3KHR formatProperties3KHR{ VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR, nullptr };
@@ -554,14 +734,15 @@
pfnCb(p, pUser);
},
};
-} //namespace MUST
+} // namespace MUST
namespace primitivesGeneratedQuery {
+
static const VkExtensionProperties deviceExtensions[] = {
VkExtensionProperties{ VK_EXT_PRIMITIVES_GENERATED_QUERY_EXTENSION_NAME, 1 },
};
static const VpFeatureDesc featureDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT: {
VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT* s = static_cast<VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT*>(static_cast<void*>(p));
@@ -570,12 +751,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT: {
- VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT* prettify_VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT = static_cast<VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT->primitivesGeneratedQuery == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT->primitivesGeneratedQuery == VK_TRUE), "Unsupported feature condition: VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT::primitivesGeneratedQuery == VK_TRUE");
+ VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT* s = static_cast<VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT*>(static_cast<void*>(p));
+ ret = ret && (s->primitivesGeneratedQuery == VK_TRUE);
} break;
default: break;
}
@@ -584,9 +765,9 @@
};
static const VpPropertyDesc propertyDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
return ret;
}
@@ -616,8 +797,8 @@
p->pNext = static_cast<VkBaseOutStructure*>(static_cast<void*>(&physicalDeviceVulkan11Properties));
pfnCb(p, pUser);
},
- [](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
- pfnCb(p, pUser);
+ [](uint32_t count, VkBaseOutStructure* p, void* pUser, PFN_vpStructArrayChainerCb pfnCb) {
+ pfnCb(count, p, pUser);
},
[](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
VkFormatProperties3KHR formatProperties3KHR{ VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR, nullptr };
@@ -625,10 +806,11 @@
pfnCb(p, pUser);
},
};
-} //namespace primitivesGeneratedQuery
+} // namespace primitivesGeneratedQuery
namespace pipelineStatisticsQuery {
+
static const VpFeatureDesc featureDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: {
VkPhysicalDeviceFeatures2KHR* s = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
@@ -637,12 +819,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: {
- VkPhysicalDeviceFeatures2KHR* prettify_VkPhysicalDeviceFeatures2KHR = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.pipelineStatisticsQuery == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.pipelineStatisticsQuery == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.pipelineStatisticsQuery == VK_TRUE");
+ VkPhysicalDeviceFeatures2KHR* s = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
+ ret = ret && (s->features.pipelineStatisticsQuery == VK_TRUE);
} break;
default: break;
}
@@ -651,9 +833,9 @@
};
static const VpPropertyDesc propertyDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
return ret;
}
@@ -683,8 +865,8 @@
p->pNext = static_cast<VkBaseOutStructure*>(static_cast<void*>(&physicalDeviceVulkan11Properties));
pfnCb(p, pUser);
},
- [](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
- pfnCb(p, pUser);
+ [](uint32_t count, VkBaseOutStructure* p, void* pUser, PFN_vpStructArrayChainerCb pfnCb) {
+ pfnCb(count, p, pUser);
},
[](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
VkFormatProperties3KHR formatProperties3KHR{ VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR, nullptr };
@@ -692,14 +874,15 @@
pfnCb(p, pUser);
},
};
-} //namespace pipelineStatisticsQuery
+} // namespace pipelineStatisticsQuery
namespace swBresenhamLines {
+
static const VkExtensionProperties deviceExtensions[] = {
VkExtensionProperties{ VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME, 1 },
};
static const VpFeatureDesc featureDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT: {
VkPhysicalDeviceLineRasterizationFeaturesEXT* s = static_cast<VkPhysicalDeviceLineRasterizationFeaturesEXT*>(static_cast<void*>(p));
@@ -708,12 +891,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT: {
- VkPhysicalDeviceLineRasterizationFeaturesEXT* prettify_VkPhysicalDeviceLineRasterizationFeaturesEXT = static_cast<VkPhysicalDeviceLineRasterizationFeaturesEXT*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceLineRasterizationFeaturesEXT->bresenhamLines == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceLineRasterizationFeaturesEXT->bresenhamLines == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceLineRasterizationFeaturesEXT::bresenhamLines == VK_TRUE");
+ VkPhysicalDeviceLineRasterizationFeaturesEXT* s = static_cast<VkPhysicalDeviceLineRasterizationFeaturesEXT*>(static_cast<void*>(p));
+ ret = ret && (s->bresenhamLines == VK_TRUE);
} break;
default: break;
}
@@ -722,9 +905,9 @@
};
static const VpPropertyDesc propertyDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
return ret;
}
@@ -754,8 +937,8 @@
p->pNext = static_cast<VkBaseOutStructure*>(static_cast<void*>(&physicalDeviceVulkan11Properties));
pfnCb(p, pUser);
},
- [](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
- pfnCb(p, pUser);
+ [](uint32_t count, VkBaseOutStructure* p, void* pUser, PFN_vpStructArrayChainerCb pfnCb) {
+ pfnCb(count, p, pUser);
},
[](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
VkFormatProperties3KHR formatProperties3KHR{ VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR, nullptr };
@@ -763,14 +946,15 @@
pfnCb(p, pUser);
},
};
-} //namespace swBresenhamLines
+} // namespace swBresenhamLines
namespace hwBresenhamLines {
+
static const VkExtensionProperties deviceExtensions[] = {
VkExtensionProperties{ VK_IMG_RELAXED_LINE_RASTERIZATION_EXTENSION_NAME, 1 },
};
static const VpFeatureDesc featureDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RELAXED_LINE_RASTERIZATION_FEATURES_IMG: {
VkPhysicalDeviceRelaxedLineRasterizationFeaturesIMG* s = static_cast<VkPhysicalDeviceRelaxedLineRasterizationFeaturesIMG*>(static_cast<void*>(p));
@@ -779,12 +963,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RELAXED_LINE_RASTERIZATION_FEATURES_IMG: {
- VkPhysicalDeviceRelaxedLineRasterizationFeaturesIMG* prettify_VkPhysicalDeviceRelaxedLineRasterizationFeaturesIMG = static_cast<VkPhysicalDeviceRelaxedLineRasterizationFeaturesIMG*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceRelaxedLineRasterizationFeaturesIMG->relaxedLineRasterization == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceRelaxedLineRasterizationFeaturesIMG->relaxedLineRasterization == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceRelaxedLineRasterizationFeaturesIMG::relaxedLineRasterization == VK_TRUE");
+ VkPhysicalDeviceRelaxedLineRasterizationFeaturesIMG* s = static_cast<VkPhysicalDeviceRelaxedLineRasterizationFeaturesIMG*>(static_cast<void*>(p));
+ ret = ret && (s->relaxedLineRasterization == VK_TRUE);
} break;
default: break;
}
@@ -793,9 +977,9 @@
};
static const VpPropertyDesc propertyDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
return ret;
}
@@ -825,8 +1009,8 @@
p->pNext = static_cast<VkBaseOutStructure*>(static_cast<void*>(&physicalDeviceVulkan11Properties));
pfnCb(p, pUser);
},
- [](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
- pfnCb(p, pUser);
+ [](uint32_t count, VkBaseOutStructure* p, void* pUser, PFN_vpStructArrayChainerCb pfnCb) {
+ pfnCb(count, p, pUser);
},
[](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
VkFormatProperties3KHR formatProperties3KHR{ VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR, nullptr };
@@ -834,10 +1018,343 @@
pfnCb(p, pUser);
},
};
-} //namespace hwBresenhamLines
+} // namespace hwBresenhamLines
+} // namespace blocks
} // namespace VP_ANDROID_15_MINIMUMS
#endif // VP_ANDROID_15_minimums
+#ifdef VP_ANDROID_16_minimums
+namespace VP_ANDROID_16_MINIMUMS {
+
+static const VkStructureType featureStructTypes[] = {
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR,
+};
+
+static const VkStructureType propertyStructTypes[] = {
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES,
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES,
+};
+
+namespace blocks {
+namespace MUST {
+
+static const VkExtensionProperties deviceExtensions[] = {
+ VkExtensionProperties{ VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME, 1 },
+ VkExtensionProperties{ VK_EXT_IMAGE_2D_VIEW_OF_3D_EXTENSION_NAME, 1 },
+ VkExtensionProperties{ VK_EXT_PIPELINE_PROTECTED_ACCESS_EXTENSION_NAME, 1 },
+ VkExtensionProperties{ VK_EXT_PIPELINE_ROBUSTNESS_EXTENSION_NAME, 1 },
+ VkExtensionProperties{ VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, 1 },
+ VkExtensionProperties{ VK_KHR_8BIT_STORAGE_EXTENSION_NAME, 1 },
+ VkExtensionProperties{ VK_KHR_LOAD_STORE_OP_NONE_EXTENSION_NAME, 1 },
+ VkExtensionProperties{ VK_KHR_MAINTENANCE_6_EXTENSION_NAME, 1 },
+ VkExtensionProperties{ VK_KHR_MAP_MEMORY_2_EXTENSION_NAME, 1 },
+ VkExtensionProperties{ VK_KHR_SHADER_EXPECT_ASSUME_EXTENSION_NAME, 1 },
+ VkExtensionProperties{ VK_KHR_SHADER_FLOAT_CONTROLS_2_EXTENSION_NAME, 1 },
+ VkExtensionProperties{ VK_KHR_SHADER_MAXIMAL_RECONVERGENCE_EXTENSION_NAME, 1 },
+ VkExtensionProperties{ VK_KHR_SHADER_SUBGROUP_ROTATE_EXTENSION_NAME, 1 },
+ VkExtensionProperties{ VK_KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_EXTENSION_NAME, 1 },
+ VkExtensionProperties{ VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME, 1 },
+};
+
+static const VpFeatureDesc featureDesc = {
+ [](VkBaseOutStructure* p) { (void)p;
+ switch (p->sType) {
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: {
+ VkPhysicalDeviceFeatures2KHR* s = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
+ s->features.fullDrawIndexUint32 = VK_TRUE;
+ s->features.shaderInt16 = VK_TRUE;
+ } break;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES: {
+ VkPhysicalDeviceVulkan12Features* s = static_cast<VkPhysicalDeviceVulkan12Features*>(static_cast<void*>(p));
+ s->samplerMirrorClampToEdge = VK_TRUE;
+ s->scalarBlockLayout = VK_TRUE;
+ } break;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES: {
+ VkPhysicalDeviceProtectedMemoryFeatures* s = static_cast<VkPhysicalDeviceProtectedMemoryFeatures*>(static_cast<void*>(p));
+ s->protectedMemory = VK_TRUE;
+ } break;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES: {
+ VkPhysicalDeviceShaderIntegerDotProductFeatures* s = static_cast<VkPhysicalDeviceShaderIntegerDotProductFeatures*>(static_cast<void*>(p));
+ s->shaderIntegerDotProduct = VK_TRUE;
+ } break;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT: {
+ VkPhysicalDeviceTransformFeedbackFeaturesEXT* s = static_cast<VkPhysicalDeviceTransformFeedbackFeaturesEXT*>(static_cast<void*>(p));
+ s->transformFeedback = VK_TRUE;
+ } break;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT: {
+ VkPhysicalDeviceImage2DViewOf3DFeaturesEXT* s = static_cast<VkPhysicalDeviceImage2DViewOf3DFeaturesEXT*>(static_cast<void*>(p));
+ s->image2DViewOf3D = VK_TRUE;
+ } break;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR: {
+ VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR* s = static_cast<VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR*>(static_cast<void*>(p));
+ s->shaderSubgroupUniformControlFlow = VK_TRUE;
+ } break;
+ default: break;
+ }
+ },
+ [](VkBaseOutStructure* p) -> bool { (void)p;
+ bool ret = true;
+ switch (p->sType) {
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: {
+ VkPhysicalDeviceFeatures2KHR* s = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
+ ret = ret && (s->features.fullDrawIndexUint32 == VK_TRUE);
+ ret = ret && (s->features.shaderInt16 == VK_TRUE);
+ } break;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES: {
+ VkPhysicalDeviceVulkan12Features* s = static_cast<VkPhysicalDeviceVulkan12Features*>(static_cast<void*>(p));
+ ret = ret && (s->samplerMirrorClampToEdge == VK_TRUE);
+ ret = ret && (s->scalarBlockLayout == VK_TRUE);
+ } break;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES: {
+ VkPhysicalDeviceProtectedMemoryFeatures* s = static_cast<VkPhysicalDeviceProtectedMemoryFeatures*>(static_cast<void*>(p));
+ ret = ret && (s->protectedMemory == VK_TRUE);
+ } break;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES: {
+ VkPhysicalDeviceShaderIntegerDotProductFeatures* s = static_cast<VkPhysicalDeviceShaderIntegerDotProductFeatures*>(static_cast<void*>(p));
+ ret = ret && (s->shaderIntegerDotProduct == VK_TRUE);
+ } break;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT: {
+ VkPhysicalDeviceTransformFeedbackFeaturesEXT* s = static_cast<VkPhysicalDeviceTransformFeedbackFeaturesEXT*>(static_cast<void*>(p));
+ ret = ret && (s->transformFeedback == VK_TRUE);
+ } break;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT: {
+ VkPhysicalDeviceImage2DViewOf3DFeaturesEXT* s = static_cast<VkPhysicalDeviceImage2DViewOf3DFeaturesEXT*>(static_cast<void*>(p));
+ ret = ret && (s->image2DViewOf3D == VK_TRUE);
+ } break;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR: {
+ VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR* s = static_cast<VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR*>(static_cast<void*>(p));
+ ret = ret && (s->shaderSubgroupUniformControlFlow == VK_TRUE);
+ } break;
+ default: break;
+ }
+ return ret;
+ }
+};
+
+static const VpPropertyDesc propertyDesc = {
+ [](VkBaseOutStructure* p) { (void)p;
+ switch (p->sType) {
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR: {
+ VkPhysicalDeviceProperties2KHR* s = static_cast<VkPhysicalDeviceProperties2KHR*>(static_cast<void*>(p));
+ s->properties.limits.bufferImageGranularity = 4096;
+ s->properties.limits.lineWidthGranularity = 0.5f;
+ s->properties.limits.maxColorAttachments = 8;
+ s->properties.limits.maxComputeWorkGroupInvocations = 256;
+ s->properties.limits.maxComputeWorkGroupSize[0] = 256;
+ s->properties.limits.maxComputeWorkGroupSize[1] = 256;
+ s->properties.limits.maxComputeWorkGroupSize[2] = 64;
+ s->properties.limits.maxDescriptorSetStorageBuffers = 96;
+ s->properties.limits.maxDescriptorSetUniformBuffers = 90;
+ s->properties.limits.maxFragmentCombinedOutputResources = 16;
+ s->properties.limits.maxImageArrayLayers = 2048;
+ s->properties.limits.maxImageDimension1D = 8192;
+ s->properties.limits.maxImageDimension2D = 8192;
+ s->properties.limits.maxImageDimensionCube = 8192;
+ s->properties.limits.maxPerStageDescriptorUniformBuffers = 15;
+ s->properties.limits.maxPerStageResources = 200;
+ s->properties.limits.maxSamplerLodBias = 14;
+ s->properties.limits.maxUniformBufferRange = 65536;
+ s->properties.limits.maxVertexOutputComponents = 72;
+ s->properties.limits.mipmapPrecisionBits = 6;
+ s->properties.limits.pointSizeGranularity = 0.125f;
+ s->properties.limits.standardSampleLocations = VK_TRUE;
+ s->properties.limits.subTexelPrecisionBits = 8;
+ s->properties.limits.timestampComputeAndGraphics = VK_TRUE;
+ } break;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES: {
+ VkPhysicalDeviceFloatControlsProperties* s = static_cast<VkPhysicalDeviceFloatControlsProperties*>(static_cast<void*>(p));
+ s->shaderSignedZeroInfNanPreserveFloat16 = VK_TRUE;
+ s->shaderSignedZeroInfNanPreserveFloat32 = VK_TRUE;
+ } break;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES: {
+ VkPhysicalDeviceVulkan11Properties* s = static_cast<VkPhysicalDeviceVulkan11Properties*>(static_cast<void*>(p));
+ s->subgroupSupportedStages |= (VK_SHADER_STAGE_COMPUTE_BIT);
+ } break;
+ default: break;
+ }
+ },
+ [](VkBaseOutStructure* p) -> bool { (void)p;
+ bool ret = true;
+ switch (p->sType) {
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR: {
+ VkPhysicalDeviceProperties2KHR* s = static_cast<VkPhysicalDeviceProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (s->properties.limits.bufferImageGranularity <= 4096);
+ ret = ret && ((4096 % s->properties.limits.bufferImageGranularity) == 0);
+ ret = ret && (s->properties.limits.lineWidthGranularity <= 0.5);
+ ret = ret && (isMultiple(0.5, s->properties.limits.lineWidthGranularity));
+ ret = ret && (s->properties.limits.maxColorAttachments >= 8);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupInvocations >= 256);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupSize[0] >= 256);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupSize[1] >= 256);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupSize[2] >= 64);
+ ret = ret && (s->properties.limits.maxDescriptorSetStorageBuffers >= 96);
+ ret = ret && (s->properties.limits.maxDescriptorSetUniformBuffers >= 90);
+ ret = ret && (s->properties.limits.maxFragmentCombinedOutputResources >= 16);
+ ret = ret && (s->properties.limits.maxImageArrayLayers >= 2048);
+ ret = ret && (s->properties.limits.maxImageDimension1D >= 8192);
+ ret = ret && (s->properties.limits.maxImageDimension2D >= 8192);
+ ret = ret && (s->properties.limits.maxImageDimensionCube >= 8192);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorUniformBuffers >= 15);
+ ret = ret && (s->properties.limits.maxPerStageResources >= 200);
+ ret = ret && (s->properties.limits.maxSamplerLodBias >= 14);
+ ret = ret && (s->properties.limits.maxUniformBufferRange >= 65536);
+ ret = ret && (s->properties.limits.maxVertexOutputComponents >= 72);
+ ret = ret && (s->properties.limits.mipmapPrecisionBits >= 6);
+ ret = ret && (s->properties.limits.pointSizeGranularity <= 0.125);
+ ret = ret && (isMultiple(0.125, s->properties.limits.pointSizeGranularity));
+ ret = ret && (s->properties.limits.standardSampleLocations == VK_TRUE);
+ ret = ret && (s->properties.limits.subTexelPrecisionBits >= 8);
+ ret = ret && (vpCheckFlags(s->properties.limits.timestampComputeAndGraphics, VK_TRUE));
+ } break;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES: {
+ VkPhysicalDeviceFloatControlsProperties* s = static_cast<VkPhysicalDeviceFloatControlsProperties*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->shaderSignedZeroInfNanPreserveFloat16, VK_TRUE));
+ ret = ret && (vpCheckFlags(s->shaderSignedZeroInfNanPreserveFloat32, VK_TRUE));
+ } break;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES: {
+ VkPhysicalDeviceVulkan11Properties* s = static_cast<VkPhysicalDeviceVulkan11Properties*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->subgroupSupportedStages, (VK_SHADER_STAGE_COMPUTE_BIT)));
+ } break;
+ default: break;
+ }
+ return ret;
+ }
+};
+
+static const VpStructChainerDesc chainerDesc = {
+ [](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
+ VkPhysicalDeviceVulkan12Features physicalDeviceVulkan12Features{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, nullptr };
+ VkPhysicalDeviceProtectedMemoryFeatures physicalDeviceProtectedMemoryFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES, &physicalDeviceVulkan12Features };
+ VkPhysicalDeviceShaderIntegerDotProductFeatures physicalDeviceShaderIntegerDotProductFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES, &physicalDeviceProtectedMemoryFeatures };
+ VkPhysicalDeviceTransformFeedbackFeaturesEXT physicalDeviceTransformFeedbackFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT, &physicalDeviceShaderIntegerDotProductFeatures };
+ VkPhysicalDeviceImage2DViewOf3DFeaturesEXT physicalDeviceImage2DViewOf3DFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT, &physicalDeviceTransformFeedbackFeaturesEXT };
+ VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR physicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR, &physicalDeviceImage2DViewOf3DFeaturesEXT };
+ p->pNext = static_cast<VkBaseOutStructure*>(static_cast<void*>(&physicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR));
+ pfnCb(p, pUser);
+ },
+ [](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
+ VkPhysicalDeviceFloatControlsProperties physicalDeviceFloatControlsProperties{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES, nullptr };
+ VkPhysicalDeviceVulkan11Properties physicalDeviceVulkan11Properties{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES, &physicalDeviceFloatControlsProperties };
+ p->pNext = static_cast<VkBaseOutStructure*>(static_cast<void*>(&physicalDeviceVulkan11Properties));
+ pfnCb(p, pUser);
+ },
+ [](uint32_t count, VkBaseOutStructure* p, void* pUser, PFN_vpStructArrayChainerCb pfnCb) {
+ pfnCb(count, p, pUser);
+ },
+ [](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
+ pfnCb(p, pUser);
+ },
+};
+} // namespace MUST
+namespace multisampledToSingleSampled {
+
+static const VkExtensionProperties deviceExtensions[] = {
+ VkExtensionProperties{ VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME, 1 },
+};
+
+static const VpFeatureDesc featureDesc = {
+ [](VkBaseOutStructure* p) { (void)p;
+ },
+ [](VkBaseOutStructure* p) -> bool { (void)p;
+ bool ret = true;
+ return ret;
+ }
+};
+
+static const VpPropertyDesc propertyDesc = {
+ [](VkBaseOutStructure* p) { (void)p;
+ },
+ [](VkBaseOutStructure* p) -> bool { (void)p;
+ bool ret = true;
+ return ret;
+ }
+};
+
+static const VpStructChainerDesc chainerDesc = {
+ [](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
+ VkPhysicalDeviceVulkan12Features physicalDeviceVulkan12Features{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, nullptr };
+ VkPhysicalDeviceProtectedMemoryFeatures physicalDeviceProtectedMemoryFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES, &physicalDeviceVulkan12Features };
+ VkPhysicalDeviceShaderIntegerDotProductFeatures physicalDeviceShaderIntegerDotProductFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES, &physicalDeviceProtectedMemoryFeatures };
+ VkPhysicalDeviceTransformFeedbackFeaturesEXT physicalDeviceTransformFeedbackFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT, &physicalDeviceShaderIntegerDotProductFeatures };
+ VkPhysicalDeviceImage2DViewOf3DFeaturesEXT physicalDeviceImage2DViewOf3DFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT, &physicalDeviceTransformFeedbackFeaturesEXT };
+ VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR physicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR, &physicalDeviceImage2DViewOf3DFeaturesEXT };
+ p->pNext = static_cast<VkBaseOutStructure*>(static_cast<void*>(&physicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR));
+ pfnCb(p, pUser);
+ },
+ [](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
+ VkPhysicalDeviceFloatControlsProperties physicalDeviceFloatControlsProperties{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES, nullptr };
+ VkPhysicalDeviceVulkan11Properties physicalDeviceVulkan11Properties{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES, &physicalDeviceFloatControlsProperties };
+ p->pNext = static_cast<VkBaseOutStructure*>(static_cast<void*>(&physicalDeviceVulkan11Properties));
+ pfnCb(p, pUser);
+ },
+ [](uint32_t count, VkBaseOutStructure* p, void* pUser, PFN_vpStructArrayChainerCb pfnCb) {
+ pfnCb(count, p, pUser);
+ },
+ [](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
+ pfnCb(p, pUser);
+ },
+};
+} // namespace multisampledToSingleSampled
+namespace shaderStencilExport {
+
+static const VkExtensionProperties deviceExtensions[] = {
+ VkExtensionProperties{ VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME, 1 },
+};
+
+static const VpFeatureDesc featureDesc = {
+ [](VkBaseOutStructure* p) { (void)p;
+ },
+ [](VkBaseOutStructure* p) -> bool { (void)p;
+ bool ret = true;
+ return ret;
+ }
+};
+
+static const VpPropertyDesc propertyDesc = {
+ [](VkBaseOutStructure* p) { (void)p;
+ },
+ [](VkBaseOutStructure* p) -> bool { (void)p;
+ bool ret = true;
+ return ret;
+ }
+};
+
+static const VpStructChainerDesc chainerDesc = {
+ [](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
+ VkPhysicalDeviceVulkan12Features physicalDeviceVulkan12Features{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, nullptr };
+ VkPhysicalDeviceProtectedMemoryFeatures physicalDeviceProtectedMemoryFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES, &physicalDeviceVulkan12Features };
+ VkPhysicalDeviceShaderIntegerDotProductFeatures physicalDeviceShaderIntegerDotProductFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES, &physicalDeviceProtectedMemoryFeatures };
+ VkPhysicalDeviceTransformFeedbackFeaturesEXT physicalDeviceTransformFeedbackFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT, &physicalDeviceShaderIntegerDotProductFeatures };
+ VkPhysicalDeviceImage2DViewOf3DFeaturesEXT physicalDeviceImage2DViewOf3DFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT, &physicalDeviceTransformFeedbackFeaturesEXT };
+ VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR physicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR, &physicalDeviceImage2DViewOf3DFeaturesEXT };
+ p->pNext = static_cast<VkBaseOutStructure*>(static_cast<void*>(&physicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR));
+ pfnCb(p, pUser);
+ },
+ [](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
+ VkPhysicalDeviceFloatControlsProperties physicalDeviceFloatControlsProperties{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES, nullptr };
+ VkPhysicalDeviceVulkan11Properties physicalDeviceVulkan11Properties{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES, &physicalDeviceFloatControlsProperties };
+ p->pNext = static_cast<VkBaseOutStructure*>(static_cast<void*>(&physicalDeviceVulkan11Properties));
+ pfnCb(p, pUser);
+ },
+ [](uint32_t count, VkBaseOutStructure* p, void* pUser, PFN_vpStructArrayChainerCb pfnCb) {
+ pfnCb(count, p, pUser);
+ },
+ [](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
+ pfnCb(p, pUser);
+ },
+};
+} // namespace shaderStencilExport
+} // namespace blocks
+} // namespace VP_ANDROID_16_MINIMUMS
+#endif // VP_ANDROID_16_minimums
+
#ifdef VP_ANDROID_baseline_2021
namespace VP_ANDROID_BASELINE_2021 {
@@ -883,7 +1400,7 @@
};
static const VpFeatureDesc featureDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: {
VkPhysicalDeviceFeatures2KHR* s = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
@@ -903,23 +1420,23 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: {
- VkPhysicalDeviceFeatures2KHR* prettify_VkPhysicalDeviceFeatures2KHR = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.depthBiasClamp == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.depthBiasClamp == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.depthBiasClamp == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.fragmentStoresAndAtomics == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.fragmentStoresAndAtomics == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.fragmentStoresAndAtomics == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.fullDrawIndexUint32 == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.fullDrawIndexUint32 == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.fullDrawIndexUint32 == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.imageCubeArray == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.imageCubeArray == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.imageCubeArray == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.independentBlend == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.independentBlend == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.independentBlend == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.robustBufferAccess == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.robustBufferAccess == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.robustBufferAccess == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.sampleRateShading == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.sampleRateShading == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.sampleRateShading == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderSampledImageArrayDynamicIndexing == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderSampledImageArrayDynamicIndexing == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderSampledImageArrayDynamicIndexing == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageImageArrayDynamicIndexing == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageImageArrayDynamicIndexing == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderStorageImageArrayDynamicIndexing == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionASTC_LDR == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionASTC_LDR == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.textureCompressionASTC_LDR == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionETC2 == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionETC2 == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.textureCompressionETC2 == VK_TRUE");
+ VkPhysicalDeviceFeatures2KHR* s = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
+ ret = ret && (s->features.depthBiasClamp == VK_TRUE);
+ ret = ret && (s->features.fragmentStoresAndAtomics == VK_TRUE);
+ ret = ret && (s->features.fullDrawIndexUint32 == VK_TRUE);
+ ret = ret && (s->features.imageCubeArray == VK_TRUE);
+ ret = ret && (s->features.independentBlend == VK_TRUE);
+ ret = ret && (s->features.robustBufferAccess == VK_TRUE);
+ ret = ret && (s->features.sampleRateShading == VK_TRUE);
+ ret = ret && (s->features.shaderSampledImageArrayDynamicIndexing == VK_TRUE);
+ ret = ret && (s->features.shaderStorageImageArrayDynamicIndexing == VK_TRUE);
+ ret = ret && (s->features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE);
+ ret = ret && (s->features.textureCompressionASTC_LDR == VK_TRUE);
+ ret = ret && (s->features.textureCompressionETC2 == VK_TRUE);
} break;
default: break;
}
@@ -928,9 +1445,9 @@
};
static const VpPropertyDesc propertyDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
return ret;
}
@@ -945,8 +1462,8 @@
p->pNext = static_cast<VkBaseOutStructure*>(static_cast<void*>(nullptr));
pfnCb(p, pUser);
},
- [](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
- pfnCb(p, pUser);
+ [](uint32_t count, VkBaseOutStructure* p, void* pUser, PFN_vpStructArrayChainerCb pfnCb) {
+ pfnCb(count, p, pUser);
},
[](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
VkFormatProperties3KHR formatProperties3KHR{ VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR, nullptr };
@@ -955,7 +1472,9 @@
},
};
+namespace blocks {
namespace baseline {
+
static const VkExtensionProperties instanceExtensions[] = {
VkExtensionProperties{ VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME, 1 },
VkExtensionProperties{ VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, 1 },
@@ -985,7 +1504,7 @@
};
static const VpFeatureDesc featureDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: {
VkPhysicalDeviceFeatures2KHR* s = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
@@ -1005,23 +1524,23 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: {
- VkPhysicalDeviceFeatures2KHR* prettify_VkPhysicalDeviceFeatures2KHR = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.depthBiasClamp == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.depthBiasClamp == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.depthBiasClamp == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.fragmentStoresAndAtomics == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.fragmentStoresAndAtomics == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.fragmentStoresAndAtomics == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.fullDrawIndexUint32 == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.fullDrawIndexUint32 == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.fullDrawIndexUint32 == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.imageCubeArray == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.imageCubeArray == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.imageCubeArray == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.independentBlend == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.independentBlend == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.independentBlend == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.robustBufferAccess == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.robustBufferAccess == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.robustBufferAccess == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.sampleRateShading == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.sampleRateShading == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.sampleRateShading == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderSampledImageArrayDynamicIndexing == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderSampledImageArrayDynamicIndexing == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderSampledImageArrayDynamicIndexing == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageImageArrayDynamicIndexing == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageImageArrayDynamicIndexing == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderStorageImageArrayDynamicIndexing == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionASTC_LDR == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionASTC_LDR == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.textureCompressionASTC_LDR == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionETC2 == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionETC2 == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.textureCompressionETC2 == VK_TRUE");
+ VkPhysicalDeviceFeatures2KHR* s = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
+ ret = ret && (s->features.depthBiasClamp == VK_TRUE);
+ ret = ret && (s->features.fragmentStoresAndAtomics == VK_TRUE);
+ ret = ret && (s->features.fullDrawIndexUint32 == VK_TRUE);
+ ret = ret && (s->features.imageCubeArray == VK_TRUE);
+ ret = ret && (s->features.independentBlend == VK_TRUE);
+ ret = ret && (s->features.robustBufferAccess == VK_TRUE);
+ ret = ret && (s->features.sampleRateShading == VK_TRUE);
+ ret = ret && (s->features.shaderSampledImageArrayDynamicIndexing == VK_TRUE);
+ ret = ret && (s->features.shaderStorageImageArrayDynamicIndexing == VK_TRUE);
+ ret = ret && (s->features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE);
+ ret = ret && (s->features.textureCompressionASTC_LDR == VK_TRUE);
+ ret = ret && (s->features.textureCompressionETC2 == VK_TRUE);
} break;
default: break;
}
@@ -1030,7 +1549,7 @@
};
static const VpPropertyDesc propertyDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR: {
VkPhysicalDeviceProperties2KHR* s = static_cast<VkPhysicalDeviceProperties2KHR*>(static_cast<void*>(p));
@@ -1119,97 +1638,97 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR: {
- VkPhysicalDeviceProperties2KHR* prettify_VkPhysicalDeviceProperties2KHR = static_cast<VkPhysicalDeviceProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.discreteQueuePriorities >= 2); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.discreteQueuePriorities >= 2), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.discreteQueuePriorities >= 2");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferColorSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferColorSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.framebufferColorSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferDepthSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferDepthSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.framebufferDepthSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferNoAttachmentsSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferNoAttachmentsSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.framebufferNoAttachmentsSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferStencilSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferStencilSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.framebufferStencilSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxBoundDescriptorSets >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxBoundDescriptorSets >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxBoundDescriptorSets >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxColorAttachments >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxColorAttachments >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxColorAttachments >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeSharedMemorySize >= 16384); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeSharedMemorySize >= 16384), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeSharedMemorySize >= 16384");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupCount[0] >= 65535); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupCount[0] >= 65535), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupCount[0] >= 65535");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupCount[1] >= 65535); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupCount[1] >= 65535), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupCount[1] >= 65535");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupCount[2] >= 65535); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupCount[2] >= 65535), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupCount[2] >= 65535");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupInvocations >= 128); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupInvocations >= 128), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupInvocations >= 128");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupSize[0] >= 128); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupSize[0] >= 128), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupSize[0] >= 128");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupSize[1] >= 128); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupSize[1] >= 128), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupSize[1] >= 128");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupSize[2] >= 64); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupSize[2] >= 64), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupSize[2] >= 64");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetInputAttachments >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetInputAttachments >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetInputAttachments >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetSampledImages >= 48); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetSampledImages >= 48), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetSampledImages >= 48");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetSamplers >= 48); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetSamplers >= 48), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetSamplers >= 48");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetStorageBuffers >= 24); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetStorageBuffers >= 24), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetStorageBuffers >= 24");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetStorageBuffersDynamic >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetStorageBuffersDynamic >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetStorageBuffersDynamic >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetStorageImages >= 12); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetStorageImages >= 12), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetStorageImages >= 12");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetUniformBuffers >= 36); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetUniformBuffers >= 36), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetUniformBuffers >= 36");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetUniformBuffersDynamic >= 8); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetUniformBuffersDynamic >= 8), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetUniformBuffersDynamic >= 8");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDrawIndexedIndexValue >= 4294967295); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDrawIndexedIndexValue >= 4294967295), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDrawIndexedIndexValue >= 4294967295");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDrawIndirectCount >= 1); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDrawIndirectCount >= 1), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDrawIndirectCount >= 1");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFragmentCombinedOutputResources >= 8); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFragmentCombinedOutputResources >= 8), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxFragmentCombinedOutputResources >= 8");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFragmentInputComponents >= 64); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFragmentInputComponents >= 64), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxFragmentInputComponents >= 64");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFragmentOutputAttachments >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFragmentOutputAttachments >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxFragmentOutputAttachments >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFramebufferHeight >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFramebufferHeight >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxFramebufferHeight >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFramebufferLayers >= 256); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFramebufferLayers >= 256), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxFramebufferLayers >= 256");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFramebufferWidth >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFramebufferWidth >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxFramebufferWidth >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageArrayLayers >= 256); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageArrayLayers >= 256), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxImageArrayLayers >= 256");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimension1D >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimension1D >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxImageDimension1D >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimension2D >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimension2D >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxImageDimension2D >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimension3D >= 512); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimension3D >= 512), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxImageDimension3D >= 512");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimensionCube >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimensionCube >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxImageDimensionCube >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxInterpolationOffset >= 0.4375); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxInterpolationOffset >= 0.4375), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxInterpolationOffset >= 0.4375");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxMemoryAllocationCount >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxMemoryAllocationCount >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxMemoryAllocationCount >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorInputAttachments >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorInputAttachments >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorInputAttachments >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorSampledImages >= 16); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorSampledImages >= 16), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorSampledImages >= 16");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorSamplers >= 16); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorSamplers >= 16), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorSamplers >= 16");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorStorageBuffers >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorStorageBuffers >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorStorageBuffers >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorStorageImages >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorStorageImages >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorStorageImages >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorUniformBuffers >= 12); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorUniformBuffers >= 12), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorUniformBuffers >= 12");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageResources >= 44); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageResources >= 44), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageResources >= 44");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPushConstantsSize >= 128); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPushConstantsSize >= 128), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPushConstantsSize >= 128");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSampleMaskWords >= 1); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSampleMaskWords >= 1), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxSampleMaskWords >= 1");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSamplerAllocationCount >= 4000); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSamplerAllocationCount >= 4000), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxSamplerAllocationCount >= 4000");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSamplerAnisotropy >= 1.0); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSamplerAnisotropy >= 1.0), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxSamplerAnisotropy >= 1.0");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSamplerLodBias >= 2.0); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSamplerLodBias >= 2.0), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxSamplerLodBias >= 2.0");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxStorageBufferRange >= 134217728); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxStorageBufferRange >= 134217728), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxStorageBufferRange >= 134217728");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxTexelBufferElements >= 65536); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxTexelBufferElements >= 65536), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxTexelBufferElements >= 65536");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxTexelOffset >= 7); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxTexelOffset >= 7), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxTexelOffset >= 7");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxUniformBufferRange >= 16384); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxUniformBufferRange >= 16384), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxUniformBufferRange >= 16384");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputAttributeOffset >= 2047); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputAttributeOffset >= 2047), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxVertexInputAttributeOffset >= 2047");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputAttributes >= 16); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputAttributes >= 16), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxVertexInputAttributes >= 16");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputBindingStride >= 2048); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputBindingStride >= 2048), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxVertexInputBindingStride >= 2048");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputBindings >= 16); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputBindings >= 16), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxVertexInputBindings >= 16");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexOutputComponents >= 64); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexOutputComponents >= 64), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxVertexOutputComponents >= 64");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxViewportDimensions[0] >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxViewportDimensions[0] >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxViewportDimensions[0] >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxViewportDimensions[1] >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxViewportDimensions[1] >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxViewportDimensions[1] >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxViewports >= 1); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxViewports >= 1), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxViewports >= 1");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minInterpolationOffset <= -0.5); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minInterpolationOffset <= -0.5), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.minInterpolationOffset <= -0.5");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment <= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment <= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.minMemoryMapAlignment <= 4096");
- ret = ret && ((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment - 1)) == 0); VP_DEBUG_COND_MSG(!((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment - 1)) == 0), "Unsupported properties condition: (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment - 1)) == 0");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment <= 256); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment <= 256), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.minStorageBufferOffsetAlignment <= 256");
- ret = ret && ((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment - 1)) == 0); VP_DEBUG_COND_MSG(!((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment - 1)) == 0), "Unsupported properties condition: (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment - 1)) == 0");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment <= 256); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment <= 256), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.minTexelBufferOffsetAlignment <= 256");
- ret = ret && ((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment - 1)) == 0); VP_DEBUG_COND_MSG(!((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment - 1)) == 0), "Unsupported properties condition: (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment - 1)) == 0");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelOffset <= -8); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelOffset <= -8), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.minTexelOffset <= -8");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment <= 256); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment <= 256), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.minUniformBufferOffsetAlignment <= 256");
- ret = ret && ((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment - 1)) == 0); VP_DEBUG_COND_MSG(!((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment - 1)) == 0), "Unsupported properties condition: (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment - 1)) == 0");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.mipmapPrecisionBits >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.mipmapPrecisionBits >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.mipmapPrecisionBits >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.pointSizeGranularity <= 1); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.pointSizeGranularity <= 1), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.pointSizeGranularity <= 1");
- ret = ret && (isMultiple(1, prettify_VkPhysicalDeviceProperties2KHR->properties.limits.pointSizeGranularity)); VP_DEBUG_COND_MSG(!(isMultiple(1, prettify_VkPhysicalDeviceProperties2KHR->properties.limits.pointSizeGranularity)), "Unsupported properties condition: isMultiple(1, prettify_VkPhysicalDeviceProperties2KHR->properties.limits.pointSizeGranularity)");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageColorSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageColorSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.sampledImageColorSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageDepthSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageDepthSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.sampledImageDepthSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageIntegerSampleCounts, (VK_SAMPLE_COUNT_1_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageIntegerSampleCounts, (VK_SAMPLE_COUNT_1_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.sampledImageIntegerSampleCounts contains (VK_SAMPLE_COUNT_1_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageStencilSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageStencilSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.sampledImageStencilSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.standardSampleLocations == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.standardSampleLocations == VK_TRUE), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.standardSampleLocations == VK_TRUE");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.storageImageSampleCounts, (VK_SAMPLE_COUNT_1_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.storageImageSampleCounts, (VK_SAMPLE_COUNT_1_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.storageImageSampleCounts contains (VK_SAMPLE_COUNT_1_BIT)");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.subPixelInterpolationOffsetBits >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.subPixelInterpolationOffsetBits >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.subPixelInterpolationOffsetBits >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.subPixelPrecisionBits >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.subPixelPrecisionBits >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.subPixelPrecisionBits >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.subTexelPrecisionBits >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.subTexelPrecisionBits >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.subTexelPrecisionBits >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.viewportBoundsRange[0] <= -8192); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.viewportBoundsRange[0] <= -8192), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.viewportBoundsRange[0] <= -8192");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.viewportBoundsRange[1] >= 8191); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.viewportBoundsRange[1] >= 8191), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.viewportBoundsRange[1] >= 8191");
+ VkPhysicalDeviceProperties2KHR* s = static_cast<VkPhysicalDeviceProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (s->properties.limits.discreteQueuePriorities >= 2);
+ ret = ret && (vpCheckFlags(s->properties.limits.framebufferColorSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (vpCheckFlags(s->properties.limits.framebufferDepthSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (vpCheckFlags(s->properties.limits.framebufferNoAttachmentsSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (vpCheckFlags(s->properties.limits.framebufferStencilSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (s->properties.limits.maxBoundDescriptorSets >= 4);
+ ret = ret && (s->properties.limits.maxColorAttachments >= 4);
+ ret = ret && (s->properties.limits.maxComputeSharedMemorySize >= 16384);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupCount[0] >= 65535);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupCount[1] >= 65535);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupCount[2] >= 65535);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupInvocations >= 128);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupSize[0] >= 128);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupSize[1] >= 128);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupSize[2] >= 64);
+ ret = ret && (s->properties.limits.maxDescriptorSetInputAttachments >= 4);
+ ret = ret && (s->properties.limits.maxDescriptorSetSampledImages >= 48);
+ ret = ret && (s->properties.limits.maxDescriptorSetSamplers >= 48);
+ ret = ret && (s->properties.limits.maxDescriptorSetStorageBuffers >= 24);
+ ret = ret && (s->properties.limits.maxDescriptorSetStorageBuffersDynamic >= 4);
+ ret = ret && (s->properties.limits.maxDescriptorSetStorageImages >= 12);
+ ret = ret && (s->properties.limits.maxDescriptorSetUniformBuffers >= 36);
+ ret = ret && (s->properties.limits.maxDescriptorSetUniformBuffersDynamic >= 8);
+ ret = ret && (s->properties.limits.maxDrawIndexedIndexValue >= 4294967295);
+ ret = ret && (s->properties.limits.maxDrawIndirectCount >= 1);
+ ret = ret && (s->properties.limits.maxFragmentCombinedOutputResources >= 8);
+ ret = ret && (s->properties.limits.maxFragmentInputComponents >= 64);
+ ret = ret && (s->properties.limits.maxFragmentOutputAttachments >= 4);
+ ret = ret && (s->properties.limits.maxFramebufferHeight >= 4096);
+ ret = ret && (s->properties.limits.maxFramebufferLayers >= 256);
+ ret = ret && (s->properties.limits.maxFramebufferWidth >= 4096);
+ ret = ret && (s->properties.limits.maxImageArrayLayers >= 256);
+ ret = ret && (s->properties.limits.maxImageDimension1D >= 4096);
+ ret = ret && (s->properties.limits.maxImageDimension2D >= 4096);
+ ret = ret && (s->properties.limits.maxImageDimension3D >= 512);
+ ret = ret && (s->properties.limits.maxImageDimensionCube >= 4096);
+ ret = ret && (s->properties.limits.maxInterpolationOffset >= 0.4375);
+ ret = ret && (s->properties.limits.maxMemoryAllocationCount >= 4096);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorInputAttachments >= 4);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorSampledImages >= 16);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorSamplers >= 16);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorStorageBuffers >= 4);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorStorageImages >= 4);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorUniformBuffers >= 12);
+ ret = ret && (s->properties.limits.maxPerStageResources >= 44);
+ ret = ret && (s->properties.limits.maxPushConstantsSize >= 128);
+ ret = ret && (s->properties.limits.maxSampleMaskWords >= 1);
+ ret = ret && (s->properties.limits.maxSamplerAllocationCount >= 4000);
+ ret = ret && (s->properties.limits.maxSamplerAnisotropy >= 1.0);
+ ret = ret && (s->properties.limits.maxSamplerLodBias >= 2.0);
+ ret = ret && (s->properties.limits.maxStorageBufferRange >= 134217728);
+ ret = ret && (s->properties.limits.maxTexelBufferElements >= 65536);
+ ret = ret && (s->properties.limits.maxTexelOffset >= 7);
+ ret = ret && (s->properties.limits.maxUniformBufferRange >= 16384);
+ ret = ret && (s->properties.limits.maxVertexInputAttributeOffset >= 2047);
+ ret = ret && (s->properties.limits.maxVertexInputAttributes >= 16);
+ ret = ret && (s->properties.limits.maxVertexInputBindingStride >= 2048);
+ ret = ret && (s->properties.limits.maxVertexInputBindings >= 16);
+ ret = ret && (s->properties.limits.maxVertexOutputComponents >= 64);
+ ret = ret && (s->properties.limits.maxViewportDimensions[0] >= 4096);
+ ret = ret && (s->properties.limits.maxViewportDimensions[1] >= 4096);
+ ret = ret && (s->properties.limits.maxViewports >= 1);
+ ret = ret && (s->properties.limits.minInterpolationOffset <= -0.5);
+ ret = ret && (s->properties.limits.minMemoryMapAlignment <= 4096);
+ ret = ret && ((s->properties.limits.minMemoryMapAlignment & (s->properties.limits.minMemoryMapAlignment - 1)) == 0);
+ ret = ret && (s->properties.limits.minStorageBufferOffsetAlignment <= 256);
+ ret = ret && ((s->properties.limits.minStorageBufferOffsetAlignment & (s->properties.limits.minStorageBufferOffsetAlignment - 1)) == 0);
+ ret = ret && (s->properties.limits.minTexelBufferOffsetAlignment <= 256);
+ ret = ret && ((s->properties.limits.minTexelBufferOffsetAlignment & (s->properties.limits.minTexelBufferOffsetAlignment - 1)) == 0);
+ ret = ret && (s->properties.limits.minTexelOffset <= -8);
+ ret = ret && (s->properties.limits.minUniformBufferOffsetAlignment <= 256);
+ ret = ret && ((s->properties.limits.minUniformBufferOffsetAlignment & (s->properties.limits.minUniformBufferOffsetAlignment - 1)) == 0);
+ ret = ret && (s->properties.limits.mipmapPrecisionBits >= 4);
+ ret = ret && (s->properties.limits.pointSizeGranularity <= 1);
+ ret = ret && (isMultiple(1, s->properties.limits.pointSizeGranularity));
+ ret = ret && (vpCheckFlags(s->properties.limits.sampledImageColorSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (vpCheckFlags(s->properties.limits.sampledImageDepthSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (vpCheckFlags(s->properties.limits.sampledImageIntegerSampleCounts, (VK_SAMPLE_COUNT_1_BIT)));
+ ret = ret && (vpCheckFlags(s->properties.limits.sampledImageStencilSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (s->properties.limits.standardSampleLocations == VK_TRUE);
+ ret = ret && (vpCheckFlags(s->properties.limits.storageImageSampleCounts, (VK_SAMPLE_COUNT_1_BIT)));
+ ret = ret && (s->properties.limits.subPixelInterpolationOffsetBits >= 4);
+ ret = ret && (s->properties.limits.subPixelPrecisionBits >= 4);
+ ret = ret && (s->properties.limits.subTexelPrecisionBits >= 4);
+ ret = ret && (s->properties.limits.viewportBoundsRange[0] <= -8192);
+ ret = ret && (s->properties.limits.viewportBoundsRange[1] >= 8191);
} break;
default: break;
}
@@ -1220,7 +1739,7 @@
static const VpFormatDesc formatDesc[] = {
{
VK_FORMAT_A1R5G5B5_UNORM_PACK16,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1230,13 +1749,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A1R5G5B5_UNORM_PACK16: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A1R5G5B5_UNORM_PACK16: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1245,7 +1764,7 @@
},
{
VK_FORMAT_A2B10G10R10_UINT_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1256,14 +1775,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_A2B10G10R10_UINT_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A2B10G10R10_UINT_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A2B10G10R10_UINT_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1272,7 +1791,7 @@
},
{
VK_FORMAT_A2B10G10R10_UNORM_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1283,14 +1802,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_A2B10G10R10_UNORM_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A2B10G10R10_UNORM_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A2B10G10R10_UNORM_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1299,7 +1818,7 @@
},
{
VK_FORMAT_A8B8G8R8_SINT_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1310,14 +1829,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SINT_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SINT_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SINT_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1326,7 +1845,7 @@
},
{
VK_FORMAT_A8B8G8R8_SNORM_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1337,14 +1856,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SNORM_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SNORM_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SNORM_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1353,7 +1872,7 @@
},
{
VK_FORMAT_A8B8G8R8_SRGB_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1363,13 +1882,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SRGB_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SRGB_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1378,7 +1897,7 @@
},
{
VK_FORMAT_A8B8G8R8_UINT_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1389,14 +1908,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_UINT_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_UINT_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_UINT_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1405,7 +1924,7 @@
},
{
VK_FORMAT_A8B8G8R8_UNORM_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1416,14 +1935,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_UNORM_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_UNORM_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_UNORM_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1432,7 +1951,7 @@
},
{
VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1442,13 +1961,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x10_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x10_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1457,7 +1976,7 @@
},
{
VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1467,13 +1986,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x10_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x10_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1482,7 +2001,7 @@
},
{
VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1492,13 +2011,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1507,7 +2026,7 @@
},
{
VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1517,13 +2036,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1532,7 +2051,7 @@
},
{
VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1542,13 +2061,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x6_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x6_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1557,7 +2076,7 @@
},
{
VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1567,13 +2086,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x6_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x6_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1582,7 +2101,7 @@
},
{
VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1592,13 +2111,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1607,7 +2126,7 @@
},
{
VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1617,13 +2136,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1632,7 +2151,7 @@
},
{
VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1642,13 +2161,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x10_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x10_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1657,7 +2176,7 @@
},
{
VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1667,13 +2186,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x10_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x10_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1682,7 +2201,7 @@
},
{
VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1692,13 +2211,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x12_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x12_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1707,7 +2226,7 @@
},
{
VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1717,13 +2236,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x12_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x12_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1732,7 +2251,7 @@
},
{
VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1742,13 +2261,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_4x4_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_4x4_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1757,7 +2276,7 @@
},
{
VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1767,13 +2286,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_4x4_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_4x4_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1782,7 +2301,7 @@
},
{
VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1792,13 +2311,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x4_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x4_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1807,7 +2326,7 @@
},
{
VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1817,13 +2336,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x4_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x4_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1832,7 +2351,7 @@
},
{
VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1842,13 +2361,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1857,7 +2376,7 @@
},
{
VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1867,13 +2386,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1882,7 +2401,7 @@
},
{
VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1892,13 +2411,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1907,7 +2426,7 @@
},
{
VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1917,13 +2436,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1932,7 +2451,7 @@
},
{
VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1942,13 +2461,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x6_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x6_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1957,7 +2476,7 @@
},
{
VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1967,13 +2486,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x6_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x6_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -1982,7 +2501,7 @@
},
{
VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -1992,13 +2511,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2007,7 +2526,7 @@
},
{
VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2017,13 +2536,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2032,7 +2551,7 @@
},
{
VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2042,13 +2561,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x6_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x6_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2057,7 +2576,7 @@
},
{
VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2067,13 +2586,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x6_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x6_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2082,7 +2601,7 @@
},
{
VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2092,13 +2611,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2107,7 +2626,7 @@
},
{
VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2117,13 +2636,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2132,7 +2651,7 @@
},
{
VK_FORMAT_B10G11R11_UFLOAT_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2143,14 +2662,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_B10G11R11_UFLOAT_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B10G11R11_UFLOAT_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B10G11R11_UFLOAT_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2159,7 +2678,7 @@
},
{
VK_FORMAT_B4G4R4A4_UNORM_PACK16,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2169,13 +2688,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B4G4R4A4_UNORM_PACK16: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B4G4R4A4_UNORM_PACK16: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2184,7 +2703,7 @@
},
{
VK_FORMAT_B8G8R8A8_SRGB,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2194,13 +2713,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B8G8R8A8_SRGB: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B8G8R8A8_SRGB: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2209,7 +2728,7 @@
},
{
VK_FORMAT_B8G8R8A8_UNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2220,14 +2739,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_B8G8R8A8_UNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B8G8R8A8_UNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B8G8R8A8_UNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2236,7 +2755,7 @@
},
{
VK_FORMAT_D16_UNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2245,12 +2764,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_D16_UNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2259,7 +2778,7 @@
},
{
VK_FORMAT_D32_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2268,12 +2787,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_D32_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2282,7 +2801,7 @@
},
{
VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2292,13 +2811,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2307,7 +2826,7 @@
},
{
VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2317,13 +2836,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11G11_SNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11G11_SNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2332,7 +2851,7 @@
},
{
VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2342,13 +2861,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11G11_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11G11_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2357,7 +2876,7 @@
},
{
VK_FORMAT_EAC_R11_SNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2367,13 +2886,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11_SNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11_SNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2382,7 +2901,7 @@
},
{
VK_FORMAT_EAC_R11_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2392,13 +2911,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2407,7 +2926,7 @@
},
{
VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2417,13 +2936,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2432,7 +2951,7 @@
},
{
VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2442,13 +2961,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2457,7 +2976,7 @@
},
{
VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2467,13 +2986,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2482,7 +3001,7 @@
},
{
VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2492,13 +3011,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2507,7 +3026,7 @@
},
{
VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2517,13 +3036,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2532,7 +3051,7 @@
},
{
VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2542,13 +3061,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2557,7 +3076,7 @@
},
{
VK_FORMAT_R16G16B16A16_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2568,14 +3087,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SFLOAT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SFLOAT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2584,7 +3103,7 @@
},
{
VK_FORMAT_R16G16B16A16_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2595,14 +3114,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2611,7 +3130,7 @@
},
{
VK_FORMAT_R16G16B16A16_SNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2620,12 +3139,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
} break;
default: break;
}
@@ -2634,7 +3153,7 @@
},
{
VK_FORMAT_R16G16B16A16_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2645,14 +3164,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2661,7 +3180,7 @@
},
{
VK_FORMAT_R16G16_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2672,14 +3191,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SFLOAT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SFLOAT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2688,7 +3207,7 @@
},
{
VK_FORMAT_R16G16_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2699,14 +3218,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2715,7 +3234,7 @@
},
{
VK_FORMAT_R16G16_SNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2724,12 +3243,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
} break;
default: break;
}
@@ -2738,7 +3257,7 @@
},
{
VK_FORMAT_R16G16_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2748,13 +3267,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2763,7 +3282,7 @@
},
{
VK_FORMAT_R16_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2774,14 +3293,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16_SFLOAT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16_SFLOAT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2790,7 +3309,7 @@
},
{
VK_FORMAT_R16_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2801,14 +3320,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2817,7 +3336,7 @@
},
{
VK_FORMAT_R16_SNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2826,12 +3345,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16_SNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
} break;
default: break;
}
@@ -2840,7 +3359,7 @@
},
{
VK_FORMAT_R16_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2851,14 +3370,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2867,7 +3386,7 @@
},
{
VK_FORMAT_R16_UNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2876,12 +3395,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16_UNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
} break;
default: break;
}
@@ -2890,7 +3409,7 @@
},
{
VK_FORMAT_R32G32B32A32_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2900,13 +3419,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32B32A32_SFLOAT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32B32A32_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2915,7 +3434,7 @@
},
{
VK_FORMAT_R32G32B32A32_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2925,13 +3444,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32B32A32_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32B32A32_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2940,7 +3459,7 @@
},
{
VK_FORMAT_R32G32B32A32_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2950,13 +3469,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32B32A32_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32B32A32_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2965,7 +3484,7 @@
},
{
VK_FORMAT_R32G32_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -2976,14 +3495,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_SFLOAT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_SFLOAT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -2992,7 +3511,7 @@
},
{
VK_FORMAT_R32G32_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3003,14 +3522,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3019,7 +3538,7 @@
},
{
VK_FORMAT_R32G32_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3030,14 +3549,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3046,7 +3565,7 @@
},
{
VK_FORMAT_R32_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3057,14 +3576,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R32_SFLOAT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32_SFLOAT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3073,7 +3592,7 @@
},
{
VK_FORMAT_R32_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3084,14 +3603,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R32_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3100,7 +3619,7 @@
},
{
VK_FORMAT_R32_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3111,14 +3630,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R32_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3127,7 +3646,7 @@
},
{
VK_FORMAT_R5G6B5_UNORM_PACK16,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3137,13 +3656,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R5G6B5_UNORM_PACK16: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R5G6B5_UNORM_PACK16: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3152,7 +3671,7 @@
},
{
VK_FORMAT_R8G8B8A8_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3163,14 +3682,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3179,7 +3698,7 @@
},
{
VK_FORMAT_R8G8B8A8_SNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3190,14 +3709,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3206,7 +3725,7 @@
},
{
VK_FORMAT_R8G8B8A8_SRGB,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3216,13 +3735,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SRGB: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SRGB: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3231,7 +3750,7 @@
},
{
VK_FORMAT_R8G8B8A8_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3242,14 +3761,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3258,7 +3777,7 @@
},
{
VK_FORMAT_R8G8B8A8_UNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3269,14 +3788,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_UNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_UNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_UNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3285,7 +3804,7 @@
},
{
VK_FORMAT_R8G8_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3296,14 +3815,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3312,7 +3831,7 @@
},
{
VK_FORMAT_R8G8_SNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3323,14 +3842,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_SNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_SNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_SNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3339,7 +3858,7 @@
},
{
VK_FORMAT_R8G8_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3350,14 +3869,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3366,7 +3885,7 @@
},
{
VK_FORMAT_R8G8_UNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3377,14 +3896,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_UNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_UNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_UNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3393,7 +3912,7 @@
},
{
VK_FORMAT_R8_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3404,14 +3923,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3420,7 +3939,7 @@
},
{
VK_FORMAT_R8_SNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3431,14 +3950,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8_SNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_SNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_SNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3447,7 +3966,7 @@
},
{
VK_FORMAT_R8_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3458,14 +3977,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3474,7 +3993,7 @@
},
{
VK_FORMAT_R8_UNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3485,14 +4004,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8_UNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_UNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_UNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3510,8 +4029,8 @@
p->pNext = static_cast<VkBaseOutStructure*>(static_cast<void*>(nullptr));
pfnCb(p, pUser);
},
- [](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
- pfnCb(p, pUser);
+ [](uint32_t count, VkBaseOutStructure* p, void* pUser, PFN_vpStructArrayChainerCb pfnCb) {
+ pfnCb(count, p, pUser);
},
[](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
VkFormatProperties3KHR formatProperties3KHR{ VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR, nullptr };
@@ -3519,7 +4038,8 @@
pfnCb(p, pUser);
},
};
-} //namespace baseline
+} // namespace baseline
+} // namespace blocks
} // namespace VP_ANDROID_BASELINE_2021
#endif // VP_ANDROID_baseline_2021
@@ -3565,7 +4085,7 @@
};
static const VpFeatureDesc featureDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: {
VkPhysicalDeviceFeatures2KHR* s = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
@@ -3585,23 +4105,23 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: {
- VkPhysicalDeviceFeatures2KHR* prettify_VkPhysicalDeviceFeatures2KHR = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.depthBiasClamp == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.depthBiasClamp == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.depthBiasClamp == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.fragmentStoresAndAtomics == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.fragmentStoresAndAtomics == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.fragmentStoresAndAtomics == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.fullDrawIndexUint32 == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.fullDrawIndexUint32 == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.fullDrawIndexUint32 == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.imageCubeArray == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.imageCubeArray == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.imageCubeArray == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.independentBlend == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.independentBlend == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.independentBlend == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.robustBufferAccess == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.robustBufferAccess == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.robustBufferAccess == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.sampleRateShading == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.sampleRateShading == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.sampleRateShading == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderSampledImageArrayDynamicIndexing == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderSampledImageArrayDynamicIndexing == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderSampledImageArrayDynamicIndexing == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageImageArrayDynamicIndexing == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageImageArrayDynamicIndexing == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderStorageImageArrayDynamicIndexing == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionASTC_LDR == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionASTC_LDR == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.textureCompressionASTC_LDR == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionETC2 == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionETC2 == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.textureCompressionETC2 == VK_TRUE");
+ VkPhysicalDeviceFeatures2KHR* s = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
+ ret = ret && (s->features.depthBiasClamp == VK_TRUE);
+ ret = ret && (s->features.fragmentStoresAndAtomics == VK_TRUE);
+ ret = ret && (s->features.fullDrawIndexUint32 == VK_TRUE);
+ ret = ret && (s->features.imageCubeArray == VK_TRUE);
+ ret = ret && (s->features.independentBlend == VK_TRUE);
+ ret = ret && (s->features.robustBufferAccess == VK_TRUE);
+ ret = ret && (s->features.sampleRateShading == VK_TRUE);
+ ret = ret && (s->features.shaderSampledImageArrayDynamicIndexing == VK_TRUE);
+ ret = ret && (s->features.shaderStorageImageArrayDynamicIndexing == VK_TRUE);
+ ret = ret && (s->features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE);
+ ret = ret && (s->features.textureCompressionASTC_LDR == VK_TRUE);
+ ret = ret && (s->features.textureCompressionETC2 == VK_TRUE);
} break;
default: break;
}
@@ -3610,9 +4130,9 @@
};
static const VpPropertyDesc propertyDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
return ret;
}
@@ -3627,8 +4147,8 @@
p->pNext = static_cast<VkBaseOutStructure*>(static_cast<void*>(nullptr));
pfnCb(p, pUser);
},
- [](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
- pfnCb(p, pUser);
+ [](uint32_t count, VkBaseOutStructure* p, void* pUser, PFN_vpStructArrayChainerCb pfnCb) {
+ pfnCb(count, p, pUser);
},
[](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
VkFormatProperties3KHR formatProperties3KHR{ VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR, nullptr };
@@ -3637,7 +4157,9 @@
},
};
+namespace blocks {
namespace baseline {
+
static const VkExtensionProperties instanceExtensions[] = {
VkExtensionProperties{ VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME, 1 },
VkExtensionProperties{ VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, 1 },
@@ -3664,7 +4186,7 @@
};
static const VpFeatureDesc featureDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: {
VkPhysicalDeviceFeatures2KHR* s = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
@@ -3684,23 +4206,23 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: {
- VkPhysicalDeviceFeatures2KHR* prettify_VkPhysicalDeviceFeatures2KHR = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.depthBiasClamp == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.depthBiasClamp == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.depthBiasClamp == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.fragmentStoresAndAtomics == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.fragmentStoresAndAtomics == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.fragmentStoresAndAtomics == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.fullDrawIndexUint32 == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.fullDrawIndexUint32 == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.fullDrawIndexUint32 == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.imageCubeArray == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.imageCubeArray == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.imageCubeArray == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.independentBlend == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.independentBlend == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.independentBlend == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.robustBufferAccess == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.robustBufferAccess == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.robustBufferAccess == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.sampleRateShading == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.sampleRateShading == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.sampleRateShading == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderSampledImageArrayDynamicIndexing == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderSampledImageArrayDynamicIndexing == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderSampledImageArrayDynamicIndexing == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageImageArrayDynamicIndexing == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageImageArrayDynamicIndexing == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderStorageImageArrayDynamicIndexing == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionASTC_LDR == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionASTC_LDR == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.textureCompressionASTC_LDR == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionETC2 == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionETC2 == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.textureCompressionETC2 == VK_TRUE");
+ VkPhysicalDeviceFeatures2KHR* s = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
+ ret = ret && (s->features.depthBiasClamp == VK_TRUE);
+ ret = ret && (s->features.fragmentStoresAndAtomics == VK_TRUE);
+ ret = ret && (s->features.fullDrawIndexUint32 == VK_TRUE);
+ ret = ret && (s->features.imageCubeArray == VK_TRUE);
+ ret = ret && (s->features.independentBlend == VK_TRUE);
+ ret = ret && (s->features.robustBufferAccess == VK_TRUE);
+ ret = ret && (s->features.sampleRateShading == VK_TRUE);
+ ret = ret && (s->features.shaderSampledImageArrayDynamicIndexing == VK_TRUE);
+ ret = ret && (s->features.shaderStorageImageArrayDynamicIndexing == VK_TRUE);
+ ret = ret && (s->features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE);
+ ret = ret && (s->features.textureCompressionASTC_LDR == VK_TRUE);
+ ret = ret && (s->features.textureCompressionETC2 == VK_TRUE);
} break;
default: break;
}
@@ -3709,7 +4231,7 @@
};
static const VpPropertyDesc propertyDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR: {
VkPhysicalDeviceProperties2KHR* s = static_cast<VkPhysicalDeviceProperties2KHR*>(static_cast<void*>(p));
@@ -3797,95 +4319,95 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR: {
- VkPhysicalDeviceProperties2KHR* prettify_VkPhysicalDeviceProperties2KHR = static_cast<VkPhysicalDeviceProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.discreteQueuePriorities >= 2); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.discreteQueuePriorities >= 2), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.discreteQueuePriorities >= 2");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferColorSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferColorSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.framebufferColorSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferDepthSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferDepthSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.framebufferDepthSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferNoAttachmentsSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferNoAttachmentsSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.framebufferNoAttachmentsSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferStencilSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferStencilSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.framebufferStencilSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxBoundDescriptorSets >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxBoundDescriptorSets >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxBoundDescriptorSets >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxColorAttachments >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxColorAttachments >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxColorAttachments >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeSharedMemorySize >= 16384); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeSharedMemorySize >= 16384), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeSharedMemorySize >= 16384");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupCount[0] >= 65535); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupCount[0] >= 65535), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupCount[0] >= 65535");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupCount[1] >= 65535); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupCount[1] >= 65535), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupCount[1] >= 65535");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupCount[2] >= 65535); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupCount[2] >= 65535), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupCount[2] >= 65535");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupInvocations >= 128); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupInvocations >= 128), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupInvocations >= 128");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupSize[0] >= 128); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupSize[0] >= 128), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupSize[0] >= 128");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupSize[1] >= 128); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupSize[1] >= 128), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupSize[1] >= 128");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupSize[2] >= 64); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupSize[2] >= 64), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupSize[2] >= 64");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetInputAttachments >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetInputAttachments >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetInputAttachments >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetSampledImages >= 48); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetSampledImages >= 48), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetSampledImages >= 48");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetSamplers >= 48); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetSamplers >= 48), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetSamplers >= 48");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetStorageBuffers >= 24); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetStorageBuffers >= 24), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetStorageBuffers >= 24");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetStorageBuffersDynamic >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetStorageBuffersDynamic >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetStorageBuffersDynamic >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetStorageImages >= 12); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetStorageImages >= 12), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetStorageImages >= 12");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetUniformBuffers >= 36); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetUniformBuffers >= 36), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetUniformBuffers >= 36");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetUniformBuffersDynamic >= 8); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetUniformBuffersDynamic >= 8), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetUniformBuffersDynamic >= 8");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDrawIndexedIndexValue >= 4294967295); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDrawIndexedIndexValue >= 4294967295), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDrawIndexedIndexValue >= 4294967295");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDrawIndirectCount >= 1); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDrawIndirectCount >= 1), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDrawIndirectCount >= 1");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFragmentCombinedOutputResources >= 8); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFragmentCombinedOutputResources >= 8), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxFragmentCombinedOutputResources >= 8");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFragmentInputComponents >= 64); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFragmentInputComponents >= 64), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxFragmentInputComponents >= 64");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFragmentOutputAttachments >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFragmentOutputAttachments >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxFragmentOutputAttachments >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFramebufferHeight >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFramebufferHeight >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxFramebufferHeight >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFramebufferLayers >= 256); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFramebufferLayers >= 256), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxFramebufferLayers >= 256");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFramebufferWidth >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFramebufferWidth >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxFramebufferWidth >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageArrayLayers >= 256); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageArrayLayers >= 256), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxImageArrayLayers >= 256");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimension1D >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimension1D >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxImageDimension1D >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimension2D >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimension2D >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxImageDimension2D >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimension3D >= 512); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimension3D >= 512), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxImageDimension3D >= 512");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimensionCube >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimensionCube >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxImageDimensionCube >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxInterpolationOffset >= 0.4375); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxInterpolationOffset >= 0.4375), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxInterpolationOffset >= 0.4375");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxMemoryAllocationCount >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxMemoryAllocationCount >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxMemoryAllocationCount >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorInputAttachments >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorInputAttachments >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorInputAttachments >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorSampledImages >= 16); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorSampledImages >= 16), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorSampledImages >= 16");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorSamplers >= 16); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorSamplers >= 16), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorSamplers >= 16");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorStorageBuffers >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorStorageBuffers >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorStorageBuffers >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorStorageImages >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorStorageImages >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorStorageImages >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorUniformBuffers >= 12); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorUniformBuffers >= 12), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorUniformBuffers >= 12");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageResources >= 44); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageResources >= 44), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageResources >= 44");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPushConstantsSize >= 128); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPushConstantsSize >= 128), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPushConstantsSize >= 128");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSampleMaskWords >= 1); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSampleMaskWords >= 1), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxSampleMaskWords >= 1");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSamplerAllocationCount >= 4000); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSamplerAllocationCount >= 4000), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxSamplerAllocationCount >= 4000");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSamplerAnisotropy >= 1.0); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSamplerAnisotropy >= 1.0), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxSamplerAnisotropy >= 1.0");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSamplerLodBias >= 2.0); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSamplerLodBias >= 2.0), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxSamplerLodBias >= 2.0");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxStorageBufferRange >= 134217728); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxStorageBufferRange >= 134217728), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxStorageBufferRange >= 134217728");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxTexelBufferElements >= 65536); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxTexelBufferElements >= 65536), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxTexelBufferElements >= 65536");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxTexelOffset >= 7); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxTexelOffset >= 7), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxTexelOffset >= 7");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxUniformBufferRange >= 16384); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxUniformBufferRange >= 16384), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxUniformBufferRange >= 16384");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputAttributeOffset >= 2047); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputAttributeOffset >= 2047), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxVertexInputAttributeOffset >= 2047");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputAttributes >= 16); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputAttributes >= 16), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxVertexInputAttributes >= 16");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputBindingStride >= 2048); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputBindingStride >= 2048), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxVertexInputBindingStride >= 2048");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputBindings >= 16); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputBindings >= 16), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxVertexInputBindings >= 16");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexOutputComponents >= 64); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexOutputComponents >= 64), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxVertexOutputComponents >= 64");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxViewportDimensions[0] >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxViewportDimensions[0] >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxViewportDimensions[0] >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxViewportDimensions[1] >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxViewportDimensions[1] >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxViewportDimensions[1] >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxViewports >= 1); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxViewports >= 1), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxViewports >= 1");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minInterpolationOffset <= -0.5); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minInterpolationOffset <= -0.5), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.minInterpolationOffset <= -0.5");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment <= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment <= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.minMemoryMapAlignment <= 4096");
- ret = ret && ((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment - 1)) == 0); VP_DEBUG_COND_MSG(!((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment - 1)) == 0), "Unsupported properties condition: (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment - 1)) == 0");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment <= 256); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment <= 256), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.minStorageBufferOffsetAlignment <= 256");
- ret = ret && ((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment - 1)) == 0); VP_DEBUG_COND_MSG(!((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment - 1)) == 0), "Unsupported properties condition: (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment - 1)) == 0");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment <= 256); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment <= 256), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.minTexelBufferOffsetAlignment <= 256");
- ret = ret && ((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment - 1)) == 0); VP_DEBUG_COND_MSG(!((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment - 1)) == 0), "Unsupported properties condition: (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment - 1)) == 0");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelOffset <= -8); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelOffset <= -8), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.minTexelOffset <= -8");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment <= 256); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment <= 256), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.minUniformBufferOffsetAlignment <= 256");
- ret = ret && ((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment - 1)) == 0); VP_DEBUG_COND_MSG(!((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment - 1)) == 0), "Unsupported properties condition: (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment - 1)) == 0");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.mipmapPrecisionBits >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.mipmapPrecisionBits >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.mipmapPrecisionBits >= 4");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageColorSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageColorSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.sampledImageColorSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageDepthSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageDepthSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.sampledImageDepthSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageIntegerSampleCounts, (VK_SAMPLE_COUNT_1_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageIntegerSampleCounts, (VK_SAMPLE_COUNT_1_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.sampledImageIntegerSampleCounts contains (VK_SAMPLE_COUNT_1_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageStencilSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageStencilSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.sampledImageStencilSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.standardSampleLocations == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.standardSampleLocations == VK_TRUE), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.standardSampleLocations == VK_TRUE");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.storageImageSampleCounts, (VK_SAMPLE_COUNT_1_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.storageImageSampleCounts, (VK_SAMPLE_COUNT_1_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.storageImageSampleCounts contains (VK_SAMPLE_COUNT_1_BIT)");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.subPixelInterpolationOffsetBits >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.subPixelInterpolationOffsetBits >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.subPixelInterpolationOffsetBits >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.subPixelPrecisionBits >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.subPixelPrecisionBits >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.subPixelPrecisionBits >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.subTexelPrecisionBits >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.subTexelPrecisionBits >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.subTexelPrecisionBits >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.viewportBoundsRange[0] <= -8192); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.viewportBoundsRange[0] <= -8192), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.viewportBoundsRange[0] <= -8192");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.viewportBoundsRange[1] >= 8191); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.viewportBoundsRange[1] >= 8191), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.viewportBoundsRange[1] >= 8191");
+ VkPhysicalDeviceProperties2KHR* s = static_cast<VkPhysicalDeviceProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (s->properties.limits.discreteQueuePriorities >= 2);
+ ret = ret && (vpCheckFlags(s->properties.limits.framebufferColorSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (vpCheckFlags(s->properties.limits.framebufferDepthSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (vpCheckFlags(s->properties.limits.framebufferNoAttachmentsSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (vpCheckFlags(s->properties.limits.framebufferStencilSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (s->properties.limits.maxBoundDescriptorSets >= 4);
+ ret = ret && (s->properties.limits.maxColorAttachments >= 4);
+ ret = ret && (s->properties.limits.maxComputeSharedMemorySize >= 16384);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupCount[0] >= 65535);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupCount[1] >= 65535);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupCount[2] >= 65535);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupInvocations >= 128);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupSize[0] >= 128);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupSize[1] >= 128);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupSize[2] >= 64);
+ ret = ret && (s->properties.limits.maxDescriptorSetInputAttachments >= 4);
+ ret = ret && (s->properties.limits.maxDescriptorSetSampledImages >= 48);
+ ret = ret && (s->properties.limits.maxDescriptorSetSamplers >= 48);
+ ret = ret && (s->properties.limits.maxDescriptorSetStorageBuffers >= 24);
+ ret = ret && (s->properties.limits.maxDescriptorSetStorageBuffersDynamic >= 4);
+ ret = ret && (s->properties.limits.maxDescriptorSetStorageImages >= 12);
+ ret = ret && (s->properties.limits.maxDescriptorSetUniformBuffers >= 36);
+ ret = ret && (s->properties.limits.maxDescriptorSetUniformBuffersDynamic >= 8);
+ ret = ret && (s->properties.limits.maxDrawIndexedIndexValue >= 4294967295);
+ ret = ret && (s->properties.limits.maxDrawIndirectCount >= 1);
+ ret = ret && (s->properties.limits.maxFragmentCombinedOutputResources >= 8);
+ ret = ret && (s->properties.limits.maxFragmentInputComponents >= 64);
+ ret = ret && (s->properties.limits.maxFragmentOutputAttachments >= 4);
+ ret = ret && (s->properties.limits.maxFramebufferHeight >= 4096);
+ ret = ret && (s->properties.limits.maxFramebufferLayers >= 256);
+ ret = ret && (s->properties.limits.maxFramebufferWidth >= 4096);
+ ret = ret && (s->properties.limits.maxImageArrayLayers >= 256);
+ ret = ret && (s->properties.limits.maxImageDimension1D >= 4096);
+ ret = ret && (s->properties.limits.maxImageDimension2D >= 4096);
+ ret = ret && (s->properties.limits.maxImageDimension3D >= 512);
+ ret = ret && (s->properties.limits.maxImageDimensionCube >= 4096);
+ ret = ret && (s->properties.limits.maxInterpolationOffset >= 0.4375);
+ ret = ret && (s->properties.limits.maxMemoryAllocationCount >= 4096);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorInputAttachments >= 4);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorSampledImages >= 16);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorSamplers >= 16);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorStorageBuffers >= 4);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorStorageImages >= 4);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorUniformBuffers >= 12);
+ ret = ret && (s->properties.limits.maxPerStageResources >= 44);
+ ret = ret && (s->properties.limits.maxPushConstantsSize >= 128);
+ ret = ret && (s->properties.limits.maxSampleMaskWords >= 1);
+ ret = ret && (s->properties.limits.maxSamplerAllocationCount >= 4000);
+ ret = ret && (s->properties.limits.maxSamplerAnisotropy >= 1.0);
+ ret = ret && (s->properties.limits.maxSamplerLodBias >= 2.0);
+ ret = ret && (s->properties.limits.maxStorageBufferRange >= 134217728);
+ ret = ret && (s->properties.limits.maxTexelBufferElements >= 65536);
+ ret = ret && (s->properties.limits.maxTexelOffset >= 7);
+ ret = ret && (s->properties.limits.maxUniformBufferRange >= 16384);
+ ret = ret && (s->properties.limits.maxVertexInputAttributeOffset >= 2047);
+ ret = ret && (s->properties.limits.maxVertexInputAttributes >= 16);
+ ret = ret && (s->properties.limits.maxVertexInputBindingStride >= 2048);
+ ret = ret && (s->properties.limits.maxVertexInputBindings >= 16);
+ ret = ret && (s->properties.limits.maxVertexOutputComponents >= 64);
+ ret = ret && (s->properties.limits.maxViewportDimensions[0] >= 4096);
+ ret = ret && (s->properties.limits.maxViewportDimensions[1] >= 4096);
+ ret = ret && (s->properties.limits.maxViewports >= 1);
+ ret = ret && (s->properties.limits.minInterpolationOffset <= -0.5);
+ ret = ret && (s->properties.limits.minMemoryMapAlignment <= 4096);
+ ret = ret && ((s->properties.limits.minMemoryMapAlignment & (s->properties.limits.minMemoryMapAlignment - 1)) == 0);
+ ret = ret && (s->properties.limits.minStorageBufferOffsetAlignment <= 256);
+ ret = ret && ((s->properties.limits.minStorageBufferOffsetAlignment & (s->properties.limits.minStorageBufferOffsetAlignment - 1)) == 0);
+ ret = ret && (s->properties.limits.minTexelBufferOffsetAlignment <= 256);
+ ret = ret && ((s->properties.limits.minTexelBufferOffsetAlignment & (s->properties.limits.minTexelBufferOffsetAlignment - 1)) == 0);
+ ret = ret && (s->properties.limits.minTexelOffset <= -8);
+ ret = ret && (s->properties.limits.minUniformBufferOffsetAlignment <= 256);
+ ret = ret && ((s->properties.limits.minUniformBufferOffsetAlignment & (s->properties.limits.minUniformBufferOffsetAlignment - 1)) == 0);
+ ret = ret && (s->properties.limits.mipmapPrecisionBits >= 4);
+ ret = ret && (vpCheckFlags(s->properties.limits.sampledImageColorSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (vpCheckFlags(s->properties.limits.sampledImageDepthSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (vpCheckFlags(s->properties.limits.sampledImageIntegerSampleCounts, (VK_SAMPLE_COUNT_1_BIT)));
+ ret = ret && (vpCheckFlags(s->properties.limits.sampledImageStencilSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (s->properties.limits.standardSampleLocations == VK_TRUE);
+ ret = ret && (vpCheckFlags(s->properties.limits.storageImageSampleCounts, (VK_SAMPLE_COUNT_1_BIT)));
+ ret = ret && (s->properties.limits.subPixelInterpolationOffsetBits >= 4);
+ ret = ret && (s->properties.limits.subPixelPrecisionBits >= 4);
+ ret = ret && (s->properties.limits.subTexelPrecisionBits >= 4);
+ ret = ret && (s->properties.limits.viewportBoundsRange[0] <= -8192);
+ ret = ret && (s->properties.limits.viewportBoundsRange[1] >= 8191);
} break;
default: break;
}
@@ -3896,7 +4418,7 @@
static const VpFormatDesc formatDesc[] = {
{
VK_FORMAT_A1R5G5B5_UNORM_PACK16,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3906,13 +4428,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A1R5G5B5_UNORM_PACK16: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A1R5G5B5_UNORM_PACK16: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3921,7 +4443,7 @@
},
{
VK_FORMAT_A2B10G10R10_UINT_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3932,14 +4454,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_A2B10G10R10_UINT_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A2B10G10R10_UINT_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A2B10G10R10_UINT_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3948,7 +4470,7 @@
},
{
VK_FORMAT_A2B10G10R10_UNORM_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3959,14 +4481,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_A2B10G10R10_UNORM_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A2B10G10R10_UNORM_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A2B10G10R10_UNORM_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -3975,7 +4497,7 @@
},
{
VK_FORMAT_A8B8G8R8_SINT_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -3986,14 +4508,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SINT_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SINT_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SINT_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4002,7 +4524,7 @@
},
{
VK_FORMAT_A8B8G8R8_SNORM_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4013,14 +4535,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SNORM_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SNORM_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SNORM_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4029,7 +4551,7 @@
},
{
VK_FORMAT_A8B8G8R8_SRGB_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4039,13 +4561,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SRGB_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SRGB_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4054,7 +4576,7 @@
},
{
VK_FORMAT_A8B8G8R8_UINT_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4065,14 +4587,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_UINT_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_UINT_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_UINT_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4081,7 +4603,7 @@
},
{
VK_FORMAT_A8B8G8R8_UNORM_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4092,14 +4614,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_UNORM_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_UNORM_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_UNORM_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4108,7 +4630,7 @@
},
{
VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4118,13 +4640,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x10_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x10_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4133,7 +4655,7 @@
},
{
VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4143,13 +4665,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x10_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x10_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4158,7 +4680,7 @@
},
{
VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4168,13 +4690,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4183,7 +4705,7 @@
},
{
VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4193,13 +4715,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4208,7 +4730,7 @@
},
{
VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4218,13 +4740,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x6_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x6_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4233,7 +4755,7 @@
},
{
VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4243,13 +4765,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x6_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x6_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4258,7 +4780,7 @@
},
{
VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4268,13 +4790,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4283,7 +4805,7 @@
},
{
VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4293,13 +4815,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4308,7 +4830,7 @@
},
{
VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4318,13 +4840,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x10_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x10_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4333,7 +4855,7 @@
},
{
VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4343,13 +4865,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x10_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x10_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4358,7 +4880,7 @@
},
{
VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4368,13 +4890,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x12_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x12_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4383,7 +4905,7 @@
},
{
VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4393,13 +4915,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x12_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x12_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4408,7 +4930,7 @@
},
{
VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4418,13 +4940,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_4x4_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_4x4_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4433,7 +4955,7 @@
},
{
VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4443,13 +4965,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_4x4_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_4x4_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4458,7 +4980,7 @@
},
{
VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4468,13 +4990,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x4_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x4_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4483,7 +5005,7 @@
},
{
VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4493,13 +5015,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x4_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x4_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4508,7 +5030,7 @@
},
{
VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4518,13 +5040,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4533,7 +5055,7 @@
},
{
VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4543,13 +5065,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4558,7 +5080,7 @@
},
{
VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4568,13 +5090,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4583,7 +5105,7 @@
},
{
VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4593,13 +5115,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4608,7 +5130,7 @@
},
{
VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4618,13 +5140,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x6_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x6_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4633,7 +5155,7 @@
},
{
VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4643,13 +5165,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x6_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x6_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4658,7 +5180,7 @@
},
{
VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4668,13 +5190,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4683,7 +5205,7 @@
},
{
VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4693,13 +5215,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4708,7 +5230,7 @@
},
{
VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4718,13 +5240,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x6_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x6_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4733,7 +5255,7 @@
},
{
VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4743,13 +5265,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x6_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x6_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4758,7 +5280,7 @@
},
{
VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4768,13 +5290,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4783,7 +5305,7 @@
},
{
VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4793,13 +5315,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4808,7 +5330,7 @@
},
{
VK_FORMAT_B10G11R11_UFLOAT_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4819,14 +5341,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_B10G11R11_UFLOAT_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B10G11R11_UFLOAT_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B10G11R11_UFLOAT_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4835,7 +5357,7 @@
},
{
VK_FORMAT_B4G4R4A4_UNORM_PACK16,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4845,13 +5367,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B4G4R4A4_UNORM_PACK16: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B4G4R4A4_UNORM_PACK16: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4860,7 +5382,7 @@
},
{
VK_FORMAT_B8G8R8A8_SRGB,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4870,13 +5392,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B8G8R8A8_SRGB: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B8G8R8A8_SRGB: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4885,7 +5407,7 @@
},
{
VK_FORMAT_B8G8R8A8_UNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4896,14 +5418,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_B8G8R8A8_UNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B8G8R8A8_UNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B8G8R8A8_UNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4912,7 +5434,7 @@
},
{
VK_FORMAT_D16_UNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4921,12 +5443,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_D16_UNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4935,7 +5457,7 @@
},
{
VK_FORMAT_D32_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4944,12 +5466,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_D32_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4958,7 +5480,7 @@
},
{
VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4968,13 +5490,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -4983,7 +5505,7 @@
},
{
VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -4993,13 +5515,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11G11_SNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11G11_SNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5008,7 +5530,7 @@
},
{
VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5018,13 +5540,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11G11_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11G11_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5033,7 +5555,7 @@
},
{
VK_FORMAT_EAC_R11_SNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5043,13 +5565,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11_SNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11_SNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5058,7 +5580,7 @@
},
{
VK_FORMAT_EAC_R11_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5068,13 +5590,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5083,7 +5605,7 @@
},
{
VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5093,13 +5615,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5108,7 +5630,7 @@
},
{
VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5118,13 +5640,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5133,7 +5655,7 @@
},
{
VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5143,13 +5665,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5158,7 +5680,7 @@
},
{
VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5168,13 +5690,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5183,7 +5705,7 @@
},
{
VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5193,13 +5715,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5208,7 +5730,7 @@
},
{
VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5218,13 +5740,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5233,7 +5755,7 @@
},
{
VK_FORMAT_R16G16B16A16_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5244,14 +5766,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SFLOAT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SFLOAT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5260,7 +5782,7 @@
},
{
VK_FORMAT_R16G16B16A16_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5271,14 +5793,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5287,7 +5809,7 @@
},
{
VK_FORMAT_R16G16B16A16_SNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5296,12 +5818,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
} break;
default: break;
}
@@ -5310,7 +5832,7 @@
},
{
VK_FORMAT_R16G16B16A16_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5321,14 +5843,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5337,7 +5859,7 @@
},
{
VK_FORMAT_R16G16_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5348,14 +5870,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SFLOAT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SFLOAT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5364,7 +5886,7 @@
},
{
VK_FORMAT_R16G16_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5375,14 +5897,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5391,7 +5913,7 @@
},
{
VK_FORMAT_R16G16_SNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5400,12 +5922,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
} break;
default: break;
}
@@ -5414,7 +5936,7 @@
},
{
VK_FORMAT_R16G16_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5424,13 +5946,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5439,7 +5961,7 @@
},
{
VK_FORMAT_R16_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5450,14 +5972,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16_SFLOAT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16_SFLOAT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5466,7 +5988,7 @@
},
{
VK_FORMAT_R16_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5477,14 +5999,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5493,7 +6015,7 @@
},
{
VK_FORMAT_R16_SNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5502,12 +6024,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16_SNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
} break;
default: break;
}
@@ -5516,7 +6038,7 @@
},
{
VK_FORMAT_R16_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5527,14 +6049,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5543,7 +6065,7 @@
},
{
VK_FORMAT_R16_UNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5552,12 +6074,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16_UNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
} break;
default: break;
}
@@ -5566,7 +6088,7 @@
},
{
VK_FORMAT_R32G32B32A32_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5576,13 +6098,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32B32A32_SFLOAT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32B32A32_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5591,7 +6113,7 @@
},
{
VK_FORMAT_R32G32B32A32_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5601,13 +6123,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32B32A32_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32B32A32_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5616,7 +6138,7 @@
},
{
VK_FORMAT_R32G32B32A32_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5626,13 +6148,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32B32A32_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32B32A32_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5641,7 +6163,7 @@
},
{
VK_FORMAT_R32G32_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5652,14 +6174,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_SFLOAT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_SFLOAT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5668,7 +6190,7 @@
},
{
VK_FORMAT_R32G32_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5679,14 +6201,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5695,7 +6217,7 @@
},
{
VK_FORMAT_R32G32_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5706,14 +6228,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5722,7 +6244,7 @@
},
{
VK_FORMAT_R32_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5733,14 +6255,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R32_SFLOAT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32_SFLOAT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5749,7 +6271,7 @@
},
{
VK_FORMAT_R32_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5760,14 +6282,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R32_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5776,7 +6298,7 @@
},
{
VK_FORMAT_R32_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5787,14 +6309,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R32_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5803,7 +6325,7 @@
},
{
VK_FORMAT_R5G6B5_UNORM_PACK16,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5813,13 +6335,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R5G6B5_UNORM_PACK16: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R5G6B5_UNORM_PACK16: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5828,7 +6350,7 @@
},
{
VK_FORMAT_R8G8B8A8_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5839,14 +6361,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5855,7 +6377,7 @@
},
{
VK_FORMAT_R8G8B8A8_SNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5866,14 +6388,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5882,7 +6404,7 @@
},
{
VK_FORMAT_R8G8B8A8_SRGB,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5892,13 +6414,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SRGB: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SRGB: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5907,7 +6429,7 @@
},
{
VK_FORMAT_R8G8B8A8_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5918,14 +6440,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5934,7 +6456,7 @@
},
{
VK_FORMAT_R8G8B8A8_UNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5945,14 +6467,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_UNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_UNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_UNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5961,7 +6483,7 @@
},
{
VK_FORMAT_R8G8_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5972,14 +6494,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -5988,7 +6510,7 @@
},
{
VK_FORMAT_R8G8_SNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -5999,14 +6521,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_SNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_SNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_SNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -6015,7 +6537,7 @@
},
{
VK_FORMAT_R8G8_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -6026,14 +6548,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -6042,7 +6564,7 @@
},
{
VK_FORMAT_R8G8_UNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -6053,14 +6575,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_UNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_UNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_UNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -6069,7 +6591,7 @@
},
{
VK_FORMAT_R8_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -6080,14 +6602,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -6096,7 +6618,7 @@
},
{
VK_FORMAT_R8_SNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -6107,14 +6629,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8_SNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_SNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_SNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -6123,7 +6645,7 @@
},
{
VK_FORMAT_R8_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -6134,14 +6656,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -6150,7 +6672,7 @@
},
{
VK_FORMAT_R8_UNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -6161,14 +6683,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8_UNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_UNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_UNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -6186,8 +6708,8 @@
p->pNext = static_cast<VkBaseOutStructure*>(static_cast<void*>(nullptr));
pfnCb(p, pUser);
},
- [](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
- pfnCb(p, pUser);
+ [](uint32_t count, VkBaseOutStructure* p, void* pUser, PFN_vpStructArrayChainerCb pfnCb) {
+ pfnCb(count, p, pUser);
},
[](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
VkFormatProperties3KHR formatProperties3KHR{ VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR, nullptr };
@@ -6195,7 +6717,8 @@
pfnCb(p, pUser);
},
};
-} //namespace baseline
+} // namespace baseline
+} // namespace blocks
} // namespace VP_ANDROID_BASELINE_2021_CPU_ONLY
#endif // VP_ANDROID_baseline_2021_cpu_only
@@ -6254,7 +6777,7 @@
};
static const VpFeatureDesc featureDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: {
VkPhysicalDeviceFeatures2KHR* s = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
@@ -6294,43 +6817,43 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: {
- VkPhysicalDeviceFeatures2KHR* prettify_VkPhysicalDeviceFeatures2KHR = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.depthBiasClamp == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.depthBiasClamp == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.depthBiasClamp == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.fragmentStoresAndAtomics == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.fragmentStoresAndAtomics == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.fragmentStoresAndAtomics == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.fullDrawIndexUint32 == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.fullDrawIndexUint32 == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.fullDrawIndexUint32 == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.imageCubeArray == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.imageCubeArray == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.imageCubeArray == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.independentBlend == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.independentBlend == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.independentBlend == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.largePoints == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.largePoints == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.largePoints == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.robustBufferAccess == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.robustBufferAccess == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.robustBufferAccess == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.sampleRateShading == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.sampleRateShading == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.sampleRateShading == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderInt16 == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderInt16 == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderInt16 == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderSampledImageArrayDynamicIndexing == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderSampledImageArrayDynamicIndexing == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderSampledImageArrayDynamicIndexing == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageBufferArrayDynamicIndexing == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageBufferArrayDynamicIndexing == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderStorageBufferArrayDynamicIndexing == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageImageArrayDynamicIndexing == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageImageArrayDynamicIndexing == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderStorageImageArrayDynamicIndexing == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionASTC_LDR == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionASTC_LDR == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.textureCompressionASTC_LDR == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionETC2 == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionETC2 == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.textureCompressionETC2 == VK_TRUE");
+ VkPhysicalDeviceFeatures2KHR* s = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
+ ret = ret && (s->features.depthBiasClamp == VK_TRUE);
+ ret = ret && (s->features.fragmentStoresAndAtomics == VK_TRUE);
+ ret = ret && (s->features.fullDrawIndexUint32 == VK_TRUE);
+ ret = ret && (s->features.imageCubeArray == VK_TRUE);
+ ret = ret && (s->features.independentBlend == VK_TRUE);
+ ret = ret && (s->features.largePoints == VK_TRUE);
+ ret = ret && (s->features.robustBufferAccess == VK_TRUE);
+ ret = ret && (s->features.sampleRateShading == VK_TRUE);
+ ret = ret && (s->features.shaderInt16 == VK_TRUE);
+ ret = ret && (s->features.shaderSampledImageArrayDynamicIndexing == VK_TRUE);
+ ret = ret && (s->features.shaderStorageBufferArrayDynamicIndexing == VK_TRUE);
+ ret = ret && (s->features.shaderStorageImageArrayDynamicIndexing == VK_TRUE);
+ ret = ret && (s->features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE);
+ ret = ret && (s->features.textureCompressionASTC_LDR == VK_TRUE);
+ ret = ret && (s->features.textureCompressionETC2 == VK_TRUE);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: {
- VkPhysicalDeviceMultiviewFeatures* prettify_VkPhysicalDeviceMultiviewFeatures = static_cast<VkPhysicalDeviceMultiviewFeatures*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceMultiviewFeatures->multiview == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceMultiviewFeatures->multiview == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceMultiviewFeatures::multiview == VK_TRUE");
+ VkPhysicalDeviceMultiviewFeatures* s = static_cast<VkPhysicalDeviceMultiviewFeatures*>(static_cast<void*>(p));
+ ret = ret && (s->multiview == VK_TRUE);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: {
- VkPhysicalDeviceSamplerYcbcrConversionFeatures* prettify_VkPhysicalDeviceSamplerYcbcrConversionFeatures = static_cast<VkPhysicalDeviceSamplerYcbcrConversionFeatures*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceSamplerYcbcrConversionFeatures->samplerYcbcrConversion == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceSamplerYcbcrConversionFeatures->samplerYcbcrConversion == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceSamplerYcbcrConversionFeatures::samplerYcbcrConversion == VK_TRUE");
+ VkPhysicalDeviceSamplerYcbcrConversionFeatures* s = static_cast<VkPhysicalDeviceSamplerYcbcrConversionFeatures*>(static_cast<void*>(p));
+ ret = ret && (s->samplerYcbcrConversion == VK_TRUE);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES: {
- VkPhysicalDeviceShaderDrawParametersFeatures* prettify_VkPhysicalDeviceShaderDrawParametersFeatures = static_cast<VkPhysicalDeviceShaderDrawParametersFeatures*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceShaderDrawParametersFeatures->shaderDrawParameters == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceShaderDrawParametersFeatures->shaderDrawParameters == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceShaderDrawParametersFeatures::shaderDrawParameters == VK_TRUE");
+ VkPhysicalDeviceShaderDrawParametersFeatures* s = static_cast<VkPhysicalDeviceShaderDrawParametersFeatures*>(static_cast<void*>(p));
+ ret = ret && (s->shaderDrawParameters == VK_TRUE);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES: {
- VkPhysicalDeviceVariablePointersFeatures* prettify_VkPhysicalDeviceVariablePointersFeatures = static_cast<VkPhysicalDeviceVariablePointersFeatures*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceVariablePointersFeatures->variablePointers == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceVariablePointersFeatures->variablePointers == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceVariablePointersFeatures::variablePointers == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceVariablePointersFeatures->variablePointersStorageBuffer == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceVariablePointersFeatures->variablePointersStorageBuffer == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceVariablePointersFeatures::variablePointersStorageBuffer == VK_TRUE");
+ VkPhysicalDeviceVariablePointersFeatures* s = static_cast<VkPhysicalDeviceVariablePointersFeatures*>(static_cast<void*>(p));
+ ret = ret && (s->variablePointers == VK_TRUE);
+ ret = ret && (s->variablePointersStorageBuffer == VK_TRUE);
} break;
default: break;
}
@@ -6339,9 +6862,9 @@
};
static const VpPropertyDesc propertyDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
return ret;
}
@@ -6361,8 +6884,8 @@
p->pNext = static_cast<VkBaseOutStructure*>(static_cast<void*>(&physicalDeviceMultiviewProperties));
pfnCb(p, pUser);
},
- [](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
- pfnCb(p, pUser);
+ [](uint32_t count, VkBaseOutStructure* p, void* pUser, PFN_vpStructArrayChainerCb pfnCb) {
+ pfnCb(count, p, pUser);
},
[](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
VkFormatProperties3KHR formatProperties3KHR{ VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR, nullptr };
@@ -6371,7 +6894,9 @@
},
};
+namespace blocks {
namespace baseline {
+
static const VkExtensionProperties instanceExtensions[] = {
VkExtensionProperties{ VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME, 1 },
VkExtensionProperties{ VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, 1 },
@@ -6406,7 +6931,7 @@
};
static const VpFeatureDesc featureDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: {
VkPhysicalDeviceFeatures2KHR* s = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
@@ -6446,43 +6971,43 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR: {
- VkPhysicalDeviceFeatures2KHR* prettify_VkPhysicalDeviceFeatures2KHR = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.depthBiasClamp == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.depthBiasClamp == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.depthBiasClamp == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.fragmentStoresAndAtomics == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.fragmentStoresAndAtomics == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.fragmentStoresAndAtomics == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.fullDrawIndexUint32 == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.fullDrawIndexUint32 == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.fullDrawIndexUint32 == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.imageCubeArray == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.imageCubeArray == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.imageCubeArray == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.independentBlend == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.independentBlend == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.independentBlend == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.largePoints == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.largePoints == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.largePoints == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.robustBufferAccess == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.robustBufferAccess == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.robustBufferAccess == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.sampleRateShading == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.sampleRateShading == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.sampleRateShading == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderInt16 == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderInt16 == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderInt16 == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderSampledImageArrayDynamicIndexing == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderSampledImageArrayDynamicIndexing == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderSampledImageArrayDynamicIndexing == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageBufferArrayDynamicIndexing == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageBufferArrayDynamicIndexing == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderStorageBufferArrayDynamicIndexing == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageImageArrayDynamicIndexing == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderStorageImageArrayDynamicIndexing == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderStorageImageArrayDynamicIndexing == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionASTC_LDR == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionASTC_LDR == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.textureCompressionASTC_LDR == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionETC2 == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceFeatures2KHR->features.textureCompressionETC2 == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceFeatures2KHR::features.textureCompressionETC2 == VK_TRUE");
+ VkPhysicalDeviceFeatures2KHR* s = static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p));
+ ret = ret && (s->features.depthBiasClamp == VK_TRUE);
+ ret = ret && (s->features.fragmentStoresAndAtomics == VK_TRUE);
+ ret = ret && (s->features.fullDrawIndexUint32 == VK_TRUE);
+ ret = ret && (s->features.imageCubeArray == VK_TRUE);
+ ret = ret && (s->features.independentBlend == VK_TRUE);
+ ret = ret && (s->features.largePoints == VK_TRUE);
+ ret = ret && (s->features.robustBufferAccess == VK_TRUE);
+ ret = ret && (s->features.sampleRateShading == VK_TRUE);
+ ret = ret && (s->features.shaderInt16 == VK_TRUE);
+ ret = ret && (s->features.shaderSampledImageArrayDynamicIndexing == VK_TRUE);
+ ret = ret && (s->features.shaderStorageBufferArrayDynamicIndexing == VK_TRUE);
+ ret = ret && (s->features.shaderStorageImageArrayDynamicIndexing == VK_TRUE);
+ ret = ret && (s->features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE);
+ ret = ret && (s->features.textureCompressionASTC_LDR == VK_TRUE);
+ ret = ret && (s->features.textureCompressionETC2 == VK_TRUE);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: {
- VkPhysicalDeviceMultiviewFeatures* prettify_VkPhysicalDeviceMultiviewFeatures = static_cast<VkPhysicalDeviceMultiviewFeatures*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceMultiviewFeatures->multiview == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceMultiviewFeatures->multiview == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceMultiviewFeatures::multiview == VK_TRUE");
+ VkPhysicalDeviceMultiviewFeatures* s = static_cast<VkPhysicalDeviceMultiviewFeatures*>(static_cast<void*>(p));
+ ret = ret && (s->multiview == VK_TRUE);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: {
- VkPhysicalDeviceSamplerYcbcrConversionFeatures* prettify_VkPhysicalDeviceSamplerYcbcrConversionFeatures = static_cast<VkPhysicalDeviceSamplerYcbcrConversionFeatures*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceSamplerYcbcrConversionFeatures->samplerYcbcrConversion == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceSamplerYcbcrConversionFeatures->samplerYcbcrConversion == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceSamplerYcbcrConversionFeatures::samplerYcbcrConversion == VK_TRUE");
+ VkPhysicalDeviceSamplerYcbcrConversionFeatures* s = static_cast<VkPhysicalDeviceSamplerYcbcrConversionFeatures*>(static_cast<void*>(p));
+ ret = ret && (s->samplerYcbcrConversion == VK_TRUE);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES: {
- VkPhysicalDeviceShaderDrawParametersFeatures* prettify_VkPhysicalDeviceShaderDrawParametersFeatures = static_cast<VkPhysicalDeviceShaderDrawParametersFeatures*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceShaderDrawParametersFeatures->shaderDrawParameters == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceShaderDrawParametersFeatures->shaderDrawParameters == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceShaderDrawParametersFeatures::shaderDrawParameters == VK_TRUE");
+ VkPhysicalDeviceShaderDrawParametersFeatures* s = static_cast<VkPhysicalDeviceShaderDrawParametersFeatures*>(static_cast<void*>(p));
+ ret = ret && (s->shaderDrawParameters == VK_TRUE);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES: {
- VkPhysicalDeviceVariablePointersFeatures* prettify_VkPhysicalDeviceVariablePointersFeatures = static_cast<VkPhysicalDeviceVariablePointersFeatures*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceVariablePointersFeatures->variablePointers == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceVariablePointersFeatures->variablePointers == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceVariablePointersFeatures::variablePointers == VK_TRUE");
- ret = ret && (prettify_VkPhysicalDeviceVariablePointersFeatures->variablePointersStorageBuffer == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceVariablePointersFeatures->variablePointersStorageBuffer == VK_TRUE), "Unsupported feature condition: VkPhysicalDeviceVariablePointersFeatures::variablePointersStorageBuffer == VK_TRUE");
+ VkPhysicalDeviceVariablePointersFeatures* s = static_cast<VkPhysicalDeviceVariablePointersFeatures*>(static_cast<void*>(p));
+ ret = ret && (s->variablePointers == VK_TRUE);
+ ret = ret && (s->variablePointersStorageBuffer == VK_TRUE);
} break;
default: break;
}
@@ -6491,7 +7016,7 @@
};
static const VpPropertyDesc propertyDesc = {
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR: {
VkPhysicalDeviceProperties2KHR* s = static_cast<VkPhysicalDeviceProperties2KHR*>(static_cast<void*>(p));
@@ -6587,104 +7112,104 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR: {
- VkPhysicalDeviceProperties2KHR* prettify_VkPhysicalDeviceProperties2KHR = static_cast<VkPhysicalDeviceProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.discreteQueuePriorities >= 2); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.discreteQueuePriorities >= 2), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.discreteQueuePriorities >= 2");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferColorSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferColorSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.framebufferColorSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferDepthSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferDepthSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.framebufferDepthSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferNoAttachmentsSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferNoAttachmentsSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.framebufferNoAttachmentsSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferStencilSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.framebufferStencilSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.framebufferStencilSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxBoundDescriptorSets >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxBoundDescriptorSets >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxBoundDescriptorSets >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxColorAttachments >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxColorAttachments >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxColorAttachments >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeSharedMemorySize >= 16384); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeSharedMemorySize >= 16384), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeSharedMemorySize >= 16384");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupCount[0] >= 65535); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupCount[0] >= 65535), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupCount[0] >= 65535");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupCount[1] >= 65535); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupCount[1] >= 65535), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupCount[1] >= 65535");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupCount[2] >= 65535); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupCount[2] >= 65535), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupCount[2] >= 65535");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupInvocations >= 128); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupInvocations >= 128), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupInvocations >= 128");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupSize[0] >= 128); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupSize[0] >= 128), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupSize[0] >= 128");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupSize[1] >= 128); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupSize[1] >= 128), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupSize[1] >= 128");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupSize[2] >= 64); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxComputeWorkGroupSize[2] >= 64), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxComputeWorkGroupSize[2] >= 64");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetInputAttachments >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetInputAttachments >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetInputAttachments >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetSampledImages >= 48); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetSampledImages >= 48), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetSampledImages >= 48");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetSamplers >= 48); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetSamplers >= 48), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetSamplers >= 48");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetStorageBuffers >= 24); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetStorageBuffers >= 24), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetStorageBuffers >= 24");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetStorageBuffersDynamic >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetStorageBuffersDynamic >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetStorageBuffersDynamic >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetStorageImages >= 12); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetStorageImages >= 12), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetStorageImages >= 12");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetUniformBuffers >= 36); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetUniformBuffers >= 36), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetUniformBuffers >= 36");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetUniformBuffersDynamic >= 8); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDescriptorSetUniformBuffersDynamic >= 8), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDescriptorSetUniformBuffersDynamic >= 8");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDrawIndexedIndexValue >= 4294967295); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDrawIndexedIndexValue >= 4294967295), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDrawIndexedIndexValue >= 4294967295");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDrawIndirectCount >= 1); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxDrawIndirectCount >= 1), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxDrawIndirectCount >= 1");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFragmentCombinedOutputResources >= 8); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFragmentCombinedOutputResources >= 8), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxFragmentCombinedOutputResources >= 8");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFragmentInputComponents >= 64); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFragmentInputComponents >= 64), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxFragmentInputComponents >= 64");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFragmentOutputAttachments >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFragmentOutputAttachments >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxFragmentOutputAttachments >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFramebufferHeight >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFramebufferHeight >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxFramebufferHeight >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFramebufferLayers >= 256); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFramebufferLayers >= 256), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxFramebufferLayers >= 256");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFramebufferWidth >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxFramebufferWidth >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxFramebufferWidth >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageArrayLayers >= 256); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageArrayLayers >= 256), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxImageArrayLayers >= 256");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimension1D >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimension1D >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxImageDimension1D >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimension2D >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimension2D >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxImageDimension2D >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimension3D >= 512); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimension3D >= 512), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxImageDimension3D >= 512");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimensionCube >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxImageDimensionCube >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxImageDimensionCube >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxInterpolationOffset >= 0.4375); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxInterpolationOffset >= 0.4375), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxInterpolationOffset >= 0.4375");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxMemoryAllocationCount >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxMemoryAllocationCount >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxMemoryAllocationCount >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorInputAttachments >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorInputAttachments >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorInputAttachments >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorSampledImages >= 16); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorSampledImages >= 16), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorSampledImages >= 16");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorSamplers >= 16); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorSamplers >= 16), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorSamplers >= 16");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorStorageBuffers >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorStorageBuffers >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorStorageBuffers >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorStorageImages >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorStorageImages >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorStorageImages >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorUniformBuffers >= 12); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageDescriptorUniformBuffers >= 12), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageDescriptorUniformBuffers >= 12");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageResources >= 44); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPerStageResources >= 44), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPerStageResources >= 44");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPushConstantsSize >= 128); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxPushConstantsSize >= 128), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxPushConstantsSize >= 128");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSampleMaskWords >= 1); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSampleMaskWords >= 1), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxSampleMaskWords >= 1");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSamplerAllocationCount >= 4000); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSamplerAllocationCount >= 4000), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxSamplerAllocationCount >= 4000");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSamplerAnisotropy >= 1.0); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSamplerAnisotropy >= 1.0), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxSamplerAnisotropy >= 1.0");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSamplerLodBias >= 2.0); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxSamplerLodBias >= 2.0), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxSamplerLodBias >= 2.0");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxStorageBufferRange >= 134217728); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxStorageBufferRange >= 134217728), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxStorageBufferRange >= 134217728");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxTexelBufferElements >= 65536); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxTexelBufferElements >= 65536), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxTexelBufferElements >= 65536");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxTexelOffset >= 7); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxTexelOffset >= 7), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxTexelOffset >= 7");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxUniformBufferRange >= 16384); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxUniformBufferRange >= 16384), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxUniformBufferRange >= 16384");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputAttributeOffset >= 2047); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputAttributeOffset >= 2047), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxVertexInputAttributeOffset >= 2047");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputAttributes >= 16); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputAttributes >= 16), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxVertexInputAttributes >= 16");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputBindingStride >= 2048); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputBindingStride >= 2048), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxVertexInputBindingStride >= 2048");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputBindings >= 16); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexInputBindings >= 16), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxVertexInputBindings >= 16");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexOutputComponents >= 64); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxVertexOutputComponents >= 64), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxVertexOutputComponents >= 64");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxViewportDimensions[0] >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxViewportDimensions[0] >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxViewportDimensions[0] >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxViewportDimensions[1] >= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxViewportDimensions[1] >= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxViewportDimensions[1] >= 4096");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxViewports >= 1); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.maxViewports >= 1), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.maxViewports >= 1");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minInterpolationOffset <= -0.5); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minInterpolationOffset <= -0.5), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.minInterpolationOffset <= -0.5");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment <= 4096); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment <= 4096), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.minMemoryMapAlignment <= 4096");
- ret = ret && ((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment - 1)) == 0); VP_DEBUG_COND_MSG(!((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment - 1)) == 0), "Unsupported properties condition: (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minMemoryMapAlignment - 1)) == 0");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment <= 256); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment <= 256), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.minStorageBufferOffsetAlignment <= 256");
- ret = ret && ((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment - 1)) == 0); VP_DEBUG_COND_MSG(!((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment - 1)) == 0), "Unsupported properties condition: (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minStorageBufferOffsetAlignment - 1)) == 0");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment <= 256); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment <= 256), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.minTexelBufferOffsetAlignment <= 256");
- ret = ret && ((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment - 1)) == 0); VP_DEBUG_COND_MSG(!((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment - 1)) == 0), "Unsupported properties condition: (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelBufferOffsetAlignment - 1)) == 0");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelOffset <= -8); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minTexelOffset <= -8), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.minTexelOffset <= -8");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment <= 256); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment <= 256), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.minUniformBufferOffsetAlignment <= 256");
- ret = ret && ((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment - 1)) == 0); VP_DEBUG_COND_MSG(!((prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment - 1)) == 0), "Unsupported properties condition: (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment & (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.minUniformBufferOffsetAlignment - 1)) == 0");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.mipmapPrecisionBits >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.mipmapPrecisionBits >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.mipmapPrecisionBits >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.pointSizeGranularity <= 1); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.pointSizeGranularity <= 1), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.pointSizeGranularity <= 1");
- ret = ret && (isMultiple(1, prettify_VkPhysicalDeviceProperties2KHR->properties.limits.pointSizeGranularity)); VP_DEBUG_COND_MSG(!(isMultiple(1, prettify_VkPhysicalDeviceProperties2KHR->properties.limits.pointSizeGranularity)), "Unsupported properties condition: isMultiple(1, prettify_VkPhysicalDeviceProperties2KHR->properties.limits.pointSizeGranularity)");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.pointSizeRange[0] <= 1.0); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.pointSizeRange[0] <= 1.0), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.pointSizeRange[0] <= 1.0");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.pointSizeRange[1] >= 511); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.pointSizeRange[1] >= 511), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.pointSizeRange[1] >= 511");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageColorSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageColorSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.sampledImageColorSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageDepthSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageDepthSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.sampledImageDepthSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageIntegerSampleCounts, (VK_SAMPLE_COUNT_1_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageIntegerSampleCounts, (VK_SAMPLE_COUNT_1_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.sampledImageIntegerSampleCounts contains (VK_SAMPLE_COUNT_1_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageStencilSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.sampledImageStencilSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.sampledImageStencilSampleCounts contains (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.standardSampleLocations == VK_TRUE); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.standardSampleLocations == VK_TRUE), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.standardSampleLocations == VK_TRUE");
- ret = ret && (vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.storageImageSampleCounts, (VK_SAMPLE_COUNT_1_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.storageImageSampleCounts, (VK_SAMPLE_COUNT_1_BIT))), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.storageImageSampleCounts contains (VK_SAMPLE_COUNT_1_BIT)");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.subPixelInterpolationOffsetBits >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.subPixelInterpolationOffsetBits >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.subPixelInterpolationOffsetBits >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.subPixelPrecisionBits >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.subPixelPrecisionBits >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.subPixelPrecisionBits >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.subTexelPrecisionBits >= 4); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.subTexelPrecisionBits >= 4), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.subTexelPrecisionBits >= 4");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.viewportBoundsRange[0] <= -8192); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.viewportBoundsRange[0] <= -8192), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.viewportBoundsRange[0] <= -8192");
- ret = ret && (prettify_VkPhysicalDeviceProperties2KHR->properties.limits.viewportBoundsRange[1] >= 8191); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceProperties2KHR->properties.limits.viewportBoundsRange[1] >= 8191), "Unsupported properties condition: VkPhysicalDeviceProperties2KHR::properties.limits.viewportBoundsRange[1] >= 8191");
+ VkPhysicalDeviceProperties2KHR* s = static_cast<VkPhysicalDeviceProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (s->properties.limits.discreteQueuePriorities >= 2);
+ ret = ret && (vpCheckFlags(s->properties.limits.framebufferColorSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (vpCheckFlags(s->properties.limits.framebufferDepthSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (vpCheckFlags(s->properties.limits.framebufferNoAttachmentsSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (vpCheckFlags(s->properties.limits.framebufferStencilSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (s->properties.limits.maxBoundDescriptorSets >= 4);
+ ret = ret && (s->properties.limits.maxColorAttachments >= 4);
+ ret = ret && (s->properties.limits.maxComputeSharedMemorySize >= 16384);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupCount[0] >= 65535);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupCount[1] >= 65535);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupCount[2] >= 65535);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupInvocations >= 128);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupSize[0] >= 128);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupSize[1] >= 128);
+ ret = ret && (s->properties.limits.maxComputeWorkGroupSize[2] >= 64);
+ ret = ret && (s->properties.limits.maxDescriptorSetInputAttachments >= 4);
+ ret = ret && (s->properties.limits.maxDescriptorSetSampledImages >= 48);
+ ret = ret && (s->properties.limits.maxDescriptorSetSamplers >= 48);
+ ret = ret && (s->properties.limits.maxDescriptorSetStorageBuffers >= 24);
+ ret = ret && (s->properties.limits.maxDescriptorSetStorageBuffersDynamic >= 4);
+ ret = ret && (s->properties.limits.maxDescriptorSetStorageImages >= 12);
+ ret = ret && (s->properties.limits.maxDescriptorSetUniformBuffers >= 36);
+ ret = ret && (s->properties.limits.maxDescriptorSetUniformBuffersDynamic >= 8);
+ ret = ret && (s->properties.limits.maxDrawIndexedIndexValue >= 4294967295);
+ ret = ret && (s->properties.limits.maxDrawIndirectCount >= 1);
+ ret = ret && (s->properties.limits.maxFragmentCombinedOutputResources >= 8);
+ ret = ret && (s->properties.limits.maxFragmentInputComponents >= 64);
+ ret = ret && (s->properties.limits.maxFragmentOutputAttachments >= 4);
+ ret = ret && (s->properties.limits.maxFramebufferHeight >= 4096);
+ ret = ret && (s->properties.limits.maxFramebufferLayers >= 256);
+ ret = ret && (s->properties.limits.maxFramebufferWidth >= 4096);
+ ret = ret && (s->properties.limits.maxImageArrayLayers >= 256);
+ ret = ret && (s->properties.limits.maxImageDimension1D >= 4096);
+ ret = ret && (s->properties.limits.maxImageDimension2D >= 4096);
+ ret = ret && (s->properties.limits.maxImageDimension3D >= 512);
+ ret = ret && (s->properties.limits.maxImageDimensionCube >= 4096);
+ ret = ret && (s->properties.limits.maxInterpolationOffset >= 0.4375);
+ ret = ret && (s->properties.limits.maxMemoryAllocationCount >= 4096);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorInputAttachments >= 4);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorSampledImages >= 16);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorSamplers >= 16);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorStorageBuffers >= 4);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorStorageImages >= 4);
+ ret = ret && (s->properties.limits.maxPerStageDescriptorUniformBuffers >= 12);
+ ret = ret && (s->properties.limits.maxPerStageResources >= 44);
+ ret = ret && (s->properties.limits.maxPushConstantsSize >= 128);
+ ret = ret && (s->properties.limits.maxSampleMaskWords >= 1);
+ ret = ret && (s->properties.limits.maxSamplerAllocationCount >= 4000);
+ ret = ret && (s->properties.limits.maxSamplerAnisotropy >= 1.0);
+ ret = ret && (s->properties.limits.maxSamplerLodBias >= 2.0);
+ ret = ret && (s->properties.limits.maxStorageBufferRange >= 134217728);
+ ret = ret && (s->properties.limits.maxTexelBufferElements >= 65536);
+ ret = ret && (s->properties.limits.maxTexelOffset >= 7);
+ ret = ret && (s->properties.limits.maxUniformBufferRange >= 16384);
+ ret = ret && (s->properties.limits.maxVertexInputAttributeOffset >= 2047);
+ ret = ret && (s->properties.limits.maxVertexInputAttributes >= 16);
+ ret = ret && (s->properties.limits.maxVertexInputBindingStride >= 2048);
+ ret = ret && (s->properties.limits.maxVertexInputBindings >= 16);
+ ret = ret && (s->properties.limits.maxVertexOutputComponents >= 64);
+ ret = ret && (s->properties.limits.maxViewportDimensions[0] >= 4096);
+ ret = ret && (s->properties.limits.maxViewportDimensions[1] >= 4096);
+ ret = ret && (s->properties.limits.maxViewports >= 1);
+ ret = ret && (s->properties.limits.minInterpolationOffset <= -0.5);
+ ret = ret && (s->properties.limits.minMemoryMapAlignment <= 4096);
+ ret = ret && ((s->properties.limits.minMemoryMapAlignment & (s->properties.limits.minMemoryMapAlignment - 1)) == 0);
+ ret = ret && (s->properties.limits.minStorageBufferOffsetAlignment <= 256);
+ ret = ret && ((s->properties.limits.minStorageBufferOffsetAlignment & (s->properties.limits.minStorageBufferOffsetAlignment - 1)) == 0);
+ ret = ret && (s->properties.limits.minTexelBufferOffsetAlignment <= 256);
+ ret = ret && ((s->properties.limits.minTexelBufferOffsetAlignment & (s->properties.limits.minTexelBufferOffsetAlignment - 1)) == 0);
+ ret = ret && (s->properties.limits.minTexelOffset <= -8);
+ ret = ret && (s->properties.limits.minUniformBufferOffsetAlignment <= 256);
+ ret = ret && ((s->properties.limits.minUniformBufferOffsetAlignment & (s->properties.limits.minUniformBufferOffsetAlignment - 1)) == 0);
+ ret = ret && (s->properties.limits.mipmapPrecisionBits >= 4);
+ ret = ret && (s->properties.limits.pointSizeGranularity <= 1);
+ ret = ret && (isMultiple(1, s->properties.limits.pointSizeGranularity));
+ ret = ret && (s->properties.limits.pointSizeRange[0] <= 1.0);
+ ret = ret && (s->properties.limits.pointSizeRange[1] >= 511);
+ ret = ret && (vpCheckFlags(s->properties.limits.sampledImageColorSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (vpCheckFlags(s->properties.limits.sampledImageDepthSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (vpCheckFlags(s->properties.limits.sampledImageIntegerSampleCounts, (VK_SAMPLE_COUNT_1_BIT)));
+ ret = ret && (vpCheckFlags(s->properties.limits.sampledImageStencilSampleCounts, (VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT)));
+ ret = ret && (s->properties.limits.standardSampleLocations == VK_TRUE);
+ ret = ret && (vpCheckFlags(s->properties.limits.storageImageSampleCounts, (VK_SAMPLE_COUNT_1_BIT)));
+ ret = ret && (s->properties.limits.subPixelInterpolationOffsetBits >= 4);
+ ret = ret && (s->properties.limits.subPixelPrecisionBits >= 4);
+ ret = ret && (s->properties.limits.subTexelPrecisionBits >= 4);
+ ret = ret && (s->properties.limits.viewportBoundsRange[0] <= -8192);
+ ret = ret && (s->properties.limits.viewportBoundsRange[1] >= 8191);
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES: {
- VkPhysicalDeviceMultiviewProperties* prettify_VkPhysicalDeviceMultiviewProperties = static_cast<VkPhysicalDeviceMultiviewProperties*>(static_cast<void*>(p));
- ret = ret && (prettify_VkPhysicalDeviceMultiviewProperties->maxMultiviewInstanceIndex >= 134217727); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceMultiviewProperties->maxMultiviewInstanceIndex >= 134217727), "Unsupported properties condition: VkPhysicalDeviceMultiviewProperties::maxMultiviewInstanceIndex >= 134217727");
- ret = ret && (prettify_VkPhysicalDeviceMultiviewProperties->maxMultiviewViewCount >= 6); VP_DEBUG_COND_MSG(!(prettify_VkPhysicalDeviceMultiviewProperties->maxMultiviewViewCount >= 6), "Unsupported properties condition: VkPhysicalDeviceMultiviewProperties::maxMultiviewViewCount >= 6");
+ VkPhysicalDeviceMultiviewProperties* s = static_cast<VkPhysicalDeviceMultiviewProperties*>(static_cast<void*>(p));
+ ret = ret && (s->maxMultiviewInstanceIndex >= 134217727);
+ ret = ret && (s->maxMultiviewViewCount >= 6);
} break;
default: break;
}
@@ -6695,7 +7220,7 @@
static const VpFormatDesc formatDesc[] = {
{
VK_FORMAT_A1R5G5B5_UNORM_PACK16,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -6705,13 +7230,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A1R5G5B5_UNORM_PACK16: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A1R5G5B5_UNORM_PACK16: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -6720,7 +7245,7 @@
},
{
VK_FORMAT_A2B10G10R10_UINT_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -6731,14 +7256,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_A2B10G10R10_UINT_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A2B10G10R10_UINT_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A2B10G10R10_UINT_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -6747,7 +7272,7 @@
},
{
VK_FORMAT_A2B10G10R10_UNORM_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -6758,14 +7283,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_A2B10G10R10_UNORM_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A2B10G10R10_UNORM_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A2B10G10R10_UNORM_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -6774,7 +7299,7 @@
},
{
VK_FORMAT_A8B8G8R8_SINT_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -6785,14 +7310,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SINT_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SINT_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SINT_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -6801,7 +7326,7 @@
},
{
VK_FORMAT_A8B8G8R8_SNORM_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -6812,14 +7337,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SNORM_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SNORM_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SNORM_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -6828,7 +7353,7 @@
},
{
VK_FORMAT_A8B8G8R8_SRGB_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -6838,13 +7363,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SRGB_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_SRGB_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -6853,7 +7378,7 @@
},
{
VK_FORMAT_A8B8G8R8_UINT_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -6864,14 +7389,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_UINT_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_UINT_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_UINT_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -6880,7 +7405,7 @@
},
{
VK_FORMAT_A8B8G8R8_UNORM_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -6891,14 +7416,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_UNORM_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_UNORM_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_A8B8G8R8_UNORM_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -6907,7 +7432,7 @@
},
{
VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -6917,13 +7442,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x10_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x10_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -6932,7 +7457,7 @@
},
{
VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -6942,13 +7467,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x10_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x10_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -6957,7 +7482,7 @@
},
{
VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -6967,13 +7492,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -6982,7 +7507,7 @@
},
{
VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -6992,13 +7517,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7007,7 +7532,7 @@
},
{
VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7017,13 +7542,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x6_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x6_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7032,7 +7557,7 @@
},
{
VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7042,13 +7567,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x6_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x6_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7057,7 +7582,7 @@
},
{
VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7067,13 +7592,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7082,7 +7607,7 @@
},
{
VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7092,13 +7617,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_10x8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7107,7 +7632,7 @@
},
{
VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7117,13 +7642,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x10_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x10_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7132,7 +7657,7 @@
},
{
VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7142,13 +7667,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x10_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x10_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7157,7 +7682,7 @@
},
{
VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7167,13 +7692,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x12_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x12_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7182,7 +7707,7 @@
},
{
VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7192,13 +7717,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x12_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_12x12_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7207,7 +7732,7 @@
},
{
VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7217,13 +7742,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_4x4_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_4x4_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7232,7 +7757,7 @@
},
{
VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7242,13 +7767,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_4x4_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_4x4_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7257,7 +7782,7 @@
},
{
VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7267,13 +7792,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x4_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x4_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7282,7 +7807,7 @@
},
{
VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7292,13 +7817,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x4_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x4_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7307,7 +7832,7 @@
},
{
VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7317,13 +7842,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7332,7 +7857,7 @@
},
{
VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7342,13 +7867,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_5x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7357,7 +7882,7 @@
},
{
VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7367,13 +7892,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7382,7 +7907,7 @@
},
{
VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7392,13 +7917,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7407,7 +7932,7 @@
},
{
VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7417,13 +7942,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x6_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x6_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7432,7 +7957,7 @@
},
{
VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7442,13 +7967,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x6_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_6x6_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7457,7 +7982,7 @@
},
{
VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7467,13 +7992,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x5_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7482,7 +8007,7 @@
},
{
VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7492,13 +8017,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x5_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7507,7 +8032,7 @@
},
{
VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7517,13 +8042,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x6_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x6_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7532,7 +8057,7 @@
},
{
VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7542,13 +8067,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x6_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x6_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7557,7 +8082,7 @@
},
{
VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7567,13 +8092,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7582,7 +8107,7 @@
},
{
VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7592,13 +8117,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ASTC_8x8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7607,7 +8132,7 @@
},
{
VK_FORMAT_B10G11R11_UFLOAT_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7618,14 +8143,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_B10G11R11_UFLOAT_PACK32: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B10G11R11_UFLOAT_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B10G11R11_UFLOAT_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7634,7 +8159,7 @@
},
{
VK_FORMAT_B4G4R4A4_UNORM_PACK16,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7644,13 +8169,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B4G4R4A4_UNORM_PACK16: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B4G4R4A4_UNORM_PACK16: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7659,7 +8184,7 @@
},
{
VK_FORMAT_B8G8R8A8_SRGB,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7669,13 +8194,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B8G8R8A8_SRGB: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B8G8R8A8_SRGB: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7684,7 +8209,7 @@
},
{
VK_FORMAT_B8G8R8A8_UNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7695,14 +8220,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_B8G8R8A8_UNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B8G8R8A8_UNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_B8G8R8A8_UNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7711,7 +8236,7 @@
},
{
VK_FORMAT_D16_UNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7720,12 +8245,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_D16_UNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7734,7 +8259,7 @@
},
{
VK_FORMAT_D32_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7743,12 +8268,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_D32_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7757,7 +8282,7 @@
},
{
VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7767,13 +8292,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7782,7 +8307,7 @@
},
{
VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7792,13 +8317,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11G11_SNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11G11_SNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7807,7 +8332,7 @@
},
{
VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7817,13 +8342,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11G11_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11G11_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7832,7 +8357,7 @@
},
{
VK_FORMAT_EAC_R11_SNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7842,13 +8367,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11_SNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11_SNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7857,7 +8382,7 @@
},
{
VK_FORMAT_EAC_R11_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7867,13 +8392,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_EAC_R11_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7882,7 +8407,7 @@
},
{
VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7892,13 +8417,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7907,7 +8432,7 @@
},
{
VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7917,13 +8442,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7932,7 +8457,7 @@
},
{
VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7942,13 +8467,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7957,7 +8482,7 @@
},
{
VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7967,13 +8492,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -7982,7 +8507,7 @@
},
{
VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -7992,13 +8517,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8007,7 +8532,7 @@
},
{
VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8017,13 +8542,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8032,7 +8557,7 @@
},
{
VK_FORMAT_R16G16B16A16_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8043,14 +8568,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SFLOAT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SFLOAT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8059,7 +8584,7 @@
},
{
VK_FORMAT_R16G16B16A16_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8070,14 +8595,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8086,7 +8611,7 @@
},
{
VK_FORMAT_R16G16B16A16_SNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8095,12 +8620,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_SNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
} break;
default: break;
}
@@ -8109,7 +8634,7 @@
},
{
VK_FORMAT_R16G16B16A16_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8120,14 +8645,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16B16A16_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8136,7 +8661,7 @@
},
{
VK_FORMAT_R16G16_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8147,14 +8672,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SFLOAT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SFLOAT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8163,7 +8688,7 @@
},
{
VK_FORMAT_R16G16_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8174,14 +8699,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8190,7 +8715,7 @@
},
{
VK_FORMAT_R16G16_SNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8199,12 +8724,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_SNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
} break;
default: break;
}
@@ -8213,7 +8738,7 @@
},
{
VK_FORMAT_R16G16_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8223,13 +8748,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16G16_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8238,7 +8763,7 @@
},
{
VK_FORMAT_R16_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8249,14 +8774,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16_SFLOAT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16_SFLOAT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8265,7 +8790,7 @@
},
{
VK_FORMAT_R16_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8276,14 +8801,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8292,7 +8817,7 @@
},
{
VK_FORMAT_R16_SNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8301,12 +8826,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16_SNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
} break;
default: break;
}
@@ -8315,7 +8840,7 @@
},
{
VK_FORMAT_R16_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8326,14 +8851,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R16_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8342,7 +8867,7 @@
},
{
VK_FORMAT_R16_UNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8351,12 +8876,12 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R16_UNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
} break;
default: break;
}
@@ -8365,7 +8890,7 @@
},
{
VK_FORMAT_R32G32B32A32_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8375,13 +8900,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32B32A32_SFLOAT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32B32A32_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8390,7 +8915,7 @@
},
{
VK_FORMAT_R32G32B32A32_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8400,13 +8925,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32B32A32_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32B32A32_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8415,7 +8940,7 @@
},
{
VK_FORMAT_R32G32B32A32_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8425,13 +8950,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32B32A32_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32B32A32_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8440,7 +8965,7 @@
},
{
VK_FORMAT_R32G32_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8451,14 +8976,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_SFLOAT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_SFLOAT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8467,7 +8992,7 @@
},
{
VK_FORMAT_R32G32_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8478,14 +9003,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8494,7 +9019,7 @@
},
{
VK_FORMAT_R32G32_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8505,14 +9030,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32G32_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8521,7 +9046,7 @@
},
{
VK_FORMAT_R32_SFLOAT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8532,14 +9057,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R32_SFLOAT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32_SFLOAT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32_SFLOAT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8548,7 +9073,7 @@
},
{
VK_FORMAT_R32_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8559,14 +9084,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R32_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8575,7 +9100,7 @@
},
{
VK_FORMAT_R32_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8586,14 +9111,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R32_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R32_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8602,7 +9127,7 @@
},
{
VK_FORMAT_R5G6B5_UNORM_PACK16,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8612,13 +9137,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R5G6B5_UNORM_PACK16: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R5G6B5_UNORM_PACK16: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8627,7 +9152,7 @@
},
{
VK_FORMAT_R8G8B8A8_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8638,14 +9163,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8654,7 +9179,7 @@
},
{
VK_FORMAT_R8G8B8A8_SNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8665,14 +9190,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8681,7 +9206,7 @@
},
{
VK_FORMAT_R8G8B8A8_SRGB,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8691,13 +9216,13 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SRGB: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_SRGB: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8706,7 +9231,7 @@
},
{
VK_FORMAT_R8G8B8A8_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8717,14 +9242,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8733,7 +9258,7 @@
},
{
VK_FORMAT_R8G8B8A8_UNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8744,14 +9269,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_UNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_UNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8B8A8_UNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8760,7 +9285,7 @@
},
{
VK_FORMAT_R8G8_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8771,14 +9296,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8787,7 +9312,7 @@
},
{
VK_FORMAT_R8G8_SNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8798,14 +9323,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_SNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_SNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_SNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8814,7 +9339,7 @@
},
{
VK_FORMAT_R8G8_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8825,14 +9350,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8841,7 +9366,7 @@
},
{
VK_FORMAT_R8G8_UNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8852,14 +9377,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_UNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_UNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8G8_UNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8868,7 +9393,7 @@
},
{
VK_FORMAT_R8_SINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8879,14 +9404,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8_SINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_SINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_SINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8895,7 +9420,7 @@
},
{
VK_FORMAT_R8_SNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8906,14 +9431,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8_SNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_SNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_SNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8922,7 +9447,7 @@
},
{
VK_FORMAT_R8_UINT,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8933,14 +9458,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8_UINT: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_UINT: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_UINT: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8949,7 +9474,7 @@
},
{
VK_FORMAT_R8_UNORM,
- [](VkBaseOutStructure* p) {
+ [](VkBaseOutStructure* p) { (void)p;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
@@ -8960,14 +9485,14 @@
default: break;
}
},
- [](VkBaseOutStructure* p) -> bool {
+ [](VkBaseOutStructure* p) -> bool { (void)p;
bool ret = true;
switch (p->sType) {
case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR: {
- VkFormatProperties2KHR* prettify_VkFormatProperties2KHR = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT))), "Unsupported format condition for VK_FORMAT_R8_UNORM: VkFormatProperties2KHR::formatProperties.bufferFeatures contains (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_UNORM: VkFormatProperties2KHR::formatProperties.linearTilingFeatures contains (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
- ret = ret && (vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))); VP_DEBUG_COND_MSG(!(vpCheckFlags(prettify_VkFormatProperties2KHR->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT))), "Unsupported format condition for VK_FORMAT_R8_UNORM: VkFormatProperties2KHR::formatProperties.optimalTilingFeatures contains (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)");
+ VkFormatProperties2KHR* s = static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p));
+ ret = ret && (vpCheckFlags(s->formatProperties.bufferFeatures, (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.linearTilingFeatures, (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
+ ret = ret && (vpCheckFlags(s->formatProperties.optimalTilingFeatures, (VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)));
} break;
default: break;
}
@@ -8990,8 +9515,8 @@
p->pNext = static_cast<VkBaseOutStructure*>(static_cast<void*>(&physicalDeviceMultiviewProperties));
pfnCb(p, pUser);
},
- [](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
- pfnCb(p, pUser);
+ [](uint32_t count, VkBaseOutStructure* p, void* pUser, PFN_vpStructArrayChainerCb pfnCb) {
+ pfnCb(count, p, pUser);
},
[](VkBaseOutStructure* p, void* pUser, PFN_vpStructChainerCb pfnCb) {
VkFormatProperties3KHR formatProperties3KHR{ VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR, nullptr };
@@ -8999,105 +9524,113 @@
pfnCb(p, pUser);
},
};
-} //namespace baseline
+} // namespace baseline
+} // namespace blocks
} // namespace VP_ANDROID_BASELINE_2022
#endif // VP_ANDROID_baseline_2022
#ifdef VP_ANDROID_15_minimums
namespace VP_ANDROID_15_MINIMUMS {
- namespace MUST {
- static const VpVariantDesc variants[] = {
- {
- "MUST",
- static_cast<uint32_t>(std::size(MUST::instanceExtensions)), MUST::instanceExtensions,
- static_cast<uint32_t>(std::size(MUST::deviceExtensions)), MUST::deviceExtensions,
- static_cast<uint32_t>(std::size(featureStructTypes)), featureStructTypes,
- MUST::featureDesc,
- static_cast<uint32_t>(std::size(propertyStructTypes)), propertyStructTypes,
- MUST::propertyDesc,
- 0, nullptr,
- 0, nullptr,
- static_cast<uint32_t>(std::size(formatStructTypes)), formatStructTypes,
- static_cast<uint32_t>(std::size(MUST::formatDesc)), MUST::formatDesc,
- MUST::chainerDesc,
- },
- };
- static const uint32_t variantCount = static_cast<uint32_t>(std::size(variants));
- } // namespace MUST
+ namespace blocks {
+ namespace MUST {
+ static const VpVariantDesc variants[] = {
+ {
+ "MUST",
+ static_cast<uint32_t>(std::size(blocks::MUST::instanceExtensions)), blocks::MUST::instanceExtensions,
+ static_cast<uint32_t>(std::size(blocks::MUST::deviceExtensions)), blocks::MUST::deviceExtensions,
+ static_cast<uint32_t>(std::size(featureStructTypes)), featureStructTypes,
+ blocks::MUST::featureDesc,
+ static_cast<uint32_t>(std::size(propertyStructTypes)), propertyStructTypes,
+ blocks::MUST::propertyDesc,
+ 0, nullptr,
+ 0, nullptr,
+ static_cast<uint32_t>(std::size(formatStructTypes)), formatStructTypes,
+ static_cast<uint32_t>(std::size(blocks::MUST::formatDesc)), blocks::MUST::formatDesc,
+ blocks::MUST::chainerDesc,
+ 0, nullptr,
+ },
+ };
+ static const uint32_t variantCount = static_cast<uint32_t>(std::size(variants));
+ } // namespace MUST
- namespace primitivesGeneratedQuery_pipelineStatisticsQuery_ {
- static const VpVariantDesc variants[] = {
- {
- "primitivesGeneratedQuery",
- 0, nullptr,
- static_cast<uint32_t>(std::size(primitivesGeneratedQuery::deviceExtensions)), primitivesGeneratedQuery::deviceExtensions,
- static_cast<uint32_t>(std::size(featureStructTypes)), featureStructTypes,
- primitivesGeneratedQuery::featureDesc,
- 0, nullptr,
- primitivesGeneratedQuery::propertyDesc,
- 0, nullptr,
- 0, nullptr,
- 0, nullptr,
- 0, nullptr,
- primitivesGeneratedQuery::chainerDesc,
- },
- {
- "pipelineStatisticsQuery",
- 0, nullptr,
- 0, nullptr,
- static_cast<uint32_t>(std::size(featureStructTypes)), featureStructTypes,
- pipelineStatisticsQuery::featureDesc,
- 0, nullptr,
- pipelineStatisticsQuery::propertyDesc,
- 0, nullptr,
- 0, nullptr,
- 0, nullptr,
- 0, nullptr,
- pipelineStatisticsQuery::chainerDesc,
- },
- };
- static const uint32_t variantCount = static_cast<uint32_t>(std::size(variants));
- } // namespace primitivesGeneratedQuery_pipelineStatisticsQuery_
+ namespace primitivesGeneratedQuery_pipelineStatisticsQuery_ {
+ static const VpVariantDesc variants[] = {
+ {
+ "primitivesGeneratedQuery",
+ 0, nullptr,
+ static_cast<uint32_t>(std::size(blocks::primitivesGeneratedQuery::deviceExtensions)), blocks::primitivesGeneratedQuery::deviceExtensions,
+ static_cast<uint32_t>(std::size(featureStructTypes)), featureStructTypes,
+ blocks::primitivesGeneratedQuery::featureDesc,
+ 0, nullptr,
+ blocks::primitivesGeneratedQuery::propertyDesc,
+ 0, nullptr,
+ 0, nullptr,
+ 0, nullptr,
+ 0, nullptr,
+ blocks::primitivesGeneratedQuery::chainerDesc,
+ 0, nullptr,
+ },
+ {
+ "pipelineStatisticsQuery",
+ 0, nullptr,
+ 0, nullptr,
+ static_cast<uint32_t>(std::size(featureStructTypes)), featureStructTypes,
+ blocks::pipelineStatisticsQuery::featureDesc,
+ 0, nullptr,
+ blocks::pipelineStatisticsQuery::propertyDesc,
+ 0, nullptr,
+ 0, nullptr,
+ 0, nullptr,
+ 0, nullptr,
+ blocks::pipelineStatisticsQuery::chainerDesc,
+ 0, nullptr,
+ },
+ };
+ static const uint32_t variantCount = static_cast<uint32_t>(std::size(variants));
+ } // namespace primitivesGeneratedQuery_pipelineStatisticsQuery_
- namespace swBresenhamLines_hwBresenhamLines_ {
- static const VpVariantDesc variants[] = {
- {
- "swBresenhamLines",
- 0, nullptr,
- static_cast<uint32_t>(std::size(swBresenhamLines::deviceExtensions)), swBresenhamLines::deviceExtensions,
- static_cast<uint32_t>(std::size(featureStructTypes)), featureStructTypes,
- swBresenhamLines::featureDesc,
- 0, nullptr,
- swBresenhamLines::propertyDesc,
- 0, nullptr,
- 0, nullptr,
- 0, nullptr,
- 0, nullptr,
- swBresenhamLines::chainerDesc,
- },
- {
- "hwBresenhamLines",
- 0, nullptr,
- static_cast<uint32_t>(std::size(hwBresenhamLines::deviceExtensions)), hwBresenhamLines::deviceExtensions,
- static_cast<uint32_t>(std::size(featureStructTypes)), featureStructTypes,
- hwBresenhamLines::featureDesc,
- 0, nullptr,
- hwBresenhamLines::propertyDesc,
- 0, nullptr,
- 0, nullptr,
- 0, nullptr,
- 0, nullptr,
- hwBresenhamLines::chainerDesc,
- },
- };
- static const uint32_t variantCount = static_cast<uint32_t>(std::size(variants));
- } // namespace swBresenhamLines_hwBresenhamLines_
+ namespace swBresenhamLines_hwBresenhamLines_ {
+ static const VpVariantDesc variants[] = {
+ {
+ "swBresenhamLines",
+ 0, nullptr,
+ static_cast<uint32_t>(std::size(blocks::swBresenhamLines::deviceExtensions)), blocks::swBresenhamLines::deviceExtensions,
+ static_cast<uint32_t>(std::size(featureStructTypes)), featureStructTypes,
+ blocks::swBresenhamLines::featureDesc,
+ 0, nullptr,
+ blocks::swBresenhamLines::propertyDesc,
+ 0, nullptr,
+ 0, nullptr,
+ 0, nullptr,
+ 0, nullptr,
+ blocks::swBresenhamLines::chainerDesc,
+ 0, nullptr,
+ },
+ {
+ "hwBresenhamLines",
+ 0, nullptr,
+ static_cast<uint32_t>(std::size(blocks::hwBresenhamLines::deviceExtensions)), blocks::hwBresenhamLines::deviceExtensions,
+ static_cast<uint32_t>(std::size(featureStructTypes)), featureStructTypes,
+ blocks::hwBresenhamLines::featureDesc,
+ 0, nullptr,
+ blocks::hwBresenhamLines::propertyDesc,
+ 0, nullptr,
+ 0, nullptr,
+ 0, nullptr,
+ 0, nullptr,
+ blocks::hwBresenhamLines::chainerDesc,
+ 0, nullptr,
+ },
+ };
+ static const uint32_t variantCount = static_cast<uint32_t>(std::size(variants));
+ } // namespace swBresenhamLines_hwBresenhamLines_
+ } // namespace blocks
static const VpCapabilitiesDesc capabilities[] = {
- MUST::variantCount, MUST::variants,
- primitivesGeneratedQuery_pipelineStatisticsQuery_::variantCount, primitivesGeneratedQuery_pipelineStatisticsQuery_::variants,
- swBresenhamLines_hwBresenhamLines_::variantCount, swBresenhamLines_hwBresenhamLines_::variants,
+ { blocks::MUST::variantCount, blocks::MUST::variants },
+ { blocks::primitivesGeneratedQuery_pipelineStatisticsQuery_::variantCount, blocks::primitivesGeneratedQuery_pipelineStatisticsQuery_::variants },
+ { blocks::swBresenhamLines_hwBresenhamLines_::variantCount, blocks::swBresenhamLines_hwBresenhamLines_::variants },
};
static const uint32_t capabilityCount = static_cast<uint32_t>(std::size(capabilities));
@@ -9108,9 +9641,85 @@
} // namespace VP_ANDROID_15_MINIMUMS
#endif //VP_ANDROID_15_minimums
+#ifdef VP_ANDROID_16_minimums
+namespace VP_ANDROID_16_MINIMUMS {
+ namespace blocks {
+ namespace MUST {
+ static const VpVariantDesc variants[] = {
+ {
+ "MUST",
+ 0, nullptr,
+ static_cast<uint32_t>(std::size(blocks::MUST::deviceExtensions)), blocks::MUST::deviceExtensions,
+ static_cast<uint32_t>(std::size(featureStructTypes)), featureStructTypes,
+ blocks::MUST::featureDesc,
+ static_cast<uint32_t>(std::size(propertyStructTypes)), propertyStructTypes,
+ blocks::MUST::propertyDesc,
+ 0, nullptr,
+ 0, nullptr,
+ 0, nullptr,
+ 0, nullptr,
+ blocks::MUST::chainerDesc,
+ 0, nullptr,
+ },
+ };
+ static const uint32_t variantCount = static_cast<uint32_t>(std::size(variants));
+ } // namespace MUST
+
+ namespace multisampledToSingleSampled_shaderStencilExport_ {
+ static const VpVariantDesc variants[] = {
+ {
+ "multisampledToSingleSampled",
+ 0, nullptr,
+ static_cast<uint32_t>(std::size(blocks::multisampledToSingleSampled::deviceExtensions)), blocks::multisampledToSingleSampled::deviceExtensions,
+ 0, nullptr,
+ blocks::multisampledToSingleSampled::featureDesc,
+ 0, nullptr,
+ blocks::multisampledToSingleSampled::propertyDesc,
+ 0, nullptr,
+ 0, nullptr,
+ 0, nullptr,
+ 0, nullptr,
+ blocks::multisampledToSingleSampled::chainerDesc,
+ 0, nullptr,
+ },
+ {
+ "shaderStencilExport",
+ 0, nullptr,
+ static_cast<uint32_t>(std::size(blocks::shaderStencilExport::deviceExtensions)), blocks::shaderStencilExport::deviceExtensions,
+ 0, nullptr,
+ blocks::shaderStencilExport::featureDesc,
+ 0, nullptr,
+ blocks::shaderStencilExport::propertyDesc,
+ 0, nullptr,
+ 0, nullptr,
+ 0, nullptr,
+ 0, nullptr,
+ blocks::shaderStencilExport::chainerDesc,
+ 0, nullptr,
+ },
+ };
+ static const uint32_t variantCount = static_cast<uint32_t>(std::size(variants));
+ } // namespace multisampledToSingleSampled_shaderStencilExport_
+ } // namespace blocks
+
+ static const VpCapabilitiesDesc capabilities[] = {
+ { blocks::MUST::variantCount, blocks::MUST::variants },
+ { blocks::multisampledToSingleSampled_shaderStencilExport_::variantCount, blocks::multisampledToSingleSampled_shaderStencilExport_::variants },
+ };
+ static const uint32_t capabilityCount = static_cast<uint32_t>(std::size(capabilities));
+
+ static const VpProfileProperties profiles[] = {
+ {VP_ANDROID_BASELINE_2022_NAME, VP_ANDROID_BASELINE_2022_SPEC_VERSION},
+ {VP_ANDROID_15_MINIMUMS_NAME, VP_ANDROID_15_MINIMUMS_SPEC_VERSION},
+ };
+ static const uint32_t profileCount = static_cast<uint32_t>(std::size(profiles));
+} // namespace VP_ANDROID_16_MINIMUMS
+#endif //VP_ANDROID_16_minimums
+
#ifdef VP_ANDROID_baseline_2021
namespace VP_ANDROID_BASELINE_2021 {
static const VpVariantDesc mergedCapabilities[] = {
+ {
"MERGED",
static_cast<uint32_t>(std::size(instanceExtensions)), instanceExtensions,
static_cast<uint32_t>(std::size(deviceExtensions)), deviceExtensions,
@@ -9123,30 +9732,35 @@
0, nullptr,
0, nullptr,
chainerDesc,
+ 0, nullptr,
+ },
};
- namespace baseline {
- static const VpVariantDesc variants[] = {
- {
- "baseline",
- static_cast<uint32_t>(std::size(baseline::instanceExtensions)), baseline::instanceExtensions,
- static_cast<uint32_t>(std::size(baseline::deviceExtensions)), baseline::deviceExtensions,
- static_cast<uint32_t>(std::size(featureStructTypes)), featureStructTypes,
- baseline::featureDesc,
- static_cast<uint32_t>(std::size(propertyStructTypes)), propertyStructTypes,
- baseline::propertyDesc,
- 0, nullptr,
- 0, nullptr,
- static_cast<uint32_t>(std::size(formatStructTypes)), formatStructTypes,
- static_cast<uint32_t>(std::size(baseline::formatDesc)), baseline::formatDesc,
- baseline::chainerDesc,
- },
- };
- static const uint32_t variantCount = static_cast<uint32_t>(std::size(variants));
- } // namespace baseline
+ namespace blocks {
+ namespace baseline {
+ static const VpVariantDesc variants[] = {
+ {
+ "baseline",
+ static_cast<uint32_t>(std::size(blocks::baseline::instanceExtensions)), blocks::baseline::instanceExtensions,
+ static_cast<uint32_t>(std::size(blocks::baseline::deviceExtensions)), blocks::baseline::deviceExtensions,
+ static_cast<uint32_t>(std::size(featureStructTypes)), featureStructTypes,
+ blocks::baseline::featureDesc,
+ static_cast<uint32_t>(std::size(propertyStructTypes)), propertyStructTypes,
+ blocks::baseline::propertyDesc,
+ 0, nullptr,
+ 0, nullptr,
+ static_cast<uint32_t>(std::size(formatStructTypes)), formatStructTypes,
+ static_cast<uint32_t>(std::size(blocks::baseline::formatDesc)), blocks::baseline::formatDesc,
+ blocks::baseline::chainerDesc,
+ 0, nullptr,
+ },
+ };
+ static const uint32_t variantCount = static_cast<uint32_t>(std::size(variants));
+ } // namespace baseline
+ } // namespace blocks
static const VpCapabilitiesDesc capabilities[] = {
- baseline::variantCount, baseline::variants,
+ { blocks::baseline::variantCount, blocks::baseline::variants },
};
static const uint32_t capabilityCount = static_cast<uint32_t>(std::size(capabilities));
} // namespace VP_ANDROID_BASELINE_2021
@@ -9155,6 +9769,7 @@
#ifdef VP_ANDROID_baseline_2021_cpu_only
namespace VP_ANDROID_BASELINE_2021_CPU_ONLY {
static const VpVariantDesc mergedCapabilities[] = {
+ {
"MERGED",
static_cast<uint32_t>(std::size(instanceExtensions)), instanceExtensions,
static_cast<uint32_t>(std::size(deviceExtensions)), deviceExtensions,
@@ -9167,30 +9782,35 @@
0, nullptr,
0, nullptr,
chainerDesc,
+ 0, nullptr,
+ },
};
- namespace baseline {
- static const VpVariantDesc variants[] = {
- {
- "baseline",
- static_cast<uint32_t>(std::size(baseline::instanceExtensions)), baseline::instanceExtensions,
- static_cast<uint32_t>(std::size(baseline::deviceExtensions)), baseline::deviceExtensions,
- static_cast<uint32_t>(std::size(featureStructTypes)), featureStructTypes,
- baseline::featureDesc,
- static_cast<uint32_t>(std::size(propertyStructTypes)), propertyStructTypes,
- baseline::propertyDesc,
- 0, nullptr,
- 0, nullptr,
- static_cast<uint32_t>(std::size(formatStructTypes)), formatStructTypes,
- static_cast<uint32_t>(std::size(baseline::formatDesc)), baseline::formatDesc,
- baseline::chainerDesc,
- },
- };
- static const uint32_t variantCount = static_cast<uint32_t>(std::size(variants));
- } // namespace baseline
+ namespace blocks {
+ namespace baseline {
+ static const VpVariantDesc variants[] = {
+ {
+ "baseline",
+ static_cast<uint32_t>(std::size(blocks::baseline::instanceExtensions)), blocks::baseline::instanceExtensions,
+ static_cast<uint32_t>(std::size(blocks::baseline::deviceExtensions)), blocks::baseline::deviceExtensions,
+ static_cast<uint32_t>(std::size(featureStructTypes)), featureStructTypes,
+ blocks::baseline::featureDesc,
+ static_cast<uint32_t>(std::size(propertyStructTypes)), propertyStructTypes,
+ blocks::baseline::propertyDesc,
+ 0, nullptr,
+ 0, nullptr,
+ static_cast<uint32_t>(std::size(formatStructTypes)), formatStructTypes,
+ static_cast<uint32_t>(std::size(blocks::baseline::formatDesc)), blocks::baseline::formatDesc,
+ blocks::baseline::chainerDesc,
+ 0, nullptr,
+ },
+ };
+ static const uint32_t variantCount = static_cast<uint32_t>(std::size(variants));
+ } // namespace baseline
+ } // namespace blocks
static const VpCapabilitiesDesc capabilities[] = {
- baseline::variantCount, baseline::variants,
+ { blocks::baseline::variantCount, blocks::baseline::variants },
};
static const uint32_t capabilityCount = static_cast<uint32_t>(std::size(capabilities));
} // namespace VP_ANDROID_BASELINE_2021_CPU_ONLY
@@ -9199,6 +9819,7 @@
#ifdef VP_ANDROID_baseline_2022
namespace VP_ANDROID_BASELINE_2022 {
static const VpVariantDesc mergedCapabilities[] = {
+ {
"MERGED",
static_cast<uint32_t>(std::size(instanceExtensions)), instanceExtensions,
static_cast<uint32_t>(std::size(deviceExtensions)), deviceExtensions,
@@ -9211,30 +9832,35 @@
0, nullptr,
0, nullptr,
chainerDesc,
+ 0, nullptr,
+ },
};
- namespace baseline {
- static const VpVariantDesc variants[] = {
- {
- "baseline",
- static_cast<uint32_t>(std::size(baseline::instanceExtensions)), baseline::instanceExtensions,
- static_cast<uint32_t>(std::size(baseline::deviceExtensions)), baseline::deviceExtensions,
- static_cast<uint32_t>(std::size(featureStructTypes)), featureStructTypes,
- baseline::featureDesc,
- static_cast<uint32_t>(std::size(propertyStructTypes)), propertyStructTypes,
- baseline::propertyDesc,
- 0, nullptr,
- 0, nullptr,
- static_cast<uint32_t>(std::size(formatStructTypes)), formatStructTypes,
- static_cast<uint32_t>(std::size(baseline::formatDesc)), baseline::formatDesc,
- baseline::chainerDesc,
- },
- };
- static const uint32_t variantCount = static_cast<uint32_t>(std::size(variants));
- } // namespace baseline
+ namespace blocks {
+ namespace baseline {
+ static const VpVariantDesc variants[] = {
+ {
+ "baseline",
+ static_cast<uint32_t>(std::size(blocks::baseline::instanceExtensions)), blocks::baseline::instanceExtensions,
+ static_cast<uint32_t>(std::size(blocks::baseline::deviceExtensions)), blocks::baseline::deviceExtensions,
+ static_cast<uint32_t>(std::size(featureStructTypes)), featureStructTypes,
+ blocks::baseline::featureDesc,
+ static_cast<uint32_t>(std::size(propertyStructTypes)), propertyStructTypes,
+ blocks::baseline::propertyDesc,
+ 0, nullptr,
+ 0, nullptr,
+ static_cast<uint32_t>(std::size(formatStructTypes)), formatStructTypes,
+ static_cast<uint32_t>(std::size(blocks::baseline::formatDesc)), blocks::baseline::formatDesc,
+ blocks::baseline::chainerDesc,
+ 0, nullptr,
+ },
+ };
+ static const uint32_t variantCount = static_cast<uint32_t>(std::size(variants));
+ } // namespace baseline
+ } // namespace blocks
static const VpCapabilitiesDesc capabilities[] = {
- baseline::variantCount, baseline::variants,
+ { blocks::baseline::variantCount, blocks::baseline::variants },
};
static const uint32_t capabilityCount = static_cast<uint32_t>(std::size(capabilities));
} // namespace VP_ANDROID_BASELINE_2022
@@ -9251,6 +9877,16 @@
0, nullptr,
},
#endif // VP_ANDROID_15_MINIMUMS
+#ifdef VP_ANDROID_16_minimums
+ VpProfileDesc{
+ VpProfileProperties{ VP_ANDROID_16_MINIMUMS_NAME, VP_ANDROID_16_MINIMUMS_SPEC_VERSION },
+ VP_ANDROID_16_MINIMUMS_MIN_API_VERSION,
+ nullptr,
+ VP_ANDROID_16_MINIMUMS::profileCount, VP_ANDROID_16_MINIMUMS::profiles,
+ VP_ANDROID_16_MINIMUMS::capabilityCount, VP_ANDROID_16_MINIMUMS::capabilities,
+ 0, nullptr,
+ },
+#endif // VP_ANDROID_16_MINIMUMS
#ifdef VP_ANDROID_baseline_2021
VpProfileDesc{
VpProfileProperties{ VP_ANDROID_BASELINE_2021_NAME, VP_ANDROID_BASELINE_2021_SPEC_VERSION },
@@ -9309,12 +9945,13 @@
VkPhysicalDeviceMultiDrawFeaturesEXT physicalDeviceMultiDrawFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT, nullptr };
VkPhysicalDeviceInlineUniformBlockFeatures physicalDeviceInlineUniformBlockFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES, nullptr };
VkPhysicalDeviceMaintenance4Features physicalDeviceMaintenance4Features{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES, nullptr };
- VkPhysicalDeviceMaintenance5FeaturesKHR physicalDeviceMaintenance5FeaturesKHR{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR, nullptr };
- VkPhysicalDeviceMaintenance6FeaturesKHR physicalDeviceMaintenance6FeaturesKHR{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_6_FEATURES_KHR, nullptr };
+ VkPhysicalDeviceMaintenance5Features physicalDeviceMaintenance5Features{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES, nullptr };
+ VkPhysicalDeviceMaintenance6Features physicalDeviceMaintenance6Features{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_6_FEATURES, nullptr };
+ VkPhysicalDeviceMaintenance7FeaturesKHR physicalDeviceMaintenance7FeaturesKHR{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_7_FEATURES_KHR, nullptr };
VkPhysicalDeviceShaderDrawParametersFeatures physicalDeviceShaderDrawParametersFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES, nullptr };
VkPhysicalDeviceShaderFloat16Int8Features physicalDeviceShaderFloat16Int8Features{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES, nullptr };
VkPhysicalDeviceHostQueryResetFeatures physicalDeviceHostQueryResetFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES, nullptr };
- VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR physicalDeviceGlobalPriorityQueryFeaturesKHR{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR, nullptr };
+ VkPhysicalDeviceGlobalPriorityQueryFeatures physicalDeviceGlobalPriorityQueryFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES, nullptr };
VkPhysicalDeviceDeviceMemoryReportFeaturesEXT physicalDeviceDeviceMemoryReportFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT, nullptr };
VkPhysicalDeviceDescriptorIndexingFeatures physicalDeviceDescriptorIndexingFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES, nullptr };
VkPhysicalDeviceTimelineSemaphoreFeatures physicalDeviceTimelineSemaphoreFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, nullptr };
@@ -9324,13 +9961,12 @@
VkPhysicalDeviceShaderAtomicInt64Features physicalDeviceShaderAtomicInt64Features{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES, nullptr };
VkPhysicalDeviceShaderAtomicFloatFeaturesEXT physicalDeviceShaderAtomicFloatFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT, nullptr };
VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT physicalDeviceShaderAtomicFloat2FeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT, nullptr };
- VkPhysicalDeviceVertexAttributeDivisorFeaturesKHR physicalDeviceVertexAttributeDivisorFeaturesKHR{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_KHR, nullptr };
+ VkPhysicalDeviceVertexAttributeDivisorFeatures physicalDeviceVertexAttributeDivisorFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES, nullptr };
VkPhysicalDeviceASTCDecodeFeaturesEXT physicalDeviceASTCDecodeFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT, nullptr };
VkPhysicalDeviceTransformFeedbackFeaturesEXT physicalDeviceTransformFeedbackFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT, nullptr };
VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV physicalDeviceRepresentativeFragmentTestFeaturesNV{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV, nullptr };
VkPhysicalDeviceExclusiveScissorFeaturesNV physicalDeviceExclusiveScissorFeaturesNV{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV, nullptr };
VkPhysicalDeviceCornerSampledImageFeaturesNV physicalDeviceCornerSampledImageFeaturesNV{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV, nullptr };
- VkPhysicalDeviceComputeShaderDerivativesFeaturesNV physicalDeviceComputeShaderDerivativesFeaturesNV{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV, nullptr };
VkPhysicalDeviceShaderImageFootprintFeaturesNV physicalDeviceShaderImageFootprintFeaturesNV{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV, nullptr };
VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV physicalDeviceDedicatedAllocationImageAliasingFeaturesNV{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEDICATED_ALLOCATION_IMAGE_ALIASING_FEATURES_NV, nullptr };
VkPhysicalDeviceCopyMemoryIndirectFeaturesNV physicalDeviceCopyMemoryIndirectFeaturesNV{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_FEATURES_NV, nullptr };
@@ -9362,7 +9998,7 @@
VkPhysicalDeviceCoverageReductionModeFeaturesNV physicalDeviceCoverageReductionModeFeaturesNV{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COVERAGE_REDUCTION_MODE_FEATURES_NV, nullptr };
VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL physicalDeviceShaderIntegerFunctions2FeaturesINTEL{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL, nullptr };
VkPhysicalDeviceShaderClockFeaturesKHR physicalDeviceShaderClockFeaturesKHR{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR, nullptr };
- VkPhysicalDeviceIndexTypeUint8FeaturesEXT physicalDeviceIndexTypeUint8FeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT, nullptr };
+ VkPhysicalDeviceIndexTypeUint8Features physicalDeviceIndexTypeUint8Features{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES, nullptr };
VkPhysicalDeviceShaderSMBuiltinsFeaturesNV physicalDeviceShaderSMBuiltinsFeaturesNV{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV, nullptr };
VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT physicalDeviceFragmentShaderInterlockFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT, nullptr };
VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures physicalDeviceSeparateDepthStencilLayoutsFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES, nullptr };
@@ -9371,11 +10007,12 @@
VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures physicalDeviceShaderDemoteToHelperInvocationFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES, nullptr };
VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT physicalDeviceTexelBufferAlignmentFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT, nullptr };
VkPhysicalDeviceSubgroupSizeControlFeatures physicalDeviceSubgroupSizeControlFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES, nullptr };
- VkPhysicalDeviceLineRasterizationFeaturesEXT physicalDeviceLineRasterizationFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT, nullptr };
+ VkPhysicalDeviceLineRasterizationFeatures physicalDeviceLineRasterizationFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES, nullptr };
VkPhysicalDevicePipelineCreationCacheControlFeatures physicalDevicePipelineCreationCacheControlFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES, nullptr };
VkPhysicalDeviceVulkan11Features physicalDeviceVulkan11Features{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES, nullptr };
VkPhysicalDeviceVulkan12Features physicalDeviceVulkan12Features{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, nullptr };
VkPhysicalDeviceVulkan13Features physicalDeviceVulkan13Features{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES, nullptr };
+ VkPhysicalDeviceVulkan14Features physicalDeviceVulkan14Features{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_4_FEATURES, nullptr };
VkPhysicalDeviceCoherentMemoryFeaturesAMD physicalDeviceCoherentMemoryFeaturesAMD{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD, nullptr };
VkPhysicalDeviceCustomBorderColorFeaturesEXT physicalDeviceCustomBorderColorFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT, nullptr };
VkPhysicalDeviceBorderColorSwizzleFeaturesEXT physicalDeviceBorderColorSwizzleFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT, nullptr };
@@ -9401,17 +10038,19 @@
VkPhysicalDeviceImage2DViewOf3DFeaturesEXT physicalDeviceImage2DViewOf3DFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT, nullptr };
VkPhysicalDeviceImageSlicedViewOf3DFeaturesEXT physicalDeviceImageSlicedViewOf3DFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_SLICED_VIEW_OF_3D_FEATURES_EXT, nullptr };
VkPhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT physicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT, nullptr };
+ VkPhysicalDeviceLegacyVertexAttributesFeaturesEXT physicalDeviceLegacyVertexAttributesFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_VERTEX_ATTRIBUTES_FEATURES_EXT, nullptr };
VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT physicalDeviceMutableDescriptorTypeFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT, nullptr };
VkPhysicalDeviceDepthClipControlFeaturesEXT physicalDeviceDepthClipControlFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT, nullptr };
VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT physicalDeviceVertexInputDynamicStateFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT, nullptr };
VkPhysicalDeviceExternalMemoryRDMAFeaturesNV physicalDeviceExternalMemoryRDMAFeaturesNV{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_RDMA_FEATURES_NV, nullptr };
+ VkPhysicalDeviceShaderRelaxedExtendedInstructionFeaturesKHR physicalDeviceShaderRelaxedExtendedInstructionFeaturesKHR{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_RELAXED_EXTENDED_INSTRUCTION_FEATURES_KHR, nullptr };
VkPhysicalDeviceColorWriteEnableFeaturesEXT physicalDeviceColorWriteEnableFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT, nullptr };
VkPhysicalDeviceSynchronization2Features physicalDeviceSynchronization2Features{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES, nullptr };
- VkPhysicalDeviceHostImageCopyFeaturesEXT physicalDeviceHostImageCopyFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT, nullptr };
+ VkPhysicalDeviceHostImageCopyFeatures physicalDeviceHostImageCopyFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES, nullptr };
VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT physicalDevicePrimitivesGeneratedQueryFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT, nullptr };
VkPhysicalDeviceLegacyDitheringFeaturesEXT physicalDeviceLegacyDitheringFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT, nullptr };
VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT physicalDeviceMultisampledRenderToSingleSampledFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT, nullptr };
- VkPhysicalDevicePipelineProtectedAccessFeaturesEXT physicalDevicePipelineProtectedAccessFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT, nullptr };
+ VkPhysicalDevicePipelineProtectedAccessFeatures physicalDevicePipelineProtectedAccessFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES, nullptr };
VkPhysicalDeviceVideoMaintenance1FeaturesKHR physicalDeviceVideoMaintenance1FeaturesKHR{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_1_FEATURES_KHR, nullptr };
VkPhysicalDeviceInheritedViewportScissorFeaturesNV physicalDeviceInheritedViewportScissorFeaturesNV{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INHERITED_VIEWPORT_SCISSOR_FEATURES_NV, nullptr };
VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT physicalDeviceYcbcr2Plane444FormatsFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT, nullptr };
@@ -9420,12 +10059,14 @@
VkPhysicalDeviceShaderIntegerDotProductFeatures physicalDeviceShaderIntegerDotProductFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES, nullptr };
VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR physicalDeviceFragmentShaderBarycentricFeaturesKHR{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR, nullptr };
VkPhysicalDeviceRayTracingMotionBlurFeaturesNV physicalDeviceRayTracingMotionBlurFeaturesNV{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MOTION_BLUR_FEATURES_NV, nullptr };
+ VkPhysicalDeviceRayTracingValidationFeaturesNV physicalDeviceRayTracingValidationFeaturesNV{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_VALIDATION_FEATURES_NV, nullptr };
VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT physicalDeviceRGBA10X6FormatsFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT, nullptr };
VkPhysicalDeviceDynamicRenderingFeatures physicalDeviceDynamicRenderingFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES, nullptr };
VkPhysicalDeviceImageViewMinLodFeaturesEXT physicalDeviceImageViewMinLodFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT, nullptr };
VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT physicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT, nullptr };
VkPhysicalDeviceLinearColorAttachmentFeaturesNV physicalDeviceLinearColorAttachmentFeaturesNV{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINEAR_COLOR_ATTACHMENT_FEATURES_NV, nullptr };
VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT physicalDeviceGraphicsPipelineLibraryFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT, nullptr };
+ VkPhysicalDevicePipelineBinaryFeaturesKHR physicalDevicePipelineBinaryFeaturesKHR{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_BINARY_FEATURES_KHR, nullptr };
VkPhysicalDeviceDescriptorSetHostMappingFeaturesVALVE physicalDeviceDescriptorSetHostMappingFeaturesVALVE{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE, nullptr };
VkPhysicalDeviceNestedCommandBufferFeaturesEXT physicalDeviceNestedCommandBufferFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_FEATURES_EXT, nullptr };
VkPhysicalDeviceShaderModuleIdentifierFeaturesEXT physicalDeviceShaderModuleIdentifierFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_FEATURES_EXT, nullptr };
@@ -9439,7 +10080,7 @@
VkPhysicalDevicePipelinePropertiesFeaturesEXT physicalDevicePipelinePropertiesFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROPERTIES_FEATURES_EXT, nullptr };
VkPhysicalDeviceShaderEarlyAndLateFragmentTestsFeaturesAMD physicalDeviceShaderEarlyAndLateFragmentTestsFeaturesAMD{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_FEATURES_AMD, nullptr };
VkPhysicalDeviceNonSeamlessCubeMapFeaturesEXT physicalDeviceNonSeamlessCubeMapFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT, nullptr };
- VkPhysicalDevicePipelineRobustnessFeaturesEXT physicalDevicePipelineRobustnessFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES_EXT, nullptr };
+ VkPhysicalDevicePipelineRobustnessFeatures physicalDevicePipelineRobustnessFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES, nullptr };
VkPhysicalDeviceImageProcessingFeaturesQCOM physicalDeviceImageProcessingFeaturesQCOM{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_FEATURES_QCOM, nullptr };
VkPhysicalDeviceTilePropertiesFeaturesQCOM physicalDeviceTilePropertiesFeaturesQCOM{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM, nullptr };
VkPhysicalDeviceAmigoProfilingFeaturesSEC physicalDeviceAmigoProfilingFeaturesSEC{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_AMIGO_PROFILING_FEATURES_SEC, nullptr };
@@ -9468,6 +10109,7 @@
#ifdef VK_ENABLE_BETA_EXTENSIONS
VkPhysicalDeviceShaderEnqueueFeaturesAMDX physicalDeviceShaderEnqueueFeaturesAMDX{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ENQUEUE_FEATURES_AMDX, nullptr };
#endif
+ VkPhysicalDeviceAntiLagFeaturesAMD physicalDeviceAntiLagFeaturesAMD{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ANTI_LAG_FEATURES_AMD, nullptr };
VkPhysicalDeviceCubicClampFeaturesQCOM physicalDeviceCubicClampFeaturesQCOM{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_CLAMP_FEATURES_QCOM, nullptr };
VkPhysicalDeviceYcbcrDegammaFeaturesQCOM physicalDeviceYcbcrDegammaFeaturesQCOM{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_DEGAMMA_FEATURES_QCOM, nullptr };
VkPhysicalDeviceCubicWeightsFeaturesQCOM physicalDeviceCubicWeightsFeaturesQCOM{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_WEIGHTS_FEATURES_QCOM, nullptr };
@@ -9481,6 +10123,18 @@
VkPhysicalDeviceSchedulingControlsFeaturesARM physicalDeviceSchedulingControlsFeaturesARM{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_FEATURES_ARM, nullptr };
VkPhysicalDeviceRelaxedLineRasterizationFeaturesIMG physicalDeviceRelaxedLineRasterizationFeaturesIMG{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RELAXED_LINE_RASTERIZATION_FEATURES_IMG, nullptr };
VkPhysicalDeviceRenderPassStripedFeaturesARM physicalDeviceRenderPassStripedFeaturesARM{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RENDER_PASS_STRIPED_FEATURES_ARM, nullptr };
+ VkPhysicalDeviceShaderMaximalReconvergenceFeaturesKHR physicalDeviceShaderMaximalReconvergenceFeaturesKHR{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MAXIMAL_RECONVERGENCE_FEATURES_KHR, nullptr };
+ VkPhysicalDeviceShaderSubgroupRotateFeatures physicalDeviceShaderSubgroupRotateFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES, nullptr };
+ VkPhysicalDeviceShaderExpectAssumeFeatures physicalDeviceShaderExpectAssumeFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EXPECT_ASSUME_FEATURES, nullptr };
+ VkPhysicalDeviceShaderFloatControls2Features physicalDeviceShaderFloatControls2Features{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT_CONTROLS_2_FEATURES, nullptr };
+ VkPhysicalDeviceDynamicRenderingLocalReadFeatures physicalDeviceDynamicRenderingLocalReadFeatures{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES, nullptr };
+ VkPhysicalDeviceShaderQuadControlFeaturesKHR physicalDeviceShaderQuadControlFeaturesKHR{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_QUAD_CONTROL_FEATURES_KHR, nullptr };
+ VkPhysicalDeviceShaderAtomicFloat16VectorFeaturesNV physicalDeviceShaderAtomicFloat16VectorFeaturesNV{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT16_VECTOR_FEATURES_NV, nullptr };
+ VkPhysicalDeviceMapMemoryPlacedFeaturesEXT physicalDeviceMapMemoryPlacedFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT, nullptr };
+ VkPhysicalDeviceRawAccessChainsFeaturesNV physicalDeviceRawAccessChainsFeaturesNV{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAW_ACCESS_CHAINS_FEATURES_NV, nullptr };
+ VkPhysicalDeviceCommandBufferInheritanceFeaturesNV physicalDeviceCommandBufferInheritanceFeaturesNV{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMMAND_BUFFER_INHERITANCE_FEATURES_NV, nullptr };
+ VkPhysicalDeviceImageAlignmentControlFeaturesMESA physicalDeviceImageAlignmentControlFeaturesMESA{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ALIGNMENT_CONTROL_FEATURES_MESA, nullptr };
+ VkPhysicalDeviceShaderReplicatedCompositesFeaturesEXT physicalDeviceShaderReplicatedCompositesFeaturesEXT{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_REPLICATED_COMPOSITES_FEATURES_EXT, nullptr };
VkPhysicalDeviceFeatures2KHR physicalDeviceFeatures2KHR{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR, nullptr };
FeaturesChain() {
@@ -9500,12 +10154,13 @@
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT, size<VkPhysicalDeviceMultiDrawFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES, size<VkPhysicalDeviceInlineUniformBlockFeatures>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES, size<VkPhysicalDeviceMaintenance4Features>() });
- this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR, size<VkPhysicalDeviceMaintenance5FeaturesKHR>() });
- this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_6_FEATURES_KHR, size<VkPhysicalDeviceMaintenance6FeaturesKHR>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES, size<VkPhysicalDeviceMaintenance5Features>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_6_FEATURES, size<VkPhysicalDeviceMaintenance6Features>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_7_FEATURES_KHR, size<VkPhysicalDeviceMaintenance7FeaturesKHR>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES, size<VkPhysicalDeviceShaderDrawParametersFeatures>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES, size<VkPhysicalDeviceShaderFloat16Int8Features>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES, size<VkPhysicalDeviceHostQueryResetFeatures>() });
- this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR, size<VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES, size<VkPhysicalDeviceGlobalPriorityQueryFeatures>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT, size<VkPhysicalDeviceDeviceMemoryReportFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES, size<VkPhysicalDeviceDescriptorIndexingFeatures>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, size<VkPhysicalDeviceTimelineSemaphoreFeatures>() });
@@ -9515,13 +10170,12 @@
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES, size<VkPhysicalDeviceShaderAtomicInt64Features>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT, size<VkPhysicalDeviceShaderAtomicFloatFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT, size<VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT>() });
- this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_KHR, size<VkPhysicalDeviceVertexAttributeDivisorFeaturesKHR>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES, size<VkPhysicalDeviceVertexAttributeDivisorFeatures>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT, size<VkPhysicalDeviceASTCDecodeFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT, size<VkPhysicalDeviceTransformFeedbackFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV, size<VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV, size<VkPhysicalDeviceExclusiveScissorFeaturesNV>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV, size<VkPhysicalDeviceCornerSampledImageFeaturesNV>() });
- this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV, size<VkPhysicalDeviceComputeShaderDerivativesFeaturesNV>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV, size<VkPhysicalDeviceShaderImageFootprintFeaturesNV>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEDICATED_ALLOCATION_IMAGE_ALIASING_FEATURES_NV, size<VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_FEATURES_NV, size<VkPhysicalDeviceCopyMemoryIndirectFeaturesNV>() });
@@ -9553,7 +10207,7 @@
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COVERAGE_REDUCTION_MODE_FEATURES_NV, size<VkPhysicalDeviceCoverageReductionModeFeaturesNV>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL, size<VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CLOCK_FEATURES_KHR, size<VkPhysicalDeviceShaderClockFeaturesKHR>() });
- this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT, size<VkPhysicalDeviceIndexTypeUint8FeaturesEXT>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES, size<VkPhysicalDeviceIndexTypeUint8Features>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV, size<VkPhysicalDeviceShaderSMBuiltinsFeaturesNV>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT, size<VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES, size<VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures>() });
@@ -9562,11 +10216,12 @@
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES, size<VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT, size<VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES, size<VkPhysicalDeviceSubgroupSizeControlFeatures>() });
- this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT, size<VkPhysicalDeviceLineRasterizationFeaturesEXT>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES, size<VkPhysicalDeviceLineRasterizationFeatures>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES, size<VkPhysicalDevicePipelineCreationCacheControlFeatures>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES, size<VkPhysicalDeviceVulkan11Features>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, size<VkPhysicalDeviceVulkan12Features>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES, size<VkPhysicalDeviceVulkan13Features>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_4_FEATURES, size<VkPhysicalDeviceVulkan14Features>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD, size<VkPhysicalDeviceCoherentMemoryFeaturesAMD>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT, size<VkPhysicalDeviceCustomBorderColorFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT, size<VkPhysicalDeviceBorderColorSwizzleFeaturesEXT>() });
@@ -9592,17 +10247,19 @@
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT, size<VkPhysicalDeviceImage2DViewOf3DFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_SLICED_VIEW_OF_3D_FEATURES_EXT, size<VkPhysicalDeviceImageSlicedViewOf3DFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_FEATURES_EXT, size<VkPhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_VERTEX_ATTRIBUTES_FEATURES_EXT, size<VkPhysicalDeviceLegacyVertexAttributesFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT, size<VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT, size<VkPhysicalDeviceDepthClipControlFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT, size<VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_RDMA_FEATURES_NV, size<VkPhysicalDeviceExternalMemoryRDMAFeaturesNV>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_RELAXED_EXTENDED_INSTRUCTION_FEATURES_KHR, size<VkPhysicalDeviceShaderRelaxedExtendedInstructionFeaturesKHR>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT, size<VkPhysicalDeviceColorWriteEnableFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES, size<VkPhysicalDeviceSynchronization2Features>() });
- this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT, size<VkPhysicalDeviceHostImageCopyFeaturesEXT>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES, size<VkPhysicalDeviceHostImageCopyFeatures>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT, size<VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT, size<VkPhysicalDeviceLegacyDitheringFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT, size<VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT>() });
- this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES_EXT, size<VkPhysicalDevicePipelineProtectedAccessFeaturesEXT>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROTECTED_ACCESS_FEATURES, size<VkPhysicalDevicePipelineProtectedAccessFeatures>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_1_FEATURES_KHR, size<VkPhysicalDeviceVideoMaintenance1FeaturesKHR>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INHERITED_VIEWPORT_SCISSOR_FEATURES_NV, size<VkPhysicalDeviceInheritedViewportScissorFeaturesNV>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT, size<VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT>() });
@@ -9611,12 +10268,14 @@
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES, size<VkPhysicalDeviceShaderIntegerDotProductFeatures>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR, size<VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MOTION_BLUR_FEATURES_NV, size<VkPhysicalDeviceRayTracingMotionBlurFeaturesNV>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_VALIDATION_FEATURES_NV, size<VkPhysicalDeviceRayTracingValidationFeaturesNV>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT, size<VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES, size<VkPhysicalDeviceDynamicRenderingFeatures>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT, size<VkPhysicalDeviceImageViewMinLodFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT, size<VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINEAR_COLOR_ATTACHMENT_FEATURES_NV, size<VkPhysicalDeviceLinearColorAttachmentFeaturesNV>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT, size<VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_BINARY_FEATURES_KHR, size<VkPhysicalDevicePipelineBinaryFeaturesKHR>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE, size<VkPhysicalDeviceDescriptorSetHostMappingFeaturesVALVE>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_FEATURES_EXT, size<VkPhysicalDeviceNestedCommandBufferFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_FEATURES_EXT, size<VkPhysicalDeviceShaderModuleIdentifierFeaturesEXT>() });
@@ -9630,7 +10289,7 @@
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROPERTIES_FEATURES_EXT, size<VkPhysicalDevicePipelinePropertiesFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_FEATURES_AMD, size<VkPhysicalDeviceShaderEarlyAndLateFragmentTestsFeaturesAMD>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT, size<VkPhysicalDeviceNonSeamlessCubeMapFeaturesEXT>() });
- this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES_EXT, size<VkPhysicalDevicePipelineRobustnessFeaturesEXT>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES, size<VkPhysicalDevicePipelineRobustnessFeatures>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_FEATURES_QCOM, size<VkPhysicalDeviceImageProcessingFeaturesQCOM>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM, size<VkPhysicalDeviceTilePropertiesFeaturesQCOM>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_AMIGO_PROFILING_FEATURES_SEC, size<VkPhysicalDeviceAmigoProfilingFeaturesSEC>() });
@@ -9659,6 +10318,7 @@
#ifdef VK_ENABLE_BETA_EXTENSIONS
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ENQUEUE_FEATURES_AMDX, size<VkPhysicalDeviceShaderEnqueueFeaturesAMDX>() });
#endif
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ANTI_LAG_FEATURES_AMD, size<VkPhysicalDeviceAntiLagFeaturesAMD>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_CLAMP_FEATURES_QCOM, size<VkPhysicalDeviceCubicClampFeaturesQCOM>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_DEGAMMA_FEATURES_QCOM, size<VkPhysicalDeviceYcbcrDegammaFeaturesQCOM>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUBIC_WEIGHTS_FEATURES_QCOM, size<VkPhysicalDeviceCubicWeightsFeaturesQCOM>() });
@@ -9672,6 +10332,18 @@
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCHEDULING_CONTROLS_FEATURES_ARM, size<VkPhysicalDeviceSchedulingControlsFeaturesARM>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RELAXED_LINE_RASTERIZATION_FEATURES_IMG, size<VkPhysicalDeviceRelaxedLineRasterizationFeaturesIMG>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RENDER_PASS_STRIPED_FEATURES_ARM, size<VkPhysicalDeviceRenderPassStripedFeaturesARM>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MAXIMAL_RECONVERGENCE_FEATURES_KHR, size<VkPhysicalDeviceShaderMaximalReconvergenceFeaturesKHR>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES, size<VkPhysicalDeviceShaderSubgroupRotateFeatures>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EXPECT_ASSUME_FEATURES, size<VkPhysicalDeviceShaderExpectAssumeFeatures>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT_CONTROLS_2_FEATURES, size<VkPhysicalDeviceShaderFloatControls2Features>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_LOCAL_READ_FEATURES, size<VkPhysicalDeviceDynamicRenderingLocalReadFeatures>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_QUAD_CONTROL_FEATURES_KHR, size<VkPhysicalDeviceShaderQuadControlFeaturesKHR>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT16_VECTOR_FEATURES_NV, size<VkPhysicalDeviceShaderAtomicFloat16VectorFeaturesNV>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT, size<VkPhysicalDeviceMapMemoryPlacedFeaturesEXT>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAW_ACCESS_CHAINS_FEATURES_NV, size<VkPhysicalDeviceRawAccessChainsFeaturesNV>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMMAND_BUFFER_INHERITANCE_FEATURES_NV, size<VkPhysicalDeviceCommandBufferInheritanceFeaturesNV>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ALIGNMENT_CONTROL_FEATURES_MESA, size<VkPhysicalDeviceImageAlignmentControlFeaturesMESA>() });
+ this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_REPLICATED_COMPOSITES_FEATURES_EXT, size<VkPhysicalDeviceShaderReplicatedCompositesFeaturesEXT>() });
this->structureSize.insert({ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR, size<VkPhysicalDeviceFeatures2KHR>() });
//Initializing the full list of available structure features
@@ -9706,18 +10378,20 @@
pNext = &physicalDeviceInlineUniformBlockFeatures;
physicalDeviceMaintenance4Features.pNext = pNext;
pNext = &physicalDeviceMaintenance4Features;
- physicalDeviceMaintenance5FeaturesKHR.pNext = pNext;
- pNext = &physicalDeviceMaintenance5FeaturesKHR;
- physicalDeviceMaintenance6FeaturesKHR.pNext = pNext;
- pNext = &physicalDeviceMaintenance6FeaturesKHR;
+ physicalDeviceMaintenance5Features.pNext = pNext;
+ pNext = &physicalDeviceMaintenance5Features;
+ physicalDeviceMaintenance6Features.pNext = pNext;
+ pNext = &physicalDeviceMaintenance6Features;
+ physicalDeviceMaintenance7FeaturesKHR.pNext = pNext;
+ pNext = &physicalDeviceMaintenance7FeaturesKHR;
physicalDeviceShaderDrawParametersFeatures.pNext = pNext;
pNext = &physicalDeviceShaderDrawParametersFeatures;
physicalDeviceShaderFloat16Int8Features.pNext = pNext;
pNext = &physicalDeviceShaderFloat16Int8Features;
physicalDeviceHostQueryResetFeatures.pNext = pNext;
pNext = &physicalDeviceHostQueryResetFeatures;
- physicalDeviceGlobalPriorityQueryFeaturesKHR.pNext = pNext;
- pNext = &physicalDeviceGlobalPriorityQueryFeaturesKHR;
+ physicalDeviceGlobalPriorityQueryFeatures.pNext = pNext;
+ pNext = &physicalDeviceGlobalPriorityQueryFeatures;
physicalDeviceDeviceMemoryReportFeaturesEXT.pNext = pNext;
pNext = &physicalDeviceDeviceMemoryReportFeaturesEXT;
physicalDeviceDescriptorIndexingFeatures.pNext = pNext;
@@ -9736,8 +10410,8 @@
pNext = &physicalDeviceShaderAtomicFloatFeaturesEXT;
physicalDeviceShaderAtomicFloat2FeaturesEXT.pNext = pNext;
pNext = &physicalDeviceShaderAtomicFloat2FeaturesEXT;
- physicalDeviceVertexAttributeDivisorFeaturesKHR.pNext = pNext;
- pNext = &physicalDeviceVertexAttributeDivisorFeaturesKHR;
+ physicalDeviceVertexAttributeDivisorFeatures.pNext = pNext;
+ pNext = &physicalDeviceVertexAttributeDivisorFeatures;
physicalDeviceASTCDecodeFeaturesEXT.pNext = pNext;
pNext = &physicalDeviceASTCDecodeFeaturesEXT;
physicalDeviceTransformFeedbackFeaturesEXT.pNext = pNext;
@@ -9748,8 +10422,6 @@
pNext = &physicalDeviceExclusiveScissorFeaturesNV;
physicalDeviceCornerSampledImageFeaturesNV.pNext = pNext;
pNext = &physicalDeviceCornerSampledImageFeaturesNV;
- physicalDeviceComputeShaderDerivativesFeaturesNV.pNext = pNext;
- pNext = &physicalDeviceComputeShaderDerivativesFeaturesNV;
physicalDeviceShaderImageFootprintFeaturesNV.pNext = pNext;
pNext = &physicalDeviceShaderImageFootprintFeaturesNV;
physicalDeviceDedicatedAllocationImageAliasingFeaturesNV.pNext = pNext;
@@ -9812,8 +10484,8 @@
pNext = &physicalDeviceShaderIntegerFunctions2FeaturesINTEL;
physicalDeviceShaderClockFeaturesKHR.pNext = pNext;
pNext = &physicalDeviceShaderClockFeaturesKHR;
- physicalDeviceIndexTypeUint8FeaturesEXT.pNext = pNext;
- pNext = &physicalDeviceIndexTypeUint8FeaturesEXT;
+ physicalDeviceIndexTypeUint8Features.pNext = pNext;
+ pNext = &physicalDeviceIndexTypeUint8Features;
physicalDeviceShaderSMBuiltinsFeaturesNV.pNext = pNext;
pNext = &physicalDeviceShaderSMBuiltinsFeaturesNV;
physicalDeviceFragmentShaderInterlockFeaturesEXT.pNext = pNext;
@@ -9830,8 +10502,8 @@
pNext = &physicalDeviceTexelBufferAlignmentFeaturesEXT;
physicalDeviceSubgroupSizeControlFeatures.pNext = pNext;
pNext = &physicalDeviceSubgroupSizeControlFeatures;
- physicalDeviceLineRasterizationFeaturesEXT.pNext = pNext;
- pNext = &physicalDeviceLineRasterizationFeaturesEXT;
+ physicalDeviceLineRasterizationFeatures.pNext = pNext;
+ pNext = &physicalDeviceLineRasterizationFeatures;
physicalDevicePipelineCreationCacheControlFeatures.pNext = pNext;
pNext = &physicalDevicePipelineCreationCacheControlFeatures;
physicalDeviceVulkan11Features.pNext = pNext;
@@ -9840,6 +10512,8 @@
pNext = &physicalDeviceVulkan12Features;
physicalDeviceVulkan13Features.pNext = pNext;
pNext = &physicalDeviceVulkan13Features;
+ physicalDeviceVulkan14Features.pNext = pNext;
+ pNext = &physicalDeviceVulkan14Features;
physicalDeviceCoherentMemoryFeaturesAMD.pNext = pNext;
pNext = &physicalDeviceCoherentMemoryFeaturesAMD;
physicalDeviceCustomBorderColorFeaturesEXT.pNext = pNext;
@@ -9888,6 +10562,8 @@
pNext = &physicalDeviceImageSlicedViewOf3DFeaturesEXT;
physicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT.pNext = pNext;
pNext = &physicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT;
+ physicalDeviceLegacyVertexAttributesFeaturesEXT.pNext = pNext;
+ pNext = &physicalDeviceLegacyVertexAttributesFeaturesEXT;
physicalDeviceMutableDescriptorTypeFeaturesEXT.pNext = pNext;
pNext = &physicalDeviceMutableDescriptorTypeFeaturesEXT;
physicalDeviceDepthClipControlFeaturesEXT.pNext = pNext;
@@ -9896,20 +10572,22 @@
pNext = &physicalDeviceVertexInputDynamicStateFeaturesEXT;
physicalDeviceExternalMemoryRDMAFeaturesNV.pNext = pNext;
pNext = &physicalDeviceExternalMemoryRDMAFeaturesNV;
+ physicalDeviceShaderRelaxedExtendedInstructionFeaturesKHR.pNext = pNext;
+ pNext = &physicalDeviceShaderRelaxedExtendedInstructionFeaturesKHR;
physicalDeviceColorWriteEnableFeaturesEXT.pNext = pNext;
pNext = &physicalDeviceColorWriteEnableFeaturesEXT;
physicalDeviceSynchronization2Features.pNext = pNext;
pNext = &physicalDeviceSynchronization2Features;
- physicalDeviceHostImageCopyFeaturesEXT.pNext = pNext;
- pNext = &physicalDeviceHostImageCopyFeaturesEXT;
+ physicalDeviceHostImageCopyFeatures.pNext = pNext;
+ pNext = &physicalDeviceHostImageCopyFeatures;
physicalDevicePrimitivesGeneratedQueryFeaturesEXT.pNext = pNext;
pNext = &physicalDevicePrimitivesGeneratedQueryFeaturesEXT;
physicalDeviceLegacyDitheringFeaturesEXT.pNext = pNext;
pNext = &physicalDeviceLegacyDitheringFeaturesEXT;
physicalDeviceMultisampledRenderToSingleSampledFeaturesEXT.pNext = pNext;
pNext = &physicalDeviceMultisampledRenderToSingleSampledFeaturesEXT;
- physicalDevicePipelineProtectedAccessFeaturesEXT.pNext = pNext;
- pNext = &physicalDevicePipelineProtectedAccessFeaturesEXT;
+ physicalDevicePipelineProtectedAccessFeatures.pNext = pNext;
+ pNext = &physicalDevicePipelineProtectedAccessFeatures;
physicalDeviceVideoMaintenance1FeaturesKHR.pNext = pNext;
pNext = &physicalDeviceVideoMaintenance1FeaturesKHR;
physicalDeviceInheritedViewportScissorFeaturesNV.pNext = pNext;
@@ -9926,6 +10604,8 @@
pNext = &physicalDeviceFragmentShaderBarycentricFeaturesKHR;
physicalDeviceRayTracingMotionBlurFeaturesNV.pNext = pNext;
pNext = &physicalDeviceRayTracingMotionBlurFeaturesNV;
+ physicalDeviceRayTracingValidationFeaturesNV.pNext = pNext;
+ pNext = &physicalDeviceRayTracingValidationFeaturesNV;
physicalDeviceRGBA10X6FormatsFeaturesEXT.pNext = pNext;
pNext = &physicalDeviceRGBA10X6FormatsFeaturesEXT;
physicalDeviceDynamicRenderingFeatures.pNext = pNext;
@@ -9938,6 +10618,8 @@
pNext = &physicalDeviceLinearColorAttachmentFeaturesNV;
physicalDeviceGraphicsPipelineLibraryFeaturesEXT.pNext = pNext;
pNext = &physicalDeviceGraphicsPipelineLibraryFeaturesEXT;
+ physicalDevicePipelineBinaryFeaturesKHR.pNext = pNext;
+ pNext = &physicalDevicePipelineBinaryFeaturesKHR;
physicalDeviceDescriptorSetHostMappingFeaturesVALVE.pNext = pNext;
pNext = &physicalDeviceDescriptorSetHostMappingFeaturesVALVE;
physicalDeviceNestedCommandBufferFeaturesEXT.pNext = pNext;
@@ -9962,8 +10644,8 @@
pNext = &physicalDeviceShaderEarlyAndLateFragmentTestsFeaturesAMD;
physicalDeviceNonSeamlessCubeMapFeaturesEXT.pNext = pNext;
pNext = &physicalDeviceNonSeamlessCubeMapFeaturesEXT;
- physicalDevicePipelineRobustnessFeaturesEXT.pNext = pNext;
- pNext = &physicalDevicePipelineRobustnessFeaturesEXT;
+ physicalDevicePipelineRobustnessFeatures.pNext = pNext;
+ pNext = &physicalDevicePipelineRobustnessFeatures;
physicalDeviceImageProcessingFeaturesQCOM.pNext = pNext;
pNext = &physicalDeviceImageProcessingFeaturesQCOM;
physicalDeviceTilePropertiesFeaturesQCOM.pNext = pNext;
@@ -10016,6 +10698,8 @@
physicalDeviceShaderEnqueueFeaturesAMDX.pNext = pNext;
pNext = &physicalDeviceShaderEnqueueFeaturesAMDX;
#endif
+ physicalDeviceAntiLagFeaturesAMD.pNext = pNext;
+ pNext = &physicalDeviceAntiLagFeaturesAMD;
physicalDeviceCubicClampFeaturesQCOM.pNext = pNext;
pNext = &physicalDeviceCubicClampFeaturesQCOM;
physicalDeviceYcbcrDegammaFeaturesQCOM.pNext = pNext;
@@ -10040,6 +10724,30 @@
pNext = &physicalDeviceRelaxedLineRasterizationFeaturesIMG;
physicalDeviceRenderPassStripedFeaturesARM.pNext = pNext;
pNext = &physicalDeviceRenderPassStripedFeaturesARM;
+ physicalDeviceShaderMaximalReconvergenceFeaturesKHR.pNext = pNext;
+ pNext = &physicalDeviceShaderMaximalReconvergenceFeaturesKHR;
+ physicalDeviceShaderSubgroupRotateFeatures.pNext = pNext;
+ pNext = &physicalDeviceShaderSubgroupRotateFeatures;
+ physicalDeviceShaderExpectAssumeFeatures.pNext = pNext;
+ pNext = &physicalDeviceShaderExpectAssumeFeatures;
+ physicalDeviceShaderFloatControls2Features.pNext = pNext;
+ pNext = &physicalDeviceShaderFloatControls2Features;
+ physicalDeviceDynamicRenderingLocalReadFeatures.pNext = pNext;
+ pNext = &physicalDeviceDynamicRenderingLocalReadFeatures;
+ physicalDeviceShaderQuadControlFeaturesKHR.pNext = pNext;
+ pNext = &physicalDeviceShaderQuadControlFeaturesKHR;
+ physicalDeviceShaderAtomicFloat16VectorFeaturesNV.pNext = pNext;
+ pNext = &physicalDeviceShaderAtomicFloat16VectorFeaturesNV;
+ physicalDeviceMapMemoryPlacedFeaturesEXT.pNext = pNext;
+ pNext = &physicalDeviceMapMemoryPlacedFeaturesEXT;
+ physicalDeviceRawAccessChainsFeaturesNV.pNext = pNext;
+ pNext = &physicalDeviceRawAccessChainsFeaturesNV;
+ physicalDeviceCommandBufferInheritanceFeaturesNV.pNext = pNext;
+ pNext = &physicalDeviceCommandBufferInheritanceFeaturesNV;
+ physicalDeviceImageAlignmentControlFeaturesMESA.pNext = pNext;
+ pNext = &physicalDeviceImageAlignmentControlFeaturesMESA;
+ physicalDeviceShaderReplicatedCompositesFeaturesEXT.pNext = pNext;
+ pNext = &physicalDeviceShaderReplicatedCompositesFeaturesEXT;
physicalDeviceFeatures2KHR.pNext = pNext;
}
@@ -10090,8 +10798,8 @@
const std::size_t offset = sizeof(VkBaseOutStructure);
const VkBaseOutStructure* q = reinterpret_cast<const VkBaseOutStructure*>(pCreateInfo->pCreateInfo->pNext);
while (q) {
- std::size_t count = this->structureSize[q->sType];
- for (std::size_t i = 0, n = count; i < n; ++i) {
+ const std::size_t count = this->structureSize[q->sType];
+ for (std::size_t index = 0; index < count; ++index) {
const VkBaseOutStructure* pInputStruct = reinterpret_cast<const VkBaseOutStructure*>(q);
VkBaseOutStructure* pOutputStruct = reinterpret_cast<VkBaseOutStructure*>(detail::vpGetStructure(&this->requiredFeaturesChain, q->sType));
const uint8_t* pInputData = reinterpret_cast<const uint8_t*>(pInputStruct) + offset;
@@ -10099,7 +10807,7 @@
const VkBool32* input = reinterpret_cast<const VkBool32*>(pInputData);
VkBool32* output = reinterpret_cast<VkBool32*>(pOutputData);
- output[i] = (output[i] == VK_TRUE || input[i] == VK_TRUE) ? VK_TRUE : VK_FALSE;
+ output[index] = (output[index] == VK_TRUE || input[index] == VK_TRUE) ? VK_TRUE : VK_FALSE;
}
q = q->pNext;
}
@@ -10107,7 +10815,7 @@
this->ApplyRobustness(pCreateInfo);
}
- void PushBack(VkBaseOutStructure* found) {
+ void PushBack(VkBaseOutStructure* found) {
VkBaseOutStructure* last = reinterpret_cast<VkBaseOutStructure*>(&requiredFeaturesChain);
while (last->pNext != nullptr) {
last = last->pNext;
@@ -10133,27 +10841,29 @@
}; // struct FeaturesChain
VPAPI_ATTR const VpProfileDesc* vpGetProfileDesc(const char profileName[VP_MAX_PROFILE_NAME_SIZE]) {
- for (uint32_t i = 0; i < profileCount; ++i) {
- if (strncmp(profiles[i].props.profileName, profileName, VP_MAX_PROFILE_NAME_SIZE) == 0) return &profiles[i];
+ for (uint32_t profileIndex = 0; profileIndex < profileCount; ++profileIndex) {
+ if (strncmp(profiles[profileIndex].props.profileName, profileName, VP_MAX_PROFILE_NAME_SIZE) == 0) {
+ return &profiles[profileIndex];
+ }
}
return nullptr;
}
VPAPI_ATTR std::vector<VpProfileProperties> GatherProfiles(const VpProfileProperties& profile, const char* pBlockName = nullptr) {
- std::vector<VpProfileProperties> profiles;
+ std::vector<VpProfileProperties> gatheredProfiles;
if (pBlockName == nullptr) {
- const detail::VpProfileDesc* profile_desc = detail::vpGetProfileDesc(profile.profileName);
- if (profile_desc != nullptr) {
- for (uint32_t profile_index = 0; profile_index < profile_desc->requiredProfileCount; ++profile_index) {
- profiles.push_back(profile_desc->pRequiredProfiles[profile_index]);
+ const detail::VpProfileDesc* profileDesc = detail::vpGetProfileDesc(profile.profileName);
+ if (profileDesc != nullptr) {
+ for (uint32_t profileIndex = 0; profileIndex < profileDesc->requiredProfileCount; ++profileIndex) {
+ gatheredProfiles.push_back(profileDesc->pRequiredProfiles[profileIndex]);
}
}
}
- profiles.push_back(profile);
+ gatheredProfiles.push_back(profile);
- return profiles;
+ return gatheredProfiles;
}
VPAPI_ATTR bool vpCheckVersion(uint32_t actual, uint32_t expected) {
@@ -10184,7 +10894,6 @@
// if (supportedProperties[i].specVersion >= expectedVersion) found = true;
}
}
- VP_DEBUG_COND_MSGF(!found, "Unsupported extension: %s", requestedExtension);
return found;
}
@@ -10198,11 +10907,11 @@
}
VPAPI_ATTR void GetExtensions(uint32_t extensionCount, const VkExtensionProperties *pExtensions, std::vector<const char *> &extensions) {
- for (uint32_t i = 0; i < extensionCount; ++i) {
- if (CheckExtension(extensions, pExtensions[i].extensionName)) {
+ for (uint32_t ext_index = 0; ext_index < extensionCount; ++ext_index) {
+ if (CheckExtension(extensions, pExtensions[ext_index].extensionName)) {
continue;
}
- extensions.push_back(pExtensions[i].extensionName);
+ extensions.push_back(pExtensions[ext_index].extensionName);
}
}
@@ -10211,25 +10920,29 @@
uint32_t enabledProfileBlockCount, const VpBlockProperties* pEnabledProfileBlocks) {
std::vector<VpBlockProperties> results;
- for (std::size_t i = 0; i < enabledFullProfileCount; ++i) {
- const std::vector<VpProfileProperties>& profiles = GatherProfiles(pEnabledFullProfiles[i]);
+ for (std::size_t profile_index = 0; profile_index < enabledFullProfileCount; ++profile_index) {
+ const std::vector<VpProfileProperties>& gathered_profiles = GatherProfiles(pEnabledFullProfiles[profile_index]);
- for (std::size_t j = 0; j < profiles.size(); ++j) {
- VpBlockProperties block{profiles[j], 0, ""};
+ for (std::size_t gathered_index = 0; gathered_index < gathered_profiles.size(); ++gathered_index) {
+ VpBlockProperties block{gathered_profiles[gathered_index], 0, ""};
results.push_back(block);
}
}
- for (std::size_t i = 0; i < enabledProfileBlockCount; ++i) {
- results.push_back(pEnabledProfileBlocks[i]);
+ for (std::size_t block_index = 0; block_index < enabledProfileBlockCount; ++block_index) {
+ results.push_back(pEnabledProfileBlocks[block_index]);
}
return results;
}
VPAPI_ATTR VkResult vpGetInstanceProfileSupportSingleProfile(
- uint32_t api_version, const std::vector<VkExtensionProperties>& supported_extensions,
- const VpProfileProperties* pProfile, VkBool32* pSupported, std::vector<VpBlockProperties>& supportedBlocks, std::vector<VpBlockProperties>& unsupportedBlocks) {
+ uint32_t api_version,
+ const std::vector<VkExtensionProperties>& supported_extensions,
+ const VpProfileProperties* pProfile,
+ VkBool32* pSupported,
+ std::vector<VpBlockProperties>& supportedBlocks,
+ std::vector<VpBlockProperties>& unsupportedBlocks) {
assert(pProfile != nullptr);
const detail::VpProfileDesc* pProfileDesc = vpGetProfileDesc(pProfile->profileName);
@@ -10248,16 +10961,7 @@
// Required API version is built in root profile, not need to check dependent profile API versions
if (api_version != 0) {
if (!vpCheckVersion(api_version, pProfileDesc->minApiVersion)) {
- const uint32_t version_min_major = VK_API_VERSION_MAJOR(pProfileDesc->minApiVersion);
- const uint32_t version_min_minor = VK_API_VERSION_MINOR(pProfileDesc->minApiVersion);
- const uint32_t version_min_patch = VK_API_VERSION_PATCH(pProfileDesc->minApiVersion);
- const uint32_t version_major = VK_API_VERSION_MAJOR(api_version);
- const uint32_t version_minor = VK_API_VERSION_MINOR(api_version);
- const uint32_t version_patch = VK_API_VERSION_PATCH(api_version);
-
- VP_DEBUG_MSGF("Unsupported Profile API version %u.%u.%u on a Vulkan system with version %u.%u.%u", version_min_major, version_min_minor, version_min_patch, version_major, version_minor, version_patch);
-
*pSupported = VK_FALSE;
unsupportedBlocks.push_back(block);
}
@@ -10299,25 +11003,38 @@
enum structure_type {
STRUCTURE_FEATURE = 0,
STRUCTURE_PROPERTY,
+ STRUCTURE_QUEUE_FAMILY,
STRUCTURE_FORMAT
};
-VPAPI_ATTR VkResult vpGetProfileStructureTypes(const VpProfileProperties *pProfile, const char* pBlockName, structure_type type, uint32_t *pStructureTypeCount, VkStructureType *pStructureTypes) {
+VPAPI_ATTR VkResult vpGetProfileStructureTypes(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ structure_type type,
+ uint32_t* pStructureTypeCount,
+ VkStructureType* pStructureTypes) {
+#ifdef VP_USE_OBJECT
+ (void)capabilities;
+#endif//VP_USE_OBJECT
+
VkResult result = pBlockName == nullptr ? VK_SUCCESS : VK_INCOMPLETE;
std::vector<VkStructureType> results;
- const std::vector<VpProfileProperties>& profiles = detail::GatherProfiles(*pProfile);
+ const std::vector<VpProfileProperties>& gathered_profiles = detail::GatherProfiles(*pProfile);
- for (std::size_t profile_index = 0, profile_count = profiles.size(); profile_index < profile_count; ++profile_index) {
- const detail::VpProfileDesc* profile_desc = detail::vpGetProfileDesc(profiles[profile_index].profileName);
+ for (std::size_t profile_index = 0, profile_count = gathered_profiles.size(); profile_index < profile_count; ++profile_index) {
+ const detail::VpProfileDesc* profile_desc = detail::vpGetProfileDesc(gathered_profiles[profile_index].profileName);
if (profile_desc == nullptr) return VK_ERROR_UNKNOWN;
for (uint32_t capability_index = 0; capability_index < profile_desc->requiredCapabilityCount; ++capability_index) {
- const detail::VpCapabilitiesDesc& capabilities = profile_desc->pRequiredCapabilities[capability_index];
+ const detail::VpCapabilitiesDesc& cap_desc = profile_desc->pRequiredCapabilities[capability_index];
- for (uint32_t variant_index = 0; variant_index < capabilities.variantCount; ++variant_index) {
- const detail::VpVariantDesc& variant = capabilities.pVariants[variant_index];
+ for (uint32_t variant_index = 0; variant_index < cap_desc.variantCount; ++variant_index) {
+ const detail::VpVariantDesc& variant = cap_desc.pVariants[variant_index];
if (pBlockName != nullptr) {
if (strcmp(variant.blockName, pBlockName) != 0) {
continue;
@@ -10338,16 +11055,20 @@
count = variant.propertyStructTypeCount;
data = variant.pPropertyStructTypes;
break;
+ case STRUCTURE_QUEUE_FAMILY:
+ count = variant.queueFamilyStructTypeCount;
+ data = variant.pQueueFamilyStructTypes;
+ break;
case STRUCTURE_FORMAT:
count = variant.formatStructTypeCount;
data = variant.pFormatStructTypes;
break;
}
- for (uint32_t i = 0; i < count; ++i) {
- const VkStructureType type = data[i];
- if (std::find(results.begin(), results.end(), type) == std::end(results)) {
- results.push_back(type);
+ for (uint32_t type_index = 0; type_index < count; ++type_index) {
+ const VkStructureType dataType = data[type_index];
+ if (std::find(results.begin(), results.end(), dataType) == std::end(results)) {
+ results.push_back(dataType);
}
}
}
@@ -10379,22 +11100,36 @@
EXTENSION_DEVICE,
};
-VPAPI_ATTR VkResult vpGetProfileExtensionProperties(const VpProfileProperties *pProfile, const char* pBlockName, ExtensionType type, uint32_t *pPropertyCount, VkExtensionProperties *pProperties) {
+VPAPI_ATTR VkResult vpGetProfileExtensionProperties(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ ExtensionType type,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties) {
+#ifdef VP_USE_OBJECT
+ (void)capabilities;
+#endif//VP_USE_OBJECT
+
VkResult result = pBlockName == nullptr ? VK_SUCCESS : VK_INCOMPLETE;
std::vector<VkExtensionProperties> results;
- const std::vector<VpProfileProperties>& profiles = detail::GatherProfiles(*pProfile, pBlockName);
+ const std::vector<VpProfileProperties>& gathered_profiles = detail::GatherProfiles(*pProfile, pBlockName);
- for (std::size_t profile_index = 0, profile_count = profiles.size(); profile_index < profile_count; ++profile_index) {
- const detail::VpProfileDesc* profile_desc = detail::vpGetProfileDesc(profiles[profile_index].profileName);
- if (profile_desc == nullptr) return VK_ERROR_UNKNOWN;
+ for (std::size_t profile_index = 0, profile_count = gathered_profiles.size(); profile_index < profile_count; ++profile_index) {
+ const detail::VpProfileDesc* profile_desc = detail::vpGetProfileDesc(gathered_profiles[profile_index].profileName);
+ if (profile_desc == nullptr) {
+ return VK_ERROR_UNKNOWN;
+ }
for (uint32_t capability_index = 0; capability_index < profile_desc->requiredCapabilityCount; ++capability_index) {
- const detail::VpCapabilitiesDesc& capabilities = profile_desc->pRequiredCapabilities[capability_index];
+ const detail::VpCapabilitiesDesc& cap_desc = profile_desc->pRequiredCapabilities[capability_index];
- for (uint32_t variant_index = 0; variant_index < capabilities.variantCount; ++variant_index) {
- const detail::VpVariantDesc& variant = capabilities.pVariants[variant_index];
+ for (uint32_t variant_index = 0; variant_index < cap_desc.variantCount; ++variant_index) {
+ const detail::VpVariantDesc& variant = cap_desc.pVariants[variant_index];
if (pBlockName != nullptr) {
if (strcmp(variant.blockName, pBlockName) != 0) {
continue;
@@ -10405,19 +11140,19 @@
switch (type) {
default:
case EXTENSION_INSTANCE:
- for (uint32_t i = 0; i < variant.instanceExtensionCount; ++i) {
- if (detail::HasExtension(results, variant.pInstanceExtensions[i])) {
+ for (uint32_t ext_index = 0; ext_index < variant.instanceExtensionCount; ++ext_index) {
+ if (detail::HasExtension(results, variant.pInstanceExtensions[ext_index])) {
continue;
}
- results.push_back(variant.pInstanceExtensions[i]);
+ results.push_back(variant.pInstanceExtensions[ext_index]);
}
break;
case EXTENSION_DEVICE:
- for (uint32_t i = 0; i < variant.deviceExtensionCount; ++i) {
- if (detail::HasExtension(results, variant.pDeviceExtensions[i])) {
+ for (uint32_t ext_index = 0; ext_index < variant.deviceExtensionCount; ++ext_index) {
+ if (detail::HasExtension(results, variant.pDeviceExtensions[ext_index])) {
continue;
}
- results.push_back(variant.pDeviceExtensions[i]);
+ results.push_back(variant.pDeviceExtensions[ext_index]);
}
break;
}
@@ -10443,9 +11178,244 @@
return result;
}
+VPAPI_ATTR VkResult vpGetProfileVideoProfileDesc(
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t videoProfileIndex,
+ const detail::VpVideoProfileDesc** ppVideoProfileDesc) {
+ VkResult result = pBlockName == nullptr ? VK_SUCCESS : VK_INCOMPLETE;
+
+ uint32_t curr_base_video_profile_index = 0;
+
+ const std::vector<VpProfileProperties>& gathered_profiles = detail::GatherProfiles(*pProfile);
+
+ for (std::size_t profile_index = 0, profile_count = gathered_profiles.size(); profile_index < profile_count; ++profile_index) {
+ const detail::VpProfileDesc* profile_desc = detail::vpGetProfileDesc(gathered_profiles[profile_index].profileName);
+ if (profile_desc == nullptr) return VK_ERROR_UNKNOWN;
+
+ for (uint32_t capability_index = 0; capability_index < profile_desc->requiredCapabilityCount; ++capability_index) {
+ const detail::VpCapabilitiesDesc& cap_desc = profile_desc->pRequiredCapabilities[capability_index];
+
+ for (uint32_t variant_index = 0; variant_index < cap_desc.variantCount; ++variant_index) {
+ const detail::VpVariantDesc& variant = cap_desc.pVariants[variant_index];
+ if (pBlockName != nullptr) {
+ if (strcmp(variant.blockName, pBlockName) != 0) {
+ continue;
+ }
+ result = VK_SUCCESS;
+ }
+
+ if (videoProfileIndex < curr_base_video_profile_index + variant.videoProfileCount) {
+ *ppVideoProfileDesc = &variant.pVideoProfiles[videoProfileIndex - curr_base_video_profile_index];
+ return result;
+ } else {
+ curr_base_video_profile_index += variant.videoProfileCount;
+ }
+ }
+ }
+ }
+
+ *ppVideoProfileDesc = nullptr;
+ return VK_ERROR_UNKNOWN;
+}
+
} // namespace detail
-VPAPI_ATTR VkResult vpGetProfiles(uint32_t *pPropertyCount, VpProfileProperties *pProperties) {
+struct VpCapabilities_T : public VpVulkanFunctions {
+ bool singleton = false;
+ uint32_t apiVersion = VK_API_VERSION_1_0;
+
+ static VpCapabilities_T& Get() {
+ static VpCapabilities_T instance;
+ VpCapabilitiesCreateInfo createInfo{};
+ createInfo.flags = VP_PROFILE_CREATE_STATIC_BIT;
+ instance.init(&createInfo);
+ instance.singleton = true;
+ return instance;
+ }
+
+ VpCapabilities_T() {
+ this->GetInstanceProcAddr = nullptr;
+ this->GetDeviceProcAddr = nullptr;
+ this->EnumerateInstanceVersion = nullptr;
+ this->EnumerateInstanceExtensionProperties = nullptr;
+ this->EnumerateDeviceExtensionProperties = nullptr;
+ this->GetPhysicalDeviceFeatures2 = nullptr;
+ this->GetPhysicalDeviceProperties2 = nullptr;
+ this->GetPhysicalDeviceFormatProperties2 = nullptr;
+ this->GetPhysicalDeviceQueueFamilyProperties2 = nullptr;
+ this->CreateInstance = nullptr;
+ this->CreateDevice = nullptr;
+ }
+
+ VkResult init(const VpCapabilitiesCreateInfo* pCreateInfo) {
+ assert(pCreateInfo != nullptr);
+
+ return ImportVulkanFunctions(pCreateInfo);
+ }
+
+ VkResult ImportVulkanFunctions(const VpCapabilitiesCreateInfo* pCreateInfo) {
+ if (pCreateInfo->flags & VP_PROFILE_CREATE_STATIC_BIT) {
+ ImportVulkanFunctions_Static();
+ }
+
+ if (pCreateInfo->pVulkanFunctions != nullptr) {
+ ImportVulkanFunctions_Custom((VpVulkanFunctions*)pCreateInfo->pVulkanFunctions);
+ }
+/*
+ if (pCreateInfo->flags & VP_PROFILE_CREATE_DYNAMIC_BIT) {
+ ImportVulkanFunctions_Dynamic();
+ }
+*/
+ return ValidateVulkanFunctions();
+ }
+
+ void ImportVulkanFunctions_Static() {
+ // Vulkan 1.1
+ this->GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)vkGetInstanceProcAddr;
+ this->GetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetDeviceProcAddr;
+
+ this->EnumerateInstanceVersion = (PFN_vkEnumerateInstanceVersion)vkEnumerateInstanceVersion;
+ this->EnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)vkEnumerateInstanceExtensionProperties;
+ this->EnumerateDeviceExtensionProperties = (PFN_vkEnumerateDeviceExtensionProperties)vkEnumerateDeviceExtensionProperties;
+
+ this->GetPhysicalDeviceFeatures2 = (PFN_vkGetPhysicalDeviceFeatures2)vkGetPhysicalDeviceFeatures2;
+ this->GetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2)vkGetPhysicalDeviceProperties2;
+ this->GetPhysicalDeviceFormatProperties2 = (PFN_vkGetPhysicalDeviceFormatProperties2)vkGetPhysicalDeviceFormatProperties2;
+ this->GetPhysicalDeviceQueueFamilyProperties2 = (PFN_vkGetPhysicalDeviceQueueFamilyProperties2)vkGetPhysicalDeviceQueueFamilyProperties2;
+
+ this->CreateInstance = (PFN_vkCreateInstance)vkCreateInstance;
+ this->CreateDevice = (PFN_vkCreateDevice)vkCreateDevice;
+ }
+
+ void ImportVulkanFunctions_Custom(VpVulkanFunctions* pFunctions) {
+ #define VP_COPY_IF_NOT_NULL(funcName) if(pFunctions->funcName != nullptr) this->funcName = pFunctions->funcName;
+
+ VP_COPY_IF_NOT_NULL(GetInstanceProcAddr);
+ VP_COPY_IF_NOT_NULL(GetDeviceProcAddr);
+
+ VP_COPY_IF_NOT_NULL(EnumerateInstanceVersion);
+ VP_COPY_IF_NOT_NULL(EnumerateInstanceExtensionProperties);
+ VP_COPY_IF_NOT_NULL(EnumerateDeviceExtensionProperties);
+
+ VP_COPY_IF_NOT_NULL(GetPhysicalDeviceFeatures2);
+ VP_COPY_IF_NOT_NULL(GetPhysicalDeviceProperties2);
+ VP_COPY_IF_NOT_NULL(GetPhysicalDeviceFormatProperties2);
+ VP_COPY_IF_NOT_NULL(GetPhysicalDeviceQueueFamilyProperties2);
+
+ VP_COPY_IF_NOT_NULL(CreateInstance);
+ VP_COPY_IF_NOT_NULL(CreateDevice);
+ #undef VP_COPY_IF_NOT_NULL
+ }
+/*
+ VkResult ImportVulkanFunctions_Dynamic() {
+ // To use VP_PROFILE_CREATE_DYNAMIC_BIT you have to pass VpVulkanFunctions::vkGetInstanceProcAddr and vkGetDeviceProcAddr as VpCapabilitiesCreateInfo::pVulkanFunctions. Other members can be null.
+ if (this->GetInstanceProcAddr == nullptr || this->GetDeviceProcAddr == nullptr) {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ #define VP_FETCH_INSTANCE_FUNC(memberName, functionNameString) if(this->memberName == nullptr) this->memberName = (PFN_vk##memberName)this->GetInstanceProcAddr(m_hInstance, functionNameString);
+ #define VP_FETCH_DEVICE_FUNC(memberName, functionNameString) if(this->memberName == nullptr) this->memberName = (PFN_vk##memberName)this->GetDeviceProcAddr(m_hDevice, functionNameString);
+
+ VP_FETCH_INSTANCE_FUNC(GetInstanceProcAddr, "vkGetInstanceProcAddr");
+ VP_FETCH_DEVICE_FUNC(GetDeviceProcAddr, "vkGetDeviceProcAddr");
+
+ VP_FETCH_INSTANCE_FUNC(EnumerateInstanceVersion, "vkEnumerateInstanceVersion");
+ VP_FETCH_INSTANCE_FUNC(EnumerateInstanceExtensionProperties, "vkEnumerateInstanceExtensionProperties");
+ VP_FETCH_DEVICE_FUNC(EnumerateDeviceExtensionProperties, "vkEnumerateDeviceExtensionProperties");
+
+ VP_FETCH_DEVICE_FUNC(GetPhysicalDeviceFeatures2, "vkGetPhysicalDeviceFeatures2");
+ VP_FETCH_DEVICE_FUNC(GetPhysicalDeviceProperties2, "vkGetPhysicalDeviceProperties2");
+ VP_FETCH_DEVICE_FUNC(GetPhysicalDeviceFormatProperties2, "vkGetPhysicalDeviceFormatProperties2");
+ VP_FETCH_DEVICE_FUNC(GetPhysicalDeviceQueueFamilyProperties2, "vkGetPhysicalDeviceQueueFamilyProperties2");
+
+ VP_FETCH_INSTANCE_FUNC(CreateInstance, "vkCreateInstance");
+ VP_FETCH_DEVICE_FUNC(CreateDevice, "vkCreateDevice");
+ #undef VP_FETCH_DEVICE_FUNC
+ #undef VP_FETCH_INSTANCE_FUNC
+ }
+*/
+ VkResult ValidateVulkanFunctions() {
+ if (this->GetInstanceProcAddr == nullptr) {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ if (this->GetDeviceProcAddr == nullptr) {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ if (this->EnumerateInstanceVersion == nullptr && apiVersion >= VK_API_VERSION_1_1) {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ if (this->EnumerateInstanceExtensionProperties == nullptr) {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ if (this->EnumerateDeviceExtensionProperties == nullptr) {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ if (this->GetPhysicalDeviceFeatures2 == nullptr) {
+ return apiVersion >= VK_API_VERSION_1_1 ? VK_ERROR_INITIALIZATION_FAILED : VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ if (this->GetPhysicalDeviceProperties2 == nullptr) {
+ return apiVersion >= VK_API_VERSION_1_1 ? VK_ERROR_INITIALIZATION_FAILED : VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ if (this->GetPhysicalDeviceFormatProperties2 == nullptr) {
+ return apiVersion >= VK_API_VERSION_1_1 ? VK_ERROR_INITIALIZATION_FAILED : VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ if (this->GetPhysicalDeviceQueueFamilyProperties2 == nullptr) {
+ return apiVersion >= VK_API_VERSION_1_1 ? VK_ERROR_INITIALIZATION_FAILED : VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ if (this->CreateInstance == nullptr) {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ if (this->CreateDevice == nullptr) {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ return VK_SUCCESS;
+ }
+};
+
+VPAPI_ATTR VkResult vpCreateCapabilities(
+ const VpCapabilitiesCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VpCapabilities* pCapabilities) {
+ (void)pAllocator;
+
+ VpCapabilities_T* capabilities = new VpCapabilities_T();
+ VkResult result = capabilities->init(pCreateInfo);
+ *pCapabilities = capabilities;
+
+ return result;
+}
+
+/// Destroys allocator object.
+VPAPI_ATTR void vpDestroyCapabilities(
+ VpCapabilities capabilities,
+ const VkAllocationCallbacks* pAllocator) {
+ (void)pAllocator;
+
+ delete capabilities;
+}
+
+VPAPI_ATTR VkResult vpGetProfiles(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ uint32_t* pPropertyCount,
+ VpProfileProperties* pProperties) {
+#ifdef VP_USE_OBJECT
+ (void)capabilities;
+#endif//VP_USE_OBJECT
+
VkResult result = VK_SUCCESS;
if (pProperties == nullptr) {
@@ -10456,83 +11426,128 @@
} else {
*pPropertyCount = detail::profileCount;
}
- for (uint32_t i = 0; i < *pPropertyCount; ++i) {
- pProperties[i] = detail::profiles[i].props;
+ for (uint32_t property_index = 0; property_index < *pPropertyCount; ++property_index) {
+ pProperties[property_index] = detail::profiles[property_index].props;
}
}
return result;
}
-VPAPI_ATTR VkResult vpGetProfileRequiredProfiles(const VpProfileProperties *pProfile, uint32_t *pPropertyCount, VpProfileProperties *pProperties) {
+VPAPI_ATTR VkResult vpGetProfileRequiredProfiles(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ uint32_t* pPropertyCount,
+ VpProfileProperties* pProperties) {
+#ifdef VP_USE_OBJECT
+ (void)capabilities;
+#endif//VP_USE_OBJECT
+
VkResult result = VK_SUCCESS;
- const detail::VpProfileDesc* pDesc = detail::vpGetProfileDesc(pProfile->profileName);
- if (pDesc == nullptr) return VK_ERROR_UNKNOWN;
+ const detail::VpProfileDesc* desc = detail::vpGetProfileDesc(pProfile->profileName);
+ if (desc == nullptr) {
+ return VK_ERROR_UNKNOWN;
+ }
if (pProperties == nullptr) {
- *pPropertyCount = pDesc->requiredProfileCount;
+ *pPropertyCount = desc->requiredProfileCount;
} else {
- if (*pPropertyCount < pDesc->requiredProfileCount) {
+ if (*pPropertyCount < desc->requiredProfileCount) {
result = VK_INCOMPLETE;
} else {
- *pPropertyCount = pDesc->requiredProfileCount;
+ *pPropertyCount = desc->requiredProfileCount;
}
- for (uint32_t i = 0; i < *pPropertyCount; ++i) {
- pProperties[i] = pDesc->pRequiredProfiles[i];
+ for (uint32_t property_index = 0; property_index < *pPropertyCount; ++property_index) {
+ pProperties[property_index] = desc->pRequiredProfiles[property_index];
}
}
return result;
}
-VPAPI_ATTR uint32_t vpGetProfileAPIVersion(const VpProfileProperties* pProfile) {
- const std::vector<VpProfileProperties>& profiles = detail::GatherProfiles(*pProfile, nullptr);
+VPAPI_ATTR uint32_t vpGetProfileAPIVersion(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile) {
+#ifdef VP_USE_OBJECT
+ (void)capabilities;
+#endif//VP_USE_OBJECT
+
+ const std::vector<VpProfileProperties>& gathered_profiles = detail::GatherProfiles(*pProfile, nullptr);
uint32_t major = 0;
uint32_t minor = 0;
uint32_t patch = 0;
- for (std::size_t i = 0, n = profiles.size(); i < n; ++i) {
- const detail::VpProfileDesc* pDesc = detail::vpGetProfileDesc(profiles[i].profileName);
- if (pDesc == nullptr) return 0;
+ for (std::size_t profile_index = 0, profile_count = gathered_profiles.size(); profile_index < profile_count; ++profile_index) {
+ const detail::VpProfileDesc* desc = detail::vpGetProfileDesc(gathered_profiles[profile_index].profileName);
+ if (desc == nullptr) {
+ return 0;
+ }
- major = std::max<uint32_t>(major, VK_API_VERSION_MAJOR(pDesc->minApiVersion));
- minor = std::max<uint32_t>(minor, VK_API_VERSION_MINOR(pDesc->minApiVersion));
- patch = std::max<uint32_t>(patch, VK_API_VERSION_PATCH(pDesc->minApiVersion));
+ major = std::max<uint32_t>(major, VK_API_VERSION_MAJOR(desc->minApiVersion));
+ minor = std::max<uint32_t>(minor, VK_API_VERSION_MINOR(desc->minApiVersion));
+ patch = std::max<uint32_t>(patch, VK_API_VERSION_PATCH(desc->minApiVersion));
}
return VK_MAKE_API_VERSION(0, major, minor, patch);
}
-VPAPI_ATTR VkResult vpGetProfileFallbacks(const VpProfileProperties *pProfile, uint32_t *pPropertyCount, VpProfileProperties *pProperties) {
+VPAPI_ATTR VkResult vpGetProfileFallbacks(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ uint32_t* pPropertyCount,
+ VpProfileProperties* pProperties) {
+#ifdef VP_USE_OBJECT
+ (void)capabilities;
+#endif//VP_USE_OBJECT
+
VkResult result = VK_SUCCESS;
- const detail::VpProfileDesc* pDesc = detail::vpGetProfileDesc(pProfile->profileName);
- if (pDesc == nullptr) return VK_ERROR_UNKNOWN;
+ const detail::VpProfileDesc* desc = detail::vpGetProfileDesc(pProfile->profileName);
+ if (desc == nullptr) {
+ return VK_ERROR_UNKNOWN;
+ }
if (pProperties == nullptr) {
- *pPropertyCount = pDesc->fallbackCount;
+ *pPropertyCount = desc->fallbackCount;
} else {
- if (*pPropertyCount < pDesc->fallbackCount) {
+ if (*pPropertyCount < desc->fallbackCount) {
result = VK_INCOMPLETE;
} else {
- *pPropertyCount = pDesc->fallbackCount;
+ *pPropertyCount = desc->fallbackCount;
}
for (uint32_t i = 0; i < *pPropertyCount; ++i) {
- pProperties[i] = pDesc->pFallbacks[i];
+ pProperties[i] = desc->pFallbacks[i];
}
}
return result;
}
-VPAPI_ATTR VkResult vpHasMultipleVariantsProfile(const VpProfileProperties *pProfile, VkBool32 *pHasMultipleVariants) {
- const std::vector<VpProfileProperties>& profiles = detail::GatherProfiles(*pProfile, nullptr);
+VPAPI_ATTR VkResult vpHasMultipleVariantsProfile(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ VkBool32* pHasMultipleVariants) {
+#ifdef VP_USE_OBJECT
+ (void)capabilities;
+#endif//VP_USE_OBJECT
- for (std::size_t profile_index = 0, profile_count = profiles.size(); profile_index < profile_count; ++profile_index) {
- const detail::VpProfileDesc* pDesc = detail::vpGetProfileDesc(profiles[profile_index].profileName);
- if (pDesc == nullptr) return VK_ERROR_UNKNOWN;
+ const std::vector<VpProfileProperties>& gathered_profiles = detail::GatherProfiles(*pProfile, nullptr);
- for (uint32_t capabilities_index = 0, n = pDesc->requiredCapabilityCount; capabilities_index < n; ++capabilities_index) {
- if (pDesc->pRequiredCapabilities[capabilities_index].variantCount > 1) {
+ for (std::size_t profile_index = 0, profile_count = gathered_profiles.size(); profile_index < profile_count; ++profile_index) {
+ const detail::VpProfileDesc* desc = detail::vpGetProfileDesc(gathered_profiles[profile_index].profileName);
+ if (desc == nullptr) {
+ return VK_ERROR_UNKNOWN;
+ }
+
+ for (uint32_t caps_index = 0, caps_count = desc->requiredCapabilityCount; caps_index < caps_count; ++caps_index) {
+ if (desc->pRequiredCapabilities[caps_index].variantCount > 1) {
*pHasMultipleVariants = VK_TRUE;
return VK_SUCCESS;
}
@@ -10543,22 +11558,37 @@
return VK_SUCCESS;
}
-VPAPI_ATTR VkResult vpGetInstanceProfileVariantsSupport(const char *pLayerName, const VpProfileProperties *pProfile, VkBool32 *pSupported, uint32_t *pPropertyCount, VpBlockProperties* pProperties) {
+VPAPI_ATTR VkResult vpGetInstanceProfileVariantsSupport(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const char* pLayerName,
+ const VpProfileProperties* pProfile,
+ VkBool32* pSupported,
+ uint32_t* pPropertyCount,
+ VpBlockProperties* pProperties) {
+#ifdef VP_USE_OBJECT
+ const VpCapabilities_T& vp = capabilities == nullptr ? VpCapabilities_T::Get() : *capabilities;
+#else
+ const VpCapabilities_T& vp = VpCapabilities_T::Get();
+#endif//VP_USE_OBJECT
+
VkResult result = VK_SUCCESS;
- uint32_t api_version = VK_MAKE_API_VERSION(0, 1, 0, 0);
- static PFN_vkEnumerateInstanceVersion pfnEnumerateInstanceVersion =
- (PFN_vkEnumerateInstanceVersion)vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceVersion");
+ uint32_t api_version = VK_API_VERSION_1_0;
+ PFN_vkEnumerateInstanceVersion pfnEnumerateInstanceVersion = vp.singleton ?
+ (PFN_vkEnumerateInstanceVersion)vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceVersion") : vp.EnumerateInstanceVersion;
if (pfnEnumerateInstanceVersion != nullptr) {
result = pfnEnumerateInstanceVersion(&api_version);
if (result != VK_SUCCESS) {
*pSupported = VK_FALSE;
return result;
- }
+ } /* else {
+ } */
}
uint32_t supported_instance_extension_count = 0;
- result = vkEnumerateInstanceExtensionProperties(pLayerName, &supported_instance_extension_count, nullptr);
+ result = vp.EnumerateInstanceExtensionProperties(pLayerName, &supported_instance_extension_count, nullptr);
if (result != VK_SUCCESS) {
*pSupported = VK_FALSE;
return result;
@@ -10567,7 +11597,7 @@
if (supported_instance_extension_count > 0) {
supported_instance_extensions.resize(supported_instance_extension_count);
}
- result = vkEnumerateInstanceExtensionProperties(pLayerName, &supported_instance_extension_count, supported_instance_extensions.data());
+ result = vp.EnumerateInstanceExtensionProperties(pLayerName, &supported_instance_extension_count, supported_instance_extensions.data());
if (result != VK_SUCCESS) {
*pSupported = VK_FALSE;
return result;
@@ -10578,14 +11608,13 @@
// We require VK_KHR_get_physical_device_properties2 if we are on Vulkan 1.0
if (api_version < VK_API_VERSION_1_1) {
bool foundGPDP2 = false;
- for (size_t i = 0; i < supported_instance_extensions.size(); ++i) {
- if (strcmp(supported_instance_extensions[i].extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == 0) {
+ for (size_t ext_index = 0, ext_count = supported_instance_extensions.size(); ext_index < ext_count; ++ext_index) {
+ if (strcmp(supported_instance_extensions[ext_index].extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == 0) {
foundGPDP2 = true;
break;
}
}
if (!foundGPDP2) {
- VP_DEBUG_MSG("Unsupported mandatory extension VK_KHR_get_physical_device_properties2 on Vulkan 1.0");
supported = VK_FALSE;
}
}
@@ -10601,9 +11630,9 @@
*pSupported = supported;
return result;
}
-
- for (std::size_t i = 0; i < pProfileDesc->requiredProfileCount; ++i) {
- result = detail::vpGetInstanceProfileSupportSingleProfile(0, supported_instance_extensions, &pProfileDesc->pRequiredProfiles[i], &supported, supported_blocks, unsupported_blocks);
+
+ for (std::size_t required_profile_index = 0; required_profile_index < pProfileDesc->requiredProfileCount; ++required_profile_index) {
+ result = detail::vpGetInstanceProfileSupportSingleProfile(0, supported_instance_extensions, &pProfileDesc->pRequiredProfiles[required_profile_index], &supported, supported_blocks, unsupported_blocks);
if (result != VK_SUCCESS) {
*pSupported = supported;
return result;
@@ -10620,8 +11649,8 @@
} else {
*pPropertyCount = static_cast<uint32_t>(blocks.size());
}
- for (uint32_t i = 0, n = static_cast<uint32_t>(blocks.size()); i < n; ++i) {
- pProperties[i] = blocks[i];
+ for (uint32_t block_index = 0, block_count = static_cast<uint32_t>(blocks.size()); block_index < block_count; ++block_index) {
+ pProperties[block_index] = blocks[block_index];
}
}
@@ -10629,16 +11658,37 @@
return result;
}
-VPAPI_ATTR VkResult vpGetInstanceProfileSupport(const char *pLayerName, const VpProfileProperties *pProfile, VkBool32 *pSupported) {
+VPAPI_ATTR VkResult vpGetInstanceProfileSupport(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const char* pLayerName,
+ const VpProfileProperties* pProfile,
+ VkBool32* pSupported) {
uint32_t count = 0;
- return vpGetInstanceProfileVariantsSupport(pLayerName, pProfile, pSupported, &count, nullptr);
+
+ return vpGetInstanceProfileVariantsSupport(
+#ifdef VP_USE_OBJECT
+ capabilities,
+#endif//VP_USE_OBJECT
+ pLayerName, pProfile, pSupported, &count, nullptr);
}
+VPAPI_ATTR VkResult vpCreateInstance(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpInstanceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkInstance* pInstance) {
+#ifdef VP_USE_OBJECT
+ const VpCapabilities_T& vp = capabilities == nullptr ? VpCapabilities_T::Get() : *capabilities;
+#else
+ const VpCapabilities_T& vp = VpCapabilities_T::Get();
+#endif//VP_USE_OBJECT
-VPAPI_ATTR VkResult vpCreateInstance(const VpInstanceCreateInfo *pCreateInfo,
- const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
if (pCreateInfo == nullptr || pInstance == nullptr) {
- return vkCreateInstance(pCreateInfo == nullptr ? nullptr : pCreateInfo->pCreateInfo, pAllocator, pInstance);
+ return vp.CreateInstance(pCreateInfo == nullptr ? nullptr : pCreateInfo->pCreateInfo, pAllocator, pInstance);
}
const std::vector<VpBlockProperties>& blocks = detail::GatherBlocks(
@@ -10646,22 +11696,24 @@
pCreateInfo->enabledProfileBlockCount, pCreateInfo->pEnabledProfileBlocks);
std::vector<const char*> extensions;
- for (std::uint32_t i = 0, n = pCreateInfo->pCreateInfo->enabledExtensionCount; i < n; ++i) {
- extensions.push_back(pCreateInfo->pCreateInfo->ppEnabledExtensionNames[i]);
+ for (std::uint32_t ext_index = 0, ext_count = pCreateInfo->pCreateInfo->enabledExtensionCount; ext_index < ext_count; ++ext_index) {
+ extensions.push_back(pCreateInfo->pCreateInfo->ppEnabledExtensionNames[ext_index]);
}
- for (std::size_t i = 0, n = blocks.size(); i < n; ++i) {
- const detail::VpProfileDesc* pProfileDesc = detail::vpGetProfileDesc(blocks[i].profiles.profileName);
- if (pProfileDesc == nullptr) return VK_ERROR_UNKNOWN;
+ for (std::size_t block_index = 0, block_count = blocks.size(); block_index < block_count; ++block_index) {
+ const detail::VpProfileDesc* profile_desc = detail::vpGetProfileDesc(blocks[block_index].profiles.profileName);
+ if (profile_desc == nullptr) {
+ return VK_ERROR_UNKNOWN;
+ }
- for (std::size_t j = 0, p = pProfileDesc->requiredCapabilityCount; j < p; ++j) {
- const detail::VpCapabilitiesDesc* pCapsDesc = &pProfileDesc->pRequiredCapabilities[j];
+ for (std::size_t caps_index = 0, caps_count = profile_desc->requiredCapabilityCount; caps_index < caps_count; ++caps_index) {
+ const detail::VpCapabilitiesDesc* caps_desc = &profile_desc->pRequiredCapabilities[caps_index];
- for (std::size_t v = 0, q = pCapsDesc->variantCount; v < q; ++v) {
- const detail::VpVariantDesc* variant = &pCapsDesc->pVariants[v];
+ for (std::size_t variant_index = 0, variant_count = caps_desc->variantCount; variant_index < variant_count; ++variant_index) {
+ const detail::VpVariantDesc* variant = &caps_desc->pVariants[variant_index];
- if (strcmp(blocks[i].blockName, "") != 0) {
- if (strcmp(variant->blockName, blocks[i].blockName) != 0) {
+ if (strcmp(blocks[block_index].blockName, "") != 0) {
+ if (strcmp(variant->blockName, blocks[block_index].blockName) != 0) {
continue;
}
}
@@ -10675,7 +11727,11 @@
if (pCreateInfo->pCreateInfo->pApplicationInfo != nullptr) {
appInfo = *pCreateInfo->pCreateInfo->pApplicationInfo;
} else if (!blocks.empty()) {
- appInfo.apiVersion = vpGetProfileAPIVersion(&blocks[0].profiles);
+ appInfo.apiVersion = vpGetProfileAPIVersion(
+#ifdef VP_USE_OBJECT
+ capabilities,
+#endif//VP_USE_OBJECT
+ &blocks[0].profiles);
}
VkInstanceCreateInfo createInfo = *pCreateInfo->pCreateInfo;
@@ -10684,8 +11740,8 @@
// Need to include VK_KHR_get_physical_device_properties2 if we are on Vulkan 1.0
if (createInfo.pApplicationInfo->apiVersion < VK_API_VERSION_1_1) {
bool foundGPDP2 = false;
- for (size_t i = 0; i < extensions.size(); ++i) {
- if (strcmp(extensions[i], VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == 0) {
+ for (size_t ext_index = 0, ext_count = extensions.size(); ext_index < ext_count; ++ext_index) {
+ if (strcmp(extensions[ext_index], VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == 0) {
foundGPDP2 = true;
break;
}
@@ -10697,8 +11753,8 @@
#ifdef __APPLE__
bool has_portability_ext = false;
- for (std::size_t i = 0, n = extensions.size(); i < n; ++i) {
- if (strcmp(extensions[i], VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) == 0) {
+ for (std::size_t ext_index = 0, ext_count = extensions.size(); ext_index < ext_count; ++ext_index) {
+ if (strcmp(extensions[ext_index], VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) == 0) {
has_portability_ext = true;
break;
}
@@ -10716,15 +11772,29 @@
createInfo.ppEnabledExtensionNames = extensions.data();
}
- return vkCreateInstance(&createInfo, pAllocator, pInstance);
+ return vp.CreateInstance(&createInfo, pAllocator, pInstance);
}
-VPAPI_ATTR VkResult vpGetPhysicalDeviceProfileVariantsSupport(VkInstance instance, VkPhysicalDevice physicalDevice,
- const VpProfileProperties *pProfile, VkBool32 *pSupported, uint32_t *pPropertyCount, VpBlockProperties* pProperties) {
+VPAPI_ATTR VkResult vpGetPhysicalDeviceProfileVariantsSupport(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ VkInstance instance,
+ VkPhysicalDevice physicalDevice,
+ const VpProfileProperties *pProfile,
+ VkBool32 *pSupported,
+ uint32_t *pPropertyCount,
+ VpBlockProperties* pProperties) {
+#ifdef VP_USE_OBJECT
+ const VpCapabilities_T& vp = capabilities == nullptr ? VpCapabilities_T::Get() : *capabilities;
+#else
+ const VpCapabilities_T& vp = VpCapabilities_T::Get();
+#endif//VP_USE_OBJECT
+
VkResult result = VK_SUCCESS;
uint32_t supported_device_extension_count = 0;
- result = vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &supported_device_extension_count, nullptr);
+ result = vp.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, &supported_device_extension_count, nullptr);
if (result != VK_SUCCESS) {
return result;
}
@@ -10732,7 +11802,7 @@
if (supported_device_extension_count > 0) {
supported_device_extensions.resize(supported_device_extension_count);
}
- result = vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &supported_device_extension_count, supported_device_extensions.data());
+ result = vp.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, &supported_device_extension_count, supported_device_extensions.data());
if (result != VK_SUCCESS) {
return result;
}
@@ -10742,8 +11812,12 @@
supported_device_extensions.resize(supported_device_extension_count);
}
- const detail::VpProfileDesc* pProfileDesc = detail::vpGetProfileDesc(pProfile->profileName);
- if (pProfileDesc == nullptr) return VK_ERROR_UNKNOWN;
+ {
+ const detail::VpProfileDesc* pProfileDesc = detail::vpGetProfileDesc(pProfile->profileName);
+ if (pProfileDesc == nullptr) {
+ return VK_ERROR_UNKNOWN;
+ }
+ }
struct GPDP2EntryPoints {
PFN_vkGetPhysicalDeviceFeatures2KHR pfnGetPhysicalDeviceFeatures2;
@@ -10752,6 +11826,18 @@
PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR pfnGetPhysicalDeviceQueueFamilyProperties2;
};
+#ifdef VK_KHR_video_queue
+ struct VideoInfo {
+ PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR pfnGetPhysicalDeviceVideoCapabilitiesKHR;
+ PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR pfnGetPhysicalDeviceVideoFormatPropertiesKHR;
+ const detail::VpVideoProfileDesc* pProfileDesc;
+ VkVideoProfileInfoKHR profileInfo;
+ VkPhysicalDeviceVideoFormatInfoKHR formatInfo;
+ bool supportedProfile;
+ uint32_t matchingProfiles;
+ };
+#endif // VK_KHR_video_queue
+
std::vector<VpBlockProperties> supported_blocks;
std::vector<VpBlockProperties> unsupported_blocks;
@@ -10761,21 +11847,32 @@
std::vector<VpBlockProperties>& unsupported_blocks;
const detail::VpVariantDesc* variant;
GPDP2EntryPoints gpdp2;
+#ifdef VK_KHR_video_queue
+ VideoInfo video;
+#endif // VK_KHR_video_queue
uint32_t index;
- uint32_t count;
detail::PFN_vpStructChainerCb pfnCb;
bool supported;
} userData{physicalDevice, supported_blocks, unsupported_blocks};
+ if (!vp.singleton) {
+ userData.gpdp2.pfnGetPhysicalDeviceFeatures2 = vp.GetPhysicalDeviceFeatures2;
+ userData.gpdp2.pfnGetPhysicalDeviceProperties2 = vp.GetPhysicalDeviceProperties2;
+ userData.gpdp2.pfnGetPhysicalDeviceFormatProperties2 = vp.GetPhysicalDeviceFormatProperties2;
+ userData.gpdp2.pfnGetPhysicalDeviceQueueFamilyProperties2 = vp.GetPhysicalDeviceQueueFamilyProperties2;
+ }
+
// Attempt to load core versions of the GPDP2 entry points
- userData.gpdp2.pfnGetPhysicalDeviceFeatures2 =
- (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2");
- userData.gpdp2.pfnGetPhysicalDeviceProperties2 =
- (PFN_vkGetPhysicalDeviceProperties2KHR)vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2");
- userData.gpdp2.pfnGetPhysicalDeviceFormatProperties2 =
- (PFN_vkGetPhysicalDeviceFormatProperties2KHR)vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties2");
- userData.gpdp2.pfnGetPhysicalDeviceQueueFamilyProperties2 =
- (PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties2");
+ if (userData.gpdp2.pfnGetPhysicalDeviceFeatures2 == nullptr) {
+ userData.gpdp2.pfnGetPhysicalDeviceFeatures2 =
+ (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2");
+ userData.gpdp2.pfnGetPhysicalDeviceProperties2 =
+ (PFN_vkGetPhysicalDeviceProperties2KHR)vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2");
+ userData.gpdp2.pfnGetPhysicalDeviceFormatProperties2 =
+ (PFN_vkGetPhysicalDeviceFormatProperties2KHR)vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties2");
+ userData.gpdp2.pfnGetPhysicalDeviceQueueFamilyProperties2 =
+ (PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties2");
+ }
// If not successful, try to load KHR variant
if (userData.gpdp2.pfnGetPhysicalDeviceFeatures2 == nullptr) {
@@ -10796,36 +11893,44 @@
return VK_ERROR_EXTENSION_NOT_PRESENT;
}
- VP_DEBUG_MSGF("Checking device support for profile %s (%s). You may find the details of the capabilities of this device on https://vulkan.gpuinfo.org/", pProfile->profileName, detail::vpGetDeviceAndDriverInfoString(physicalDevice, userData.gpdp2.pfnGetPhysicalDeviceProperties2).c_str());
+#ifdef VK_KHR_video_queue
+ PFN_vkGetInstanceProcAddr gipa = vp.singleton ? vkGetInstanceProcAddr : vp.GetInstanceProcAddr;
+ userData.video.pfnGetPhysicalDeviceVideoCapabilitiesKHR =
+ (PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR)gipa(instance, "vkGetPhysicalDeviceVideoCapabilitiesKHR");
+ userData.video.pfnGetPhysicalDeviceVideoFormatPropertiesKHR =
+ (PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR)gipa(instance, "vkGetPhysicalDeviceVideoFormatPropertiesKHR");
+#endif // VK_KHR_video_queue
bool supported = true;
- const std::vector<VpProfileProperties>& profiles = detail::GatherProfiles(*pProfile);
+ const std::vector<VpProfileProperties>& gathered_profiles = detail::GatherProfiles(*pProfile);
- for (std::size_t i = 0, n = profiles.size(); i < n; ++i) {
- const char* profile_name = profiles[i].profileName;
+ for (std::size_t profile_index = 0, profile_count = gathered_profiles.size(); profile_index < profile_count; ++profile_index) {
+ const char* profile_name = gathered_profiles[profile_index].profileName;
- const detail::VpProfileDesc* pProfileDesc = detail::vpGetProfileDesc(profile_name);
- if (pProfileDesc == nullptr) return VK_ERROR_UNKNOWN;
+ const detail::VpProfileDesc* profile_desc = detail::vpGetProfileDesc(profile_name);
+ if (profile_desc == nullptr) {
+ return VK_ERROR_UNKNOWN;
+ }
bool supported_profile = true;
-
- if (pProfileDesc->props.specVersion < pProfile->specVersion) {
+ if (profile_desc->props.specVersion < gathered_profiles[profile_index].specVersion) {
supported_profile = false;
}
- VpBlockProperties block{profiles[i], pProfileDesc->minApiVersion};
+ VpBlockProperties block{gathered_profiles[profile_index], profile_desc->minApiVersion};
- VkPhysicalDeviceProperties props{};
- vkGetPhysicalDeviceProperties(physicalDevice, &props);
- if (!detail::vpCheckVersion(props.apiVersion, pProfileDesc->minApiVersion)) {
- VP_DEBUG_MSGF("Unsupported API version: %u.%u.%u", VK_API_VERSION_MAJOR(pProfileDesc->minApiVersion), VK_API_VERSION_MINOR(pProfileDesc->minApiVersion), VK_API_VERSION_PATCH(pProfileDesc->minApiVersion));
- supported_profile = false;
+ {
+ VkPhysicalDeviceProperties2KHR properties2{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR };
+ userData.gpdp2.pfnGetPhysicalDeviceProperties2(physicalDevice, &properties2);
+ if (!detail::vpCheckVersion(properties2.properties.apiVersion, profile_desc->minApiVersion)) {
+ supported_profile = false;
+ }
}
- for (uint32_t required_capability_index = 0; required_capability_index < pProfileDesc->requiredCapabilityCount; ++required_capability_index) {
- const detail::VpCapabilitiesDesc* required_capabilities = &pProfileDesc->pRequiredCapabilities[required_capability_index];
+ for (uint32_t required_capability_index = 0; required_capability_index < profile_desc->requiredCapabilityCount; ++required_capability_index) {
+ const detail::VpCapabilitiesDesc* required_capabilities = &profile_desc->pRequiredCapabilities[required_capability_index];
bool supported_block = false;
@@ -10834,8 +11939,8 @@
bool supported_variant = true;
- for (uint32_t i = 0; i < variant_desc.deviceExtensionCount; ++i) {
- const char *requested_extension = variant_desc.pDeviceExtensions[i].extensionName;
+ for (uint32_t ext_index = 0; ext_index < variant_desc.deviceExtensionCount; ++ext_index) {
+ const char *requested_extension = variant_desc.pDeviceExtensions[ext_index].extensionName;
if (!detail::CheckExtension(supported_device_extensions.data(), supported_device_extensions.size(), requested_extension)) {
supported_variant = false;
}
@@ -10848,8 +11953,10 @@
static_cast<VkBaseOutStructure*>(static_cast<void*>(&features)), &userData,
[](VkBaseOutStructure* p, void* pUser) {
UserData* pUserData = static_cast<UserData*>(pUser);
- pUserData->gpdp2.pfnGetPhysicalDeviceFeatures2(pUserData->physicalDevice,
- static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p)));
+ pUserData->gpdp2.pfnGetPhysicalDeviceFeatures2(
+ pUserData->physicalDevice,
+ static_cast<VkPhysicalDeviceFeatures2KHR*>(static_cast<void*>(p)));
+
pUserData->supported = true;
while (p != nullptr) {
if (!pUserData->variant->feature.pfnComparator(p)) {
@@ -10863,13 +11970,15 @@
supported_variant = false;
}
- VkPhysicalDeviceProperties2KHR props{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR };
+ VkPhysicalDeviceProperties2KHR device_properties2{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR };
userData.variant->chainers.pfnProperty(
- static_cast<VkBaseOutStructure*>(static_cast<void*>(&props)), &userData,
+ static_cast<VkBaseOutStructure*>(static_cast<void*>(&device_properties2)), &userData,
[](VkBaseOutStructure* p, void* pUser) {
UserData* pUserData = static_cast<UserData*>(pUser);
- pUserData->gpdp2.pfnGetPhysicalDeviceProperties2(pUserData->physicalDevice,
- static_cast<VkPhysicalDeviceProperties2KHR*>(static_cast<void*>(p)));
+ pUserData->gpdp2.pfnGetPhysicalDeviceProperties2(
+ pUserData->physicalDevice,
+ static_cast<VkPhysicalDeviceProperties2KHR*>(static_cast<void*>(p)));
+
pUserData->supported = true;
while (p != nullptr) {
if (!pUserData->variant->property.pfnComparator(p)) {
@@ -10883,15 +11992,56 @@
supported_variant = false;
}
- for (uint32_t i = 0; i < userData.variant->formatCount && supported_variant; ++i) {
- userData.index = i;
- VkFormatProperties2KHR props{ VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR };
+ if (userData.variant->queueFamilyCount > 0) {
+ uint32_t queue_family_count = 0;
+ userData.gpdp2.pfnGetPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queue_family_count, nullptr);
+ std::vector<VkQueueFamilyProperties2KHR> queueFamilyProps(queue_family_count, { VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR });
+ userData.variant->chainers.pfnQueueFamily(
+ queue_family_count, static_cast<VkBaseOutStructure*>(static_cast<void*>(queueFamilyProps.data())), &userData,
+ [](uint32_t queue_family_count, VkBaseOutStructure* pBaseArray, void* pUser) {
+ UserData* pUserData = static_cast<UserData*>(pUser);
+ VkQueueFamilyProperties2KHR* pArray = static_cast<VkQueueFamilyProperties2KHR*>(static_cast<void*>(pBaseArray));
+ pUserData->gpdp2.pfnGetPhysicalDeviceQueueFamilyProperties2(pUserData->physicalDevice, &queue_family_count, pArray);
+ pUserData->supported = true;
+ for (uint32_t profile_qf_idx = 0; profile_qf_idx < pUserData->variant->queueFamilyCount; ++profile_qf_idx) {
+ bool found_matching = false;
+ for (uint32_t queue_family_index = 0; queue_family_index < queue_family_count; ++queue_family_index) {
+ bool this_matches = true;
+ VkBaseOutStructure* p = static_cast<VkBaseOutStructure*>(static_cast<void*>(&pArray[queue_family_index]));
+ while (p != nullptr) {
+ if (!pUserData->variant->pQueueFamilies[profile_qf_idx].pfnComparator(p)) {
+ this_matches = false;
+ }
+ p = p->pNext;
+ }
+ if (this_matches) {
+ found_matching = true;
+ break;
+ }
+ }
+ if (!found_matching) {
+ pUserData->supported = false;
+ break;
+ }
+ }
+ }
+ );
+ if (!userData.supported) {
+ supported_variant = false;
+ }
+ }
+
+ for (uint32_t format_index = 0; format_index < userData.variant->formatCount && supported_variant; ++format_index) {
+ userData.index = format_index;
+ VkFormatProperties2KHR format_properties2{ VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR };
userData.variant->chainers.pfnFormat(
- static_cast<VkBaseOutStructure*>(static_cast<void*>(&props)), &userData,
+ static_cast<VkBaseOutStructure*>(static_cast<void*>(&format_properties2)), &userData,
[](VkBaseOutStructure* p, void* pUser) {
UserData* pUserData = static_cast<UserData*>(pUser);
- pUserData->gpdp2.pfnGetPhysicalDeviceFormatProperties2(pUserData->physicalDevice, pUserData->variant->pFormats[pUserData->index].format,
- static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p)));
+ pUserData->gpdp2.pfnGetPhysicalDeviceFormatProperties2(
+ pUserData->physicalDevice,
+ pUserData->variant->pFormats[pUserData->index].format,
+ static_cast<VkFormatProperties2KHR*>(static_cast<void*>(p)));
pUserData->supported = true;
while (p != nullptr) {
if (!pUserData->variant->pFormats[pUserData->index].pfnComparator(p)) {
@@ -10906,6 +12056,113 @@
}
}
+#ifdef VK_KHR_video_queue
+ if (userData.variant->videoProfileCount > 0) {
+ VkVideoProfileListInfoKHR profile_list{ VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR };
+ profile_list.profileCount = 1;
+ profile_list.pProfiles = &userData.video.profileInfo;
+ userData.video.formatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR;
+ userData.video.formatInfo.pNext = &profile_list;
+
+ if (userData.video.pfnGetPhysicalDeviceVideoCapabilitiesKHR != nullptr &&
+ userData.video.pfnGetPhysicalDeviceVideoFormatPropertiesKHR != nullptr) {
+ for (uint32_t video_profile_index = 0; video_profile_index < userData.variant->videoProfileCount; ++video_profile_index) {
+ userData.video.profileInfo = VkVideoProfileInfoKHR{ VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR };
+ userData.video.pProfileDesc = &userData.variant->pVideoProfiles[video_profile_index];
+ userData.supported = true;
+ userData.video.matchingProfiles = 0;
+
+ detail::vpForEachMatchingVideoProfiles(&userData.video.profileInfo, &userData,
+ [](VkBaseOutStructure* p, void* pUser) {
+ UserData* pUserData = static_cast<UserData*>(pUser);
+ while (p != nullptr) {
+ if (!pUserData->video.pProfileDesc->info.pfnComparator(p)) {
+ return;
+ }
+ p = p->pNext;
+ }
+
+ pUserData->video.supportedProfile = true;
+
+ VkVideoCapabilitiesKHR capabilities{ VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR };
+ pUserData->video.pProfileDesc->chainers.pfnCapability(
+ static_cast<VkBaseOutStructure*>(static_cast<void*>(&capabilities)), pUserData,
+ [](VkBaseOutStructure* p, void* pUser) {
+ UserData* pUserData = static_cast<UserData*>(pUser);
+ VkResult result = pUserData->video.pfnGetPhysicalDeviceVideoCapabilitiesKHR(
+ pUserData->physicalDevice,
+ &pUserData->video.profileInfo,
+ static_cast<VkVideoCapabilitiesKHR*>(static_cast<void*>(p)));
+ if (result != VK_SUCCESS) {
+ pUserData->video.supportedProfile = false;
+ return;
+ }
+ while (p != nullptr) {
+ if (!pUserData->video.pProfileDesc->capability.pfnComparator(p)) {
+ pUserData->supported = false;
+ }
+ p = p->pNext;
+ }
+ }
+ );
+
+ if (pUserData->video.supportedProfile) {
+ pUserData->video.matchingProfiles++;
+ } else {
+ return;
+ }
+
+ std::vector<VkVideoFormatPropertiesKHR> format_props;
+ for (uint32_t format_index = 0; format_index < pUserData->video.pProfileDesc->formatCount; ++format_index) {
+ pUserData->index = format_index;
+ {
+ VkVideoFormatPropertiesKHR tmp_props{ VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR };
+ pUserData->video.pProfileDesc->pFormats[format_index].pfnFiller(static_cast<VkBaseOutStructure*>(static_cast<void*>(&tmp_props)));
+ pUserData->video.formatInfo.imageUsage = tmp_props.imageUsageFlags;
+ }
+
+ uint32_t format_count = 0;
+ pUserData->video.pfnGetPhysicalDeviceVideoFormatPropertiesKHR(pUserData->physicalDevice, &pUserData->video.formatInfo, &format_count, nullptr);
+ format_props.resize(format_count, { VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR });
+ pUserData->video.pProfileDesc->chainers.pfnFormat(
+ format_count, static_cast<VkBaseOutStructure*>(static_cast<void*>(format_props.data())), pUserData,
+ [](uint32_t format_count, VkBaseOutStructure* pBaseArray, void* pUser) {
+ UserData* pUserData = static_cast<UserData*>(pUser);
+ VkVideoFormatPropertiesKHR* pArray = static_cast<VkVideoFormatPropertiesKHR*>(static_cast<void*>(pBaseArray));
+ pUserData->video.pfnGetPhysicalDeviceVideoFormatPropertiesKHR(pUserData->physicalDevice, &pUserData->video.formatInfo, &format_count, pArray);
+ bool found_matching = false;
+ for (uint32_t i = 0; i < format_count; ++i) {
+ bool this_matches = true;
+ VkBaseOutStructure* p = static_cast<VkBaseOutStructure*>(static_cast<void*>(&pArray[i]));
+ while (p != nullptr) {
+ if (!pUserData->video.pProfileDesc->pFormats[pUserData->index].pfnComparator(p)) {
+ this_matches = false;
+ }
+ p = p->pNext;
+ }
+ if (this_matches) {
+ found_matching = true;
+ break;
+ }
+ }
+ if (!found_matching) {
+ pUserData->supported = false;
+ }
+ }
+ );
+ }
+ }
+ );
+ if (!userData.supported || userData.video.matchingProfiles == 0) {
+ supported_variant = false;
+ }
+ }
+ } else {
+ supported_variant = false;
+ }
+ }
+#endif // VK_KHR_video_queue
+
memcpy(block.blockName, variant_desc.blockName, VP_MAX_PROFILE_NAME_SIZE * sizeof(char));
if (supported_variant) {
supported_blocks.push_back(block);
@@ -10945,16 +12202,39 @@
return VK_SUCCESS;
}
-VPAPI_ATTR VkResult vpGetPhysicalDeviceProfileSupport(VkInstance instance, VkPhysicalDevice physicalDevice,
- const VpProfileProperties *pProfile, VkBool32 *pSupported) {
+VPAPI_ATTR VkResult vpGetPhysicalDeviceProfileSupport(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ VkInstance instance,
+ VkPhysicalDevice physicalDevice,
+ const VpProfileProperties* pProfile,
+ VkBool32 *pSupported) {
uint32_t count = 0;
- return vpGetPhysicalDeviceProfileVariantsSupport(instance, physicalDevice, pProfile, pSupported, &count, nullptr);
+
+ return vpGetPhysicalDeviceProfileVariantsSupport(
+#ifdef VP_USE_OBJECT
+ capabilities,
+#endif//VP_USE_OBJECT
+ instance, physicalDevice, pProfile, pSupported, &count, nullptr);
}
-VPAPI_ATTR VkResult vpCreateDevice(VkPhysicalDevice physicalDevice, const VpDeviceCreateInfo *pCreateInfo,
- const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
+VPAPI_ATTR VkResult vpCreateDevice(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ VkPhysicalDevice physicalDevice,
+ const VpDeviceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDevice* pDevice) {
+#ifdef VP_USE_OBJECT
+ const VpCapabilities_T& vp = capabilities == nullptr ? VpCapabilities_T::Get() : *capabilities;
+#else
+ const VpCapabilities_T& vp = VpCapabilities_T::Get();
+#endif//VP_USE_OBJECT
+
if (physicalDevice == VK_NULL_HANDLE || pCreateInfo == nullptr || pDevice == nullptr) {
- return vkCreateDevice(physicalDevice, pCreateInfo == nullptr ? nullptr : pCreateInfo->pCreateInfo, pAllocator, pDevice);
+ return vp.CreateDevice(physicalDevice, pCreateInfo == nullptr ? nullptr : pCreateInfo->pCreateInfo, pAllocator, pDevice);
}
const std::vector<VpBlockProperties>& blocks = detail::GatherBlocks(
@@ -10965,28 +12245,28 @@
std::vector<VkStructureType> structureTypes;
std::vector<const char*> extensions;
- for (std::uint32_t i = 0, n = pCreateInfo->pCreateInfo->enabledExtensionCount; i < n; ++i) {
- extensions.push_back(pCreateInfo->pCreateInfo->ppEnabledExtensionNames[i]);
+ for (std::uint32_t ext_index = 0, ext_count = pCreateInfo->pCreateInfo->enabledExtensionCount; ext_index < ext_count; ++ext_index) {
+ extensions.push_back(pCreateInfo->pCreateInfo->ppEnabledExtensionNames[ext_index]);
}
- for (std::size_t i = 0, n = blocks.size(); i < n; ++i) {
- const detail::VpProfileDesc* pProfileDesc = detail::vpGetProfileDesc(blocks[i].profiles.profileName);
+ for (std::size_t block_index = 0, block_count = blocks.size(); block_index < block_count; ++block_index) {
+ const detail::VpProfileDesc* pProfileDesc = detail::vpGetProfileDesc(blocks[block_index].profiles.profileName);
if (pProfileDesc == nullptr) return VK_ERROR_UNKNOWN;
- for (std::size_t j = 0, p = pProfileDesc->requiredCapabilityCount; j < p; ++j) {
- const detail::VpCapabilitiesDesc* pCapsDesc = &pProfileDesc->pRequiredCapabilities[j];
+ for (std::size_t caps_index = 0, caps_count = pProfileDesc->requiredCapabilityCount; caps_index < caps_count; ++caps_index) {
+ const detail::VpCapabilitiesDesc* pCapsDesc = &pProfileDesc->pRequiredCapabilities[caps_index];
- for (std::size_t v = 0, q = pCapsDesc->variantCount; v < q; ++v) {
- const detail::VpVariantDesc* variant = &pCapsDesc->pVariants[v];
+ for (std::size_t variant_index = 0, variant_count = pCapsDesc->variantCount; variant_index < variant_count; ++variant_index) {
+ const detail::VpVariantDesc* variant = &pCapsDesc->pVariants[variant_index];
- if (strcmp(blocks[i].blockName, "") != 0) {
- if (strcmp(variant->blockName, blocks[i].blockName) != 0) {
+ if (strcmp(blocks[block_index].blockName, "") != 0) {
+ if (strcmp(variant->blockName, blocks[block_index].blockName) != 0) {
continue;
}
}
- for (uint32_t t = 0; t < variant->featureStructTypeCount; ++t) {
- const VkStructureType type = variant->pFeatureStructTypes[t];
+ for (uint32_t type_index = 0; type_index < variant->featureStructTypeCount; ++type_index) {
+ const VkStructureType type = variant->pFeatureStructTypes[type_index];
if (std::find(structureTypes.begin(), structureTypes.end(), type) == std::end(structureTypes)) {
structureTypes.push_back(type);
}
@@ -11007,21 +12287,23 @@
pFeatures->features = *pCreateInfo->pCreateInfo->pEnabledFeatures;
}
- for (std::size_t i = 0, n = blocks.size(); i < n; ++i) {
- const detail::VpProfileDesc* pProfileDesc = detail::vpGetProfileDesc(blocks[i].profiles.profileName);
- if (pProfileDesc == nullptr) return VK_ERROR_UNKNOWN;
+ for (std::size_t block_index = 0, block_count = blocks.size(); block_index < block_count; ++block_index) {
+ const detail::VpProfileDesc* pProfileDesc = detail::vpGetProfileDesc(blocks[block_index].profiles.profileName);
+ if (pProfileDesc == nullptr) {
+ return VK_ERROR_UNKNOWN;
+ }
- for (std::size_t j = 0, p = pProfileDesc->requiredCapabilityCount; j < p; ++j) {
- const detail::VpCapabilitiesDesc* pCapsDesc = &pProfileDesc->pRequiredCapabilities[j];
+ for (std::size_t caps_index = 0, caps_count = pProfileDesc->requiredCapabilityCount; caps_index < caps_count; ++caps_index) {
+ const detail::VpCapabilitiesDesc* pCapsDesc = &pProfileDesc->pRequiredCapabilities[caps_index];
- for (std::size_t v = 0, q = pCapsDesc->variantCount; v < q; ++v) {
- const detail::VpVariantDesc* variant = &pCapsDesc->pVariants[v];
+ for (std::size_t variant_index = 0, variant_count = pCapsDesc->variantCount; variant_index < variant_count; ++variant_index) {
+ const detail::VpVariantDesc* variant = &pCapsDesc->pVariants[variant_index];
- VkBaseOutStructure* p = reinterpret_cast<VkBaseOutStructure*>(pFeatures);
+ VkBaseOutStructure* base_ptr = reinterpret_cast<VkBaseOutStructure*>(pFeatures);
if (variant->feature.pfnFiller != nullptr) {
- while (p != nullptr) {
- variant->feature.pfnFiller(p);
- p = p->pNext;
+ while (base_ptr != nullptr) {
+ variant->feature.pfnFiller(base_ptr);
+ base_ptr = base_ptr->pNext;
}
}
}
@@ -11041,31 +12323,63 @@
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
createInfo.ppEnabledExtensionNames = extensions.data();
- return vkCreateDevice(physicalDevice, &createInfo, pAllocator, pDevice);
+ return vp.CreateDevice(physicalDevice, &createInfo, pAllocator, pDevice);
}
-VPAPI_ATTR VkResult vpGetProfileInstanceExtensionProperties(const VpProfileProperties *pProfile, const char* pBlockName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties) {
- return detail::vpGetProfileExtensionProperties(pProfile, pBlockName, detail::EXTENSION_INSTANCE, pPropertyCount, pProperties);
+VPAPI_ATTR VkResult vpGetProfileInstanceExtensionProperties(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties) {
+ return detail::vpGetProfileExtensionProperties(
+#ifdef VP_USE_OBJECT
+ capabilities,
+#endif//VP_USE_OBJECT
+ pProfile, pBlockName, detail::EXTENSION_INSTANCE, pPropertyCount, pProperties);
}
-VPAPI_ATTR VkResult vpGetProfileDeviceExtensionProperties(const VpProfileProperties *pProfile, const char* pBlockName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties) {
- return detail::vpGetProfileExtensionProperties(pProfile, pBlockName, detail::EXTENSION_DEVICE, pPropertyCount, pProperties);
+VPAPI_ATTR VkResult vpGetProfileDeviceExtensionProperties(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties) {
+ return detail::vpGetProfileExtensionProperties(
+#ifdef VP_USE_OBJECT
+ capabilities,
+#endif//VP_USE_OBJECT
+ pProfile, pBlockName, detail::EXTENSION_DEVICE, pPropertyCount, pProperties);
}
-VPAPI_ATTR VkResult vpGetProfileFeatures(const VpProfileProperties *pProfile, const char* pBlockName, void *pNext) {
+VPAPI_ATTR VkResult vpGetProfileFeatures(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ void* pNext) {
+#ifdef VP_USE_OBJECT
+ (void)capabilities;
+#endif//VP_USE_OBJECT
+
VkResult result = pBlockName == nullptr ? VK_SUCCESS : VK_INCOMPLETE;
- const std::vector<VpProfileProperties>& profiles = detail::GatherProfiles(*pProfile);
+ const std::vector<VpProfileProperties>& gathered_profiles = detail::GatherProfiles(*pProfile);
- for (std::size_t profile_index = 0, profile_count = profiles.size(); profile_index < profile_count; ++profile_index) {
- const detail::VpProfileDesc* profile_desc = detail::vpGetProfileDesc(profiles[profile_index].profileName);
+ for (std::size_t profile_index = 0, profile_count = gathered_profiles.size(); profile_index < profile_count; ++profile_index) {
+ const detail::VpProfileDesc* profile_desc = detail::vpGetProfileDesc(gathered_profiles[profile_index].profileName);
if (profile_desc == nullptr) return VK_ERROR_UNKNOWN;
for (uint32_t capability_index = 0; capability_index < profile_desc->requiredCapabilityCount; ++capability_index) {
- const detail::VpCapabilitiesDesc& capabilities = profile_desc->pRequiredCapabilities[capability_index];
+ const detail::VpCapabilitiesDesc& cap_desc = profile_desc->pRequiredCapabilities[capability_index];
- for (uint32_t variant_index = 0; variant_index < capabilities.variantCount; ++variant_index) {
- const detail::VpVariantDesc& variant = capabilities.pVariants[variant_index];
+ for (uint32_t variant_index = 0; variant_index < cap_desc.variantCount; ++variant_index) {
+ const detail::VpVariantDesc& variant = cap_desc.pVariants[variant_index];
if (pBlockName != nullptr) {
if (strcmp(variant.blockName, pBlockName) != 0) {
continue;
@@ -11087,28 +12401,39 @@
return result;
}
-VPAPI_ATTR VkResult vpGetProfileProperties(const VpProfileProperties *pProfile, const char* pBlockName, void *pNext) {
+VPAPI_ATTR VkResult vpGetProfileProperties(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ void* pNext) {
VkResult result = pBlockName == nullptr ? VK_SUCCESS : VK_INCOMPLETE;
VkBool32 multiple_variants = VK_FALSE;
- if (vpHasMultipleVariantsProfile(pProfile, &multiple_variants) == VK_ERROR_UNKNOWN) {
+ if (vpHasMultipleVariantsProfile(
+#ifdef VP_USE_OBJECT
+ capabilities,
+#endif//VP_USE_OBJECT
+ pProfile,
+ &multiple_variants) == VK_ERROR_UNKNOWN) {
return VK_ERROR_UNKNOWN;
}
if (multiple_variants == VK_TRUE && pBlockName == nullptr) {
return VK_ERROR_UNKNOWN;
}
- const std::vector<VpProfileProperties>& profiles = detail::GatherProfiles(*pProfile);
+ const std::vector<VpProfileProperties>& gathered_profiles = detail::GatherProfiles(*pProfile);
- for (std::size_t profile_index = 0, profile_count = profiles.size(); profile_index < profile_count; ++profile_index) {
- const detail::VpProfileDesc* profile_desc = detail::vpGetProfileDesc(profiles[profile_index].profileName);
+ for (std::size_t profile_index = 0, profile_count = gathered_profiles.size(); profile_index < profile_count; ++profile_index) {
+ const detail::VpProfileDesc* profile_desc = detail::vpGetProfileDesc(gathered_profiles[profile_index].profileName);
if (profile_desc == nullptr) return VK_ERROR_UNKNOWN;
for (uint32_t capability_index = 0; capability_index < profile_desc->requiredCapabilityCount; ++capability_index) {
- const detail::VpCapabilitiesDesc& capabilities = profile_desc->pRequiredCapabilities[capability_index];
+ const detail::VpCapabilitiesDesc& cap_desc = profile_desc->pRequiredCapabilities[capability_index];
- for (uint32_t variant_index = 0; variant_index < capabilities.variantCount; ++variant_index) {
- const detail::VpVariantDesc& variant = capabilities.pVariants[variant_index];
+ for (uint32_t variant_index = 0; variant_index < cap_desc.variantCount; ++variant_index) {
+ const detail::VpVariantDesc& variant = cap_desc.pVariants[variant_index];
if (pBlockName != nullptr) {
if (strcmp(variant.blockName, pBlockName) != 0) {
continue;
@@ -11117,7 +12442,7 @@
}
if (variant.property.pfnFiller == nullptr) continue;
-
+
VkBaseOutStructure* p = static_cast<VkBaseOutStructure*>(pNext);
while (p != nullptr) {
variant.property.pfnFiller(p);
@@ -11130,22 +12455,35 @@
return result;
}
-VPAPI_ATTR VkResult vpGetProfileFormats(const VpProfileProperties *pProfile, const char* pBlockName, uint32_t *pFormatCount, VkFormat *pFormats) {
+VPAPI_ATTR VkResult vpGetProfileQueueFamilyProperties(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t* pPropertyCount,
+ VkQueueFamilyProperties2KHR* pProperties) {
+#ifdef VP_USE_OBJECT
+ (void)capabilities;
+#endif//VP_USE_OBJECT
+
+ if (pPropertyCount == nullptr) return VK_ERROR_UNKNOWN;
+
VkResult result = pBlockName == nullptr ? VK_SUCCESS : VK_INCOMPLETE;
- std::vector<VkFormat> results;
+ const std::vector<VpProfileProperties>& gathered_profiles = detail::GatherProfiles(*pProfile);
- const std::vector<VpProfileProperties>& profiles = detail::GatherProfiles(*pProfile);
+ uint32_t total_queue_family_count = 0;
- for (std::size_t profile_index = 0, profile_count = profiles.size(); profile_index < profile_count; ++profile_index) {
- const detail::VpProfileDesc* profile_desc = detail::vpGetProfileDesc(profiles[profile_index].profileName);
+ for (std::size_t profile_index = 0, profile_count = gathered_profiles.size(); profile_index < profile_count; ++profile_index) {
+ const detail::VpProfileDesc* profile_desc = detail::vpGetProfileDesc(gathered_profiles[profile_index].profileName);
if (profile_desc == nullptr) return VK_ERROR_UNKNOWN;
for (uint32_t capability_index = 0; capability_index < profile_desc->requiredCapabilityCount; ++capability_index) {
- const detail::VpCapabilitiesDesc& capabilities = profile_desc->pRequiredCapabilities[capability_index];
+ const detail::VpCapabilitiesDesc& cap_desc = profile_desc->pRequiredCapabilities[capability_index];
- for (uint32_t variant_index = 0; variant_index < capabilities.variantCount; ++variant_index) {
- const detail::VpVariantDesc& variant = capabilities.pVariants[variant_index];
+ for (uint32_t variant_index = 0; variant_index < cap_desc.variantCount; ++variant_index) {
+ const detail::VpVariantDesc& variant = cap_desc.pVariants[variant_index];
if (pBlockName != nullptr) {
if (strcmp(variant.blockName, pBlockName) != 0) {
continue;
@@ -11153,9 +12491,72 @@
result = VK_SUCCESS;
}
- for (uint32_t i = 0; i < variant.formatCount; ++i) {
- if (std::find(results.begin(), results.end(), variant.pFormats[i].format) == std::end(results)) {
- results.push_back(variant.pFormats[i].format);
+ if (pProperties != nullptr) {
+ for (uint32_t i = 0; i < variant.queueFamilyCount; ++i) {
+ if (total_queue_family_count < *pPropertyCount) {
+ if (variant.pQueueFamilies[i].pfnFiller == nullptr) continue;
+
+ VkBaseOutStructure* p = reinterpret_cast<VkBaseOutStructure*>(pProperties);
+ while (p != nullptr) {
+ variant.pQueueFamilies[i].pfnFiller(p);
+ p = p->pNext;
+ }
+
+ total_queue_family_count++;
+ pProperties++;
+ } else {
+ result = VK_INCOMPLETE;
+ break;
+ }
+ }
+ } else {
+ total_queue_family_count += variant.queueFamilyCount;
+ }
+ }
+ }
+ }
+
+ *pPropertyCount = total_queue_family_count;
+ return result;
+}
+
+VPAPI_ATTR VkResult vpGetProfileFormats(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t* pFormatCount,
+ VkFormat* pFormats) {
+#ifdef VP_USE_OBJECT
+ (void)capabilities;
+#endif//VP_USE_OBJECT
+
+ VkResult result = pBlockName == nullptr ? VK_SUCCESS : VK_INCOMPLETE;
+
+ std::vector<VkFormat> results;
+
+ const std::vector<VpProfileProperties>& gathered_profiles = detail::GatherProfiles(*pProfile);
+
+ for (std::size_t profile_index = 0, profile_count = gathered_profiles.size(); profile_index < profile_count; ++profile_index) {
+ const detail::VpProfileDesc* profile_desc = detail::vpGetProfileDesc(gathered_profiles[profile_index].profileName);
+ if (profile_desc == nullptr) return VK_ERROR_UNKNOWN;
+
+ for (uint32_t capability_index = 0; capability_index < profile_desc->requiredCapabilityCount; ++capability_index) {
+ const detail::VpCapabilitiesDesc& cap_desc = profile_desc->pRequiredCapabilities[capability_index];
+
+ for (uint32_t variant_index = 0; variant_index < cap_desc.variantCount; ++variant_index) {
+ const detail::VpVariantDesc& variant = cap_desc.pVariants[variant_index];
+ if (pBlockName != nullptr) {
+ if (strcmp(variant.blockName, pBlockName) != 0) {
+ continue;
+ }
+ result = VK_SUCCESS;
+ }
+
+ for (uint32_t format_index = 0; format_index < variant.formatCount; ++format_index) {
+ if (std::find(results.begin(), results.end(), variant.pFormats[format_index].format) == std::end(results)) {
+ results.push_back(variant.pFormats[format_index].format);
}
}
}
@@ -11180,13 +12581,24 @@
return result;
}
-VPAPI_ATTR VkResult vpGetProfileFormatProperties(const VpProfileProperties *pProfile, const char* pBlockName, VkFormat format, void *pNext) {
+VPAPI_ATTR VkResult vpGetProfileFormatProperties(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ VkFormat format,
+ void* pNext) {
+#ifdef VP_USE_OBJECT
+ (void)capabilities;
+#endif//VP_USE_OBJECT
+
VkResult result = pBlockName == nullptr ? VK_SUCCESS : VK_INCOMPLETE;
- const std::vector<VpProfileProperties>& profiles = detail::GatherProfiles(*pProfile);
+ const std::vector<VpProfileProperties>& gathered_profiles = detail::GatherProfiles(*pProfile);
- for (std::size_t i = 0, n = profiles.size(); i < n; ++i) {
- const char* profile_name = profiles[i].profileName;
+ for (std::size_t profile_index = 0, profile_count = gathered_profiles.size(); profile_index < profile_count; ++profile_index) {
+ const char* profile_name = gathered_profiles[profile_index].profileName;
const detail::VpProfileDesc* pProfileDesc = detail::vpGetProfileDesc(profile_name);
if (pProfileDesc == nullptr) return VK_ERROR_UNKNOWN;
@@ -11204,15 +12616,15 @@
result = VK_SUCCESS;
}
- for (uint32_t i = 0; i < variant.formatCount; ++i) {
- if (variant.pFormats[i].format != format) {
+ for (uint32_t format_index = 0; format_index < variant.formatCount; ++format_index) {
+ if (variant.pFormats[format_index].format != format) {
continue;
}
- VkBaseOutStructure* p = static_cast<VkBaseOutStructure*>(static_cast<void*>(pNext));
- while (p != nullptr) {
- variant.pFormats[i].pfnFiller(p);
- p = p->pNext;
+ VkBaseOutStructure* base_ptr = static_cast<VkBaseOutStructure*>(static_cast<void*>(pNext));
+ while (base_ptr != nullptr) {
+ variant.pFormats[format_index].pfnFiller(base_ptr);
+ base_ptr = base_ptr->pNext;
}
#if defined(VK_VERSION_1_3) || defined(VK_KHR_format_feature_flags2)
VkFormatProperties2KHR* fp2 = static_cast<VkFormatProperties2KHR*>(
@@ -11221,14 +12633,14 @@
detail::vpGetStructure(pNext, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR));
if (fp3 != nullptr) {
VkFormatProperties2KHR fp{ VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR };
- variant.pFormats[i].pfnFiller(static_cast<VkBaseOutStructure*>(static_cast<void*>(&fp)));
+ variant.pFormats[format_index].pfnFiller(static_cast<VkBaseOutStructure*>(static_cast<void*>(&fp)));
fp3->linearTilingFeatures |= static_cast<VkFormatFeatureFlags2KHR>(fp3->linearTilingFeatures | fp.formatProperties.linearTilingFeatures);
fp3->optimalTilingFeatures |= static_cast<VkFormatFeatureFlags2KHR>(fp3->optimalTilingFeatures | fp.formatProperties.optimalTilingFeatures);
fp3->bufferFeatures |= static_cast<VkFormatFeatureFlags2KHR>(fp3->bufferFeatures | fp.formatProperties.bufferFeatures);
}
if (fp2 != nullptr) {
VkFormatProperties3KHR fp{ VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR };
- variant.pFormats[i].pfnFiller(static_cast<VkBaseOutStructure*>(static_cast<void*>(&fp)));
+ variant.pFormats[format_index].pfnFiller(static_cast<VkBaseOutStructure*>(static_cast<void*>(&fp)));
fp2->formatProperties.linearTilingFeatures |= static_cast<VkFormatFeatureFlags>(fp2->formatProperties.linearTilingFeatures | fp.linearTilingFeatures);
fp2->formatProperties.optimalTilingFeatures |= static_cast<VkFormatFeatureFlags>(fp2->formatProperties.optimalTilingFeatures | fp.optimalTilingFeatures);
fp2->formatProperties.bufferFeatures |= static_cast<VkFormatFeatureFlags>(fp2->formatProperties.bufferFeatures | fp.bufferFeatures);
@@ -11242,16 +12654,316 @@
return result;
}
-VPAPI_ATTR VkResult vpGetProfileFeatureStructureTypes(const VpProfileProperties *pProfile, const char* pBlockName, uint32_t *pStructureTypeCount, VkStructureType *pStructureTypes) {
- return detail::vpGetProfileStructureTypes(pProfile, pBlockName, detail::STRUCTURE_FEATURE, pStructureTypeCount, pStructureTypes);
+VPAPI_ATTR VkResult vpGetProfileFeatureStructureTypes(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t* pStructureTypeCount,
+ VkStructureType* pStructureTypes) {
+ return detail::vpGetProfileStructureTypes(
+#ifdef VP_USE_OBJECT
+ capabilities,
+#endif//VP_USE_OBJECT
+ pProfile, pBlockName, detail::STRUCTURE_FEATURE, pStructureTypeCount, pStructureTypes);
}
-VPAPI_ATTR VkResult vpGetProfilePropertyStructureTypes(const VpProfileProperties *pProfile, const char* pBlockName, uint32_t *pStructureTypeCount, VkStructureType *pStructureTypes) {
- return detail::vpGetProfileStructureTypes(pProfile, pBlockName, detail::STRUCTURE_PROPERTY, pStructureTypeCount, pStructureTypes);
+VPAPI_ATTR VkResult vpGetProfilePropertyStructureTypes(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t* pStructureTypeCount,
+ VkStructureType* pStructureTypes) {
+ return detail::vpGetProfileStructureTypes(
+#ifdef VP_USE_OBJECT
+ capabilities,
+#endif//VP_USE_OBJECT
+ pProfile, pBlockName, detail::STRUCTURE_PROPERTY, pStructureTypeCount, pStructureTypes);
}
-VPAPI_ATTR VkResult vpGetProfileFormatStructureTypes(const VpProfileProperties *pProfile, const char* pBlockName, uint32_t *pStructureTypeCount, VkStructureType *pStructureTypes) {
- return detail::vpGetProfileStructureTypes(pProfile, pBlockName, detail::STRUCTURE_FORMAT, pStructureTypeCount, pStructureTypes);
+VPAPI_ATTR VkResult vpGetProfileQueueFamilyStructureTypes(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t* pStructureTypeCount,
+ VkStructureType* pStructureTypes) {
+ return detail::vpGetProfileStructureTypes(
+#ifdef VP_USE_OBJECT
+ capabilities,
+#endif//VP_USE_OBJECT
+ pProfile, pBlockName, detail::STRUCTURE_QUEUE_FAMILY, pStructureTypeCount, pStructureTypes);
}
-// clang-format on
+VPAPI_ATTR VkResult vpGetProfileFormatStructureTypes(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t* pStructureTypeCount,
+ VkStructureType* pStructureTypes) {
+ return detail::vpGetProfileStructureTypes(
+#ifdef VP_USE_OBJECT
+ capabilities,
+#endif//VP_USE_OBJECT
+ pProfile, pBlockName, detail::STRUCTURE_FORMAT, pStructureTypeCount, pStructureTypes);
+}
+
+#ifdef VK_KHR_video_queue
+// Query the list of video profiles specified by the profile
+VPAPI_ATTR VkResult vpGetProfileVideoProfiles(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t* pVideoProfileCount,
+ VpVideoProfileProperties* pVideoProfiles) {
+#ifdef VP_USE_OBJECT
+ (void)capabilities;
+#endif//VP_USE_OBJECT
+ if (pVideoProfileCount == nullptr) return VK_ERROR_UNKNOWN;
+
+ VkResult result = pBlockName == nullptr ? VK_SUCCESS : VK_INCOMPLETE;
+
+ uint32_t total_video_profile_count = 0;
+
+ const std::vector<VpProfileProperties>& gathered_profiles = detail::GatherProfiles(*pProfile);
+
+ for (std::size_t profile_index = 0, profile_count = gathered_profiles.size(); profile_index < profile_count; ++profile_index) {
+ const detail::VpProfileDesc* profile_desc = detail::vpGetProfileDesc(gathered_profiles[profile_index].profileName);
+ if (profile_desc == nullptr) return VK_ERROR_UNKNOWN;
+
+ for (uint32_t capability_index = 0; capability_index < profile_desc->requiredCapabilityCount; ++capability_index) {
+ const detail::VpCapabilitiesDesc& cap_desc = profile_desc->pRequiredCapabilities[capability_index];
+
+ for (uint32_t variant_index = 0; variant_index < cap_desc.variantCount; ++variant_index) {
+ const detail::VpVariantDesc& variant = cap_desc.pVariants[variant_index];
+ if (pBlockName != nullptr) {
+ if (strcmp(variant.blockName, pBlockName) != 0) {
+ continue;
+ }
+ result = VK_SUCCESS;
+ }
+
+ if (pVideoProfiles != nullptr) {
+ for (uint32_t i = 0; i < variant.videoProfileCount; ++i) {
+ if (total_video_profile_count < *pVideoProfileCount) {
+ *pVideoProfiles = variant.pVideoProfiles[i].properties;
+ total_video_profile_count++;
+ pVideoProfiles++;
+ } else {
+ result = VK_INCOMPLETE;
+ break;
+ }
+ }
+ } else {
+ total_video_profile_count += variant.videoProfileCount;
+ }
+ }
+ }
+ }
+
+ *pVideoProfileCount = total_video_profile_count;
+ return result;
+}
+
+VPAPI_ATTR VkResult vpGetProfileVideoProfileInfo(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t videoProfileIndex,
+ VkVideoProfileInfoKHR* pVideoProfileInfo) {
+#ifdef VP_USE_OBJECT
+ (void)capabilities;
+#endif//VP_USE_OBJECT
+
+ const detail::VpVideoProfileDesc* pVideoProfileDesc = nullptr;
+ VkResult result = detail::vpGetProfileVideoProfileDesc(pProfile, pBlockName, videoProfileIndex, &pVideoProfileDesc);
+
+ if (pVideoProfileDesc != nullptr) {
+ VkBaseOutStructure* p = reinterpret_cast<VkBaseOutStructure*>(pVideoProfileInfo);
+ while (p != nullptr) {
+ pVideoProfileDesc->info.pfnFiller(p);
+ p = p->pNext;
+ }
+ }
+
+ return result;
+}
+
+VPAPI_ATTR VkResult vpGetProfileVideoCapabilities(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t videoProfileIndex,
+ void* pNext) {
+#ifdef VP_USE_OBJECT
+ (void)capabilities;
+#endif//VP_USE_OBJECT
+
+ const detail::VpVideoProfileDesc* pVideoProfileDesc = nullptr;
+ VkResult result = detail::vpGetProfileVideoProfileDesc(pProfile, pBlockName, videoProfileIndex, &pVideoProfileDesc);
+
+ if (pVideoProfileDesc != nullptr) {
+ VkBaseOutStructure* p = reinterpret_cast<VkBaseOutStructure*>(pNext);
+ while (p != nullptr) {
+ pVideoProfileDesc->capability.pfnFiller(p);
+ p = p->pNext;
+ }
+ }
+
+ return result;
+}
+
+VPAPI_ATTR VkResult vpGetProfileVideoFormatProperties(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t videoProfileIndex,
+ uint32_t* pPropertyCount,
+ VkVideoFormatPropertiesKHR* pProperties) {
+#ifdef VP_USE_OBJECT
+ (void)capabilities;
+#endif//VP_USE_OBJECT
+
+ const detail::VpVideoProfileDesc* pVideoProfileDesc = nullptr;
+ VkResult result = detail::vpGetProfileVideoProfileDesc(pProfile, pBlockName, videoProfileIndex, &pVideoProfileDesc);
+
+ uint32_t property_count = 0;
+ if (pVideoProfileDesc != nullptr) {
+ if (pProperties != nullptr) {
+ for (; property_count < pVideoProfileDesc->formatCount; ++property_count) {
+ if (property_count < *pPropertyCount) {
+ VkBaseOutStructure* p = reinterpret_cast<VkBaseOutStructure*>(&pProperties[property_count]);
+ while (p != nullptr) {
+ pVideoProfileDesc->pFormats[property_count].pfnFiller(p);
+ p = p->pNext;
+ }
+ } else {
+ result = VK_INCOMPLETE;
+ break;
+ }
+ }
+ } else {
+ property_count = pVideoProfileDesc->formatCount;
+ }
+ }
+
+ *pPropertyCount = property_count;
+ return result;
+}
+
+VPAPI_ATTR VkResult vpGetProfileVideoProfileInfoStructureTypes(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t videoProfileIndex,
+ uint32_t* pStructureTypeCount,
+ VkStructureType* pStructureTypes) {
+#ifdef VP_USE_OBJECT
+ (void)capabilities;
+#endif//VP_USE_OBJECT
+
+ const detail::VpVideoProfileDesc* pVideoProfileDesc = nullptr;
+ VkResult result = detail::vpGetProfileVideoProfileDesc(pProfile, pBlockName, videoProfileIndex, &pVideoProfileDesc);
+
+ if (pVideoProfileDesc != nullptr) {
+ if (pStructureTypes != nullptr) {
+ if (*pStructureTypeCount < pVideoProfileDesc->infoStructTypeCount) {
+ result = VK_INCOMPLETE;
+ } else {
+ *pStructureTypeCount = pVideoProfileDesc->infoStructTypeCount;
+ }
+ if (*pStructureTypeCount > 0) {
+ memcpy(pStructureTypes, pVideoProfileDesc->pInfoStructTypes, *pStructureTypeCount * sizeof(VkStructureType));
+ }
+ } else {
+ *pStructureTypeCount = pVideoProfileDesc->infoStructTypeCount;
+ }
+ }
+
+ return result;
+}
+
+VPAPI_ATTR VkResult vpGetProfileVideoCapabilityStructureTypes(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t videoProfileIndex,
+ uint32_t* pStructureTypeCount,
+ VkStructureType* pStructureTypes) {
+#ifdef VP_USE_OBJECT
+ (void)capabilities;
+#endif//VP_USE_OBJECT
+
+ const detail::VpVideoProfileDesc* pVideoProfileDesc = nullptr;
+ VkResult result = detail::vpGetProfileVideoProfileDesc(pProfile, pBlockName, videoProfileIndex, &pVideoProfileDesc);
+
+ if (pVideoProfileDesc != nullptr) {
+ if (pStructureTypes != nullptr) {
+ if (*pStructureTypeCount < pVideoProfileDesc->capabilityStructTypeCount) {
+ result = VK_INCOMPLETE;
+ } else {
+ *pStructureTypeCount = pVideoProfileDesc->capabilityStructTypeCount;
+ }
+ if (*pStructureTypeCount > 0) {
+ memcpy(pStructureTypes, pVideoProfileDesc->pCapabilityStructTypes, *pStructureTypeCount * sizeof(VkStructureType));
+ }
+ } else {
+ *pStructureTypeCount = pVideoProfileDesc->capabilityStructTypeCount;
+ }
+ }
+
+ return result;
+}
+
+VPAPI_ATTR VkResult vpGetProfileVideoFormatStructureTypes(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t videoProfileIndex,
+ uint32_t* pStructureTypeCount,
+ VkStructureType* pStructureTypes) {
+#ifdef VP_USE_OBJECT
+ (void)capabilities;
+#endif//VP_USE_OBJECT
+
+ const detail::VpVideoProfileDesc* pVideoProfileDesc = nullptr;
+ VkResult result = detail::vpGetProfileVideoProfileDesc(pProfile, pBlockName, videoProfileIndex, &pVideoProfileDesc);
+
+ if (pVideoProfileDesc != nullptr) {
+ if (pStructureTypes != nullptr) {
+ if (*pStructureTypeCount < pVideoProfileDesc->formatStructTypeCount) {
+ result = VK_INCOMPLETE;
+ } else {
+ *pStructureTypeCount = pVideoProfileDesc->formatStructTypeCount;
+ }
+ if (*pStructureTypeCount > 0) {
+ memcpy(pStructureTypes, pVideoProfileDesc->pFormatStructTypes, *pStructureTypeCount * sizeof(VkStructureType));
+ }
+ } else {
+ *pStructureTypeCount = pVideoProfileDesc->formatStructTypeCount;
+ }
+ }
+
+ return result;
+}
+#endif // VK_KHR_video_queue
diff --git a/vulkan/vkprofiles/generated/vulkan_profiles.h b/vulkan/vkprofiles/generated/vulkan_profiles.h
index 4bfb6f6..c29e340 100644
--- a/vulkan/vkprofiles/generated/vulkan_profiles.h
+++ b/vulkan/vkprofiles/generated/vulkan_profiles.h
@@ -91,6 +91,32 @@
#define VP_ANDROID_15_MINIMUMS_MIN_API_VERSION VK_MAKE_VERSION(1, 3, 273)
#endif
+#if defined(VK_VERSION_1_3) && \
+ defined(VP_ANDROID_15_minimums) && \
+ defined(VP_ANDROID_baseline_2022) && \
+ defined(VK_EXT_host_image_copy) && \
+ defined(VK_EXT_image_2d_view_of_3d) && \
+ defined(VK_EXT_multisampled_render_to_single_sampled) && \
+ defined(VK_EXT_pipeline_protected_access) && \
+ defined(VK_EXT_pipeline_robustness) && \
+ defined(VK_EXT_shader_stencil_export) && \
+ defined(VK_EXT_transform_feedback) && \
+ defined(VK_KHR_8bit_storage) && \
+ defined(VK_KHR_load_store_op_none) && \
+ defined(VK_KHR_maintenance6) && \
+ defined(VK_KHR_map_memory2) && \
+ defined(VK_KHR_shader_expect_assume) && \
+ defined(VK_KHR_shader_float_controls2) && \
+ defined(VK_KHR_shader_maximal_reconvergence) && \
+ defined(VK_KHR_shader_subgroup_rotate) && \
+ defined(VK_KHR_shader_subgroup_uniform_control_flow) && \
+ defined(VK_KHR_swapchain_mutable_format)
+#define VP_ANDROID_16_minimums 1
+#define VP_ANDROID_16_MINIMUMS_NAME "VP_ANDROID_16_minimums"
+#define VP_ANDROID_16_MINIMUMS_SPEC_VERSION 1
+#define VP_ANDROID_16_MINIMUMS_MIN_API_VERSION VK_MAKE_VERSION(1, 3, 276)
+#endif
+
#if defined(VK_VERSION_1_0) && \
defined(VK_EXT_swapchain_colorspace) && \
defined(VK_GOOGLE_display_timing) && \
@@ -161,6 +187,10 @@
char blockName[VP_MAX_PROFILE_NAME_SIZE];
} VpBlockProperties;
+typedef struct VpVideoProfileProperties {
+ char name[VP_MAX_PROFILE_NAME_SIZE];
+} VpVideoProfileProperties;
+
typedef enum VpInstanceCreateFlagBits {
VP_INSTANCE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VpInstanceCreateFlagBits;
@@ -194,70 +224,342 @@
const VpBlockProperties* pEnabledProfileBlocks;
} VpDeviceCreateInfo;
+VK_DEFINE_HANDLE(VpCapabilities)
+
+typedef enum VpCapabilitiesCreateFlagBits {
+ VP_PROFILE_CREATE_STATIC_BIT = (1 << 0),
+ //VP_PROFILE_CREATE_DYNAMIC_BIT = (1 << 1),
+ VP_PROFILE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VpCapabilitiesCreateFlagBits;
+
+typedef VkFlags VpCapabilitiesCreateFlags;
+
+// Pointers to some Vulkan functions - a subset used by the library.
+// Used in VpCapabilitiesCreateInfo::pVulkanFunctions.
+
+typedef struct VpVulkanFunctions {
+ /// Required when using VP_DYNAMIC_VULKAN_FUNCTIONS.
+ PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
+ /// Required when using VP_DYNAMIC_VULKAN_FUNCTIONS.
+ PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
+ PFN_vkEnumerateInstanceVersion EnumerateInstanceVersion;
+ PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
+ PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
+ PFN_vkGetPhysicalDeviceFeatures2 GetPhysicalDeviceFeatures2;
+ PFN_vkGetPhysicalDeviceProperties2 GetPhysicalDeviceProperties2;
+ PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysicalDeviceFormatProperties2;
+ PFN_vkGetPhysicalDeviceQueueFamilyProperties2 GetPhysicalDeviceQueueFamilyProperties2;
+ PFN_vkCreateInstance CreateInstance;
+ PFN_vkCreateDevice CreateDevice;
+} VpVulkanFunctions;
+
+/// Description of a Allocator to be created.
+typedef struct VpCapabilitiesCreateInfo
+{
+ /// Flags for created allocator. Use #VpInstanceCreateFlagBits enum.
+ VpCapabilitiesCreateFlags flags;
+ uint32_t apiVersion;
+ const VpVulkanFunctions* pVulkanFunctions;
+} VpCapabilitiesCreateInfo;
+
+VPAPI_ATTR VkResult vpCreateCapabilities(
+ const VpCapabilitiesCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VpCapabilities* pCapabilities);
+
+/// Destroys allocator object.
+VPAPI_ATTR void vpDestroyCapabilities(
+ VpCapabilities capabilities,
+ const VkAllocationCallbacks* pAllocator);
+
// Query the list of available profiles in the library
-VPAPI_ATTR VkResult vpGetProfiles(uint32_t *pPropertyCount, VpProfileProperties *pProperties);
+VPAPI_ATTR VkResult vpGetProfiles(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ uint32_t* pPropertyCount,
+ VpProfileProperties* pProperties);
// List the required profiles of a profile
-VPAPI_ATTR VkResult vpGetProfileRequiredProfiles(const VpProfileProperties* pProfile, uint32_t* pPropertyCount, VpProfileProperties* pProperties);
+VPAPI_ATTR VkResult vpGetProfileRequiredProfiles(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ uint32_t* pPropertyCount,
+ VpProfileProperties* pProperties);
// Query the profile required Vulkan API version
-VPAPI_ATTR uint32_t vpGetProfileAPIVersion(const VpProfileProperties* pProfile);
+VPAPI_ATTR uint32_t vpGetProfileAPIVersion(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile);
// List the recommended fallback profiles of a profile
-VPAPI_ATTR VkResult vpGetProfileFallbacks(const VpProfileProperties *pProfile, uint32_t *pPropertyCount, VpProfileProperties *pProperties);
+VPAPI_ATTR VkResult vpGetProfileFallbacks(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ uint32_t* pPropertyCount,
+ VpProfileProperties* pProperties);
// Query whether the profile has multiple variants. Profiles with multiple variants can only use vpGetInstanceProfileSupport and vpGetPhysicalDeviceProfileSupport capabilities of the library. Other function will return a VK_ERROR_UNKNOWN error
-VPAPI_ATTR VkResult vpHasMultipleVariantsProfile(const VpProfileProperties *pProfile, VkBool32 *pHasMultipleVariants);
+VPAPI_ATTR VkResult vpHasMultipleVariantsProfile(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ VkBool32* pHasMultipleVariants);
// Check whether a profile is supported at the instance level
-VPAPI_ATTR VkResult vpGetInstanceProfileSupport(const char *pLayerName, const VpProfileProperties *pProfile, VkBool32 *pSupported);
+VPAPI_ATTR VkResult vpGetInstanceProfileSupport(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const char* pLayerName,
+ const VpProfileProperties* pProfile,
+ VkBool32* pSupported);
// Check whether a variant of a profile is supported at the instance level and report this list of blocks used to validate the profiles
-VPAPI_ATTR VkResult vpGetInstanceProfileVariantsSupport(const char *pLayerName, const VpProfileProperties *pProfile, VkBool32 *pSupported, uint32_t *pPropertyCount, VpBlockProperties* pProperties);
+VPAPI_ATTR VkResult vpGetInstanceProfileVariantsSupport(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const char* pLayerName,
+ const VpProfileProperties* pProfile,
+ VkBool32* pSupported,
+ uint32_t* pPropertyCount,
+ VpBlockProperties* pProperties);
// Create a VkInstance with the profile instance extensions enabled
-VPAPI_ATTR VkResult vpCreateInstance(const VpInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance);
+VPAPI_ATTR VkResult vpCreateInstance(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpInstanceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkInstance* pInstance);
// Check whether a profile is supported by the physical device
-VPAPI_ATTR VkResult vpGetPhysicalDeviceProfileSupport(VkInstance instance, VkPhysicalDevice physicalDevice, const VpProfileProperties *pProfile, VkBool32 *pSupported);
+VPAPI_ATTR VkResult vpGetPhysicalDeviceProfileSupport(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ VkInstance instance,
+ VkPhysicalDevice physicalDevice,
+ const VpProfileProperties* pProfile,
+ VkBool32* pSupported);
// Check whether a variant of a profile is supported by the physical device and report this list of blocks used to validate the profiles
-VPAPI_ATTR VkResult vpGetPhysicalDeviceProfileVariantsSupport(VkInstance instance, VkPhysicalDevice physicalDevice, const VpProfileProperties *pProfile, VkBool32 *pSupported, uint32_t *pPropertyCount, VpBlockProperties* pProperties);
+VPAPI_ATTR VkResult vpGetPhysicalDeviceProfileVariantsSupport(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ VkInstance instance,
+ VkPhysicalDevice physicalDevice,
+ const VpProfileProperties* pProfile,
+ VkBool32* pSupported,
+ uint32_t* pPropertyCount,
+ VpBlockProperties* pProperties);
// Create a VkDevice with the profile features and device extensions enabled
-VPAPI_ATTR VkResult vpCreateDevice(VkPhysicalDevice physicalDevice, const VpDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice);
+VPAPI_ATTR VkResult vpCreateDevice(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ VkPhysicalDevice physicalDevice,
+ const VpDeviceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDevice* pDevice);
// Query the list of instance extensions of a profile
-VPAPI_ATTR VkResult vpGetProfileInstanceExtensionProperties(const VpProfileProperties *pProfile, const char* pBlockName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties);
+VPAPI_ATTR VkResult vpGetProfileInstanceExtensionProperties(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties);
// Query the list of device extensions of a profile
-VPAPI_ATTR VkResult vpGetProfileDeviceExtensionProperties(const VpProfileProperties *pProfile, const char* pBlockName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties);
+VPAPI_ATTR VkResult vpGetProfileDeviceExtensionProperties(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties);
// Fill the feature structures with the requirements of a profile
-VPAPI_ATTR VkResult vpGetProfileFeatures(const VpProfileProperties *pProfile, const char* pBlockName, void *pNext);
+VPAPI_ATTR VkResult vpGetProfileFeatures(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ void* pNext);
// Query the list of feature structure types specified by the profile
-VPAPI_ATTR VkResult vpGetProfileFeatureStructureTypes(const VpProfileProperties *pProfile, const char* pBlockName, uint32_t *pStructureTypeCount, VkStructureType *pStructureTypes);
+VPAPI_ATTR VkResult vpGetProfileFeatureStructureTypes(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t* pStructureTypeCount,
+ VkStructureType* pStructureTypes);
// Fill the property structures with the requirements of a profile
-VPAPI_ATTR VkResult vpGetProfileProperties(const VpProfileProperties *pProfile, const char* pBlockName, void *pNext);
+VPAPI_ATTR VkResult vpGetProfileProperties(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ void* pNext);
// Query the list of property structure types specified by the profile
-VPAPI_ATTR VkResult vpGetProfilePropertyStructureTypes(const VpProfileProperties *pProfile, const char* pBlockName, uint32_t *pStructureTypeCount, VkStructureType *pStructureTypes);
+VPAPI_ATTR VkResult vpGetProfilePropertyStructureTypes(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t* pStructureTypeCount,
+ VkStructureType* pStructureTypes);
+
+// Fill the queue family property structures with the requirements of a profile
+VPAPI_ATTR VkResult vpGetProfileQueueFamilyProperties(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t* pPropertyCount,
+ VkQueueFamilyProperties2KHR* pProperties);
+
+// Query the list of queue family property structure types specified by the profile
+VPAPI_ATTR VkResult vpGetProfileQueueFamilyStructureTypes(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t* pStructureTypeCount,
+ VkStructureType* pStructureTypes);
// Query the list of formats with specified requirements by a profile
-VPAPI_ATTR VkResult vpGetProfileFormats(const VpProfileProperties *pProfile, const char* pBlockName, uint32_t *pFormatCount, VkFormat *pFormats);
+VPAPI_ATTR VkResult vpGetProfileFormats(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t* pFormatCount,
+ VkFormat* pFormats);
// Query the requirements of a format for a profile
-VPAPI_ATTR VkResult vpGetProfileFormatProperties(const VpProfileProperties *pProfile, const char* pBlockName, VkFormat format, void *pNext);
+VPAPI_ATTR VkResult vpGetProfileFormatProperties(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ VkFormat format,
+ void* pNext);
// Query the list of format structure types specified by the profile
-VPAPI_ATTR VkResult vpGetProfileFormatStructureTypes(const VpProfileProperties *pProfile, const char* pBlockName, uint32_t *pStructureTypeCount, VkStructureType *pStructureTypes);
+VPAPI_ATTR VkResult vpGetProfileFormatStructureTypes(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t* pStructureTypeCount,
+ VkStructureType* pStructureTypes);
+
+#ifdef VK_KHR_video_queue
+// Query the list of video profiles specified by the profile
+VPAPI_ATTR VkResult vpGetProfileVideoProfiles(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t* pVideoProfileCount,
+ VpVideoProfileProperties* pVideoProfiles);
+
+// Query the video profile info structures for a video profile defined by a profile
+VPAPI_ATTR VkResult vpGetProfileVideoProfileInfo(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t videoProfileIndex,
+ VkVideoProfileInfoKHR* pVideoProfileInfo);
+
+// Query the list of video profile info structure types specified by the profile for a video profile
+VPAPI_ATTR VkResult vpGetProfileVideoProfileInfoStructureTypes(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t videoProfileIndex,
+ uint32_t* pStructureTypeCount,
+ VkStructureType* pStructureTypes);
+
+// Query the video capabilities requirements for a video profile defined by a profile
+VPAPI_ATTR VkResult vpGetProfileVideoCapabilities(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t videoProfileIndex,
+ void* pNext);
+
+// Query the list of video capability structure types specified by the profile for a video profile
+VPAPI_ATTR VkResult vpGetProfileVideoCapabilityStructureTypes(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t videoProfileIndex,
+ uint32_t* pStructureTypeCount,
+ VkStructureType* pStructureTypes);
+
+// Query the video format property requirements for a video profile defined by a profile
+VPAPI_ATTR VkResult vpGetProfileVideoFormatProperties(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t videoProfileIndex,
+ uint32_t* pPropertyCount,
+ VkVideoFormatPropertiesKHR* pProperties);
+
+// Query the list of video format property structure types specified by the profile for a video profile
+VPAPI_ATTR VkResult vpGetProfileVideoFormatStructureTypes(
+#ifdef VP_USE_OBJECT
+ VpCapabilities capabilities,
+#endif//VP_USE_OBJECT
+ const VpProfileProperties* pProfile,
+ const char* pBlockName,
+ uint32_t videoProfileIndex,
+ uint32_t* pStructureTypeCount,
+ VkStructureType* pStructureTypes);
+#endif // VK_KHR_video_queue
#ifdef __cplusplus
}
#endif
#endif // VULKAN_PROFILES_H_
-
-// clang-format on
diff --git a/vulkan/vkprofiles/profiles/VP_ANDROID_16_minimums.json b/vulkan/vkprofiles/profiles/VP_ANDROID_16_minimums.json
new file mode 100644
index 0000000..c49e68a
--- /dev/null
+++ b/vulkan/vkprofiles/profiles/VP_ANDROID_16_minimums.json
@@ -0,0 +1,154 @@
+{
+ "$schema": "https://schema.khronos.org/vulkan/profiles-0.8.2-301.json#",
+ "capabilities": {
+ "MUST": {
+ "extensions": {
+ "VK_KHR_8bit_storage": 1,
+ "VK_KHR_load_store_op_none": 1,
+ "VK_KHR_maintenance6": 1,
+ "VK_KHR_map_memory2": 1,
+ "VK_KHR_shader_expect_assume": 1,
+ "VK_KHR_shader_float_controls2": 1,
+ "VK_KHR_shader_maximal_reconvergence": 1,
+ "VK_KHR_shader_subgroup_rotate": 1,
+ "VK_KHR_shader_subgroup_uniform_control_flow": 1,
+ "VK_KHR_swapchain_mutable_format": 1,
+ "VK_EXT_host_image_copy": 1,
+ "VK_EXT_image_2d_view_of_3d": 1,
+ "VK_EXT_pipeline_protected_access": 1,
+ "VK_EXT_pipeline_robustness": 1,
+ "VK_EXT_transform_feedback": 1
+ },
+ "features": {
+ "VkPhysicalDeviceFeatures": {
+ "fullDrawIndexUint32": true,
+ "shaderInt16": true
+ },
+ "VkPhysicalDeviceVulkan12Features": {
+ "samplerMirrorClampToEdge": true,
+ "scalarBlockLayout": true
+ },
+ "VkPhysicalDeviceProtectedMemoryFeatures": {
+ "protectedMemory": true
+ },
+ "VkPhysicalDeviceShaderIntegerDotProductFeatures": {
+ "shaderIntegerDotProduct": true
+ },
+ "VkPhysicalDeviceTransformFeedbackFeaturesEXT": {
+ "transformFeedback": true
+ },
+ "VkPhysicalDeviceImage2DViewOf3DFeaturesEXT": {
+ "image2DViewOf3D": true
+ },
+ "VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR": {
+ "shaderSubgroupUniformControlFlow": true
+ }
+ },
+ "properties": {
+ "VkPhysicalDeviceProperties": {
+ "limits": {
+ "bufferImageGranularity": 4096,
+ "lineWidthGranularity": 0.5,
+ "maxColorAttachments": 8,
+ "maxComputeWorkGroupInvocations": 256,
+ "maxComputeWorkGroupSize": [ 256, 256, 64 ],
+ "maxImageArrayLayers": 2048,
+ "maxImageDimension1D": 8192,
+ "maxImageDimension2D": 8192,
+ "maxImageDimensionCube": 8192,
+ "maxDescriptorSetStorageBuffers": 96,
+ "maxDescriptorSetUniformBuffers": 90,
+ "maxFragmentCombinedOutputResources": 16,
+ "maxPerStageDescriptorUniformBuffers": 15,
+ "maxPerStageResources": 200,
+ "maxSamplerLodBias": 14,
+ "maxUniformBufferRange": 65536,
+ "maxVertexOutputComponents": 72,
+ "mipmapPrecisionBits": 6,
+ "pointSizeGranularity": 0.125,
+ "standardSampleLocations": true,
+ "subTexelPrecisionBits": 8,
+ "timestampComputeAndGraphics": true
+ }
+ },
+ "VkPhysicalDeviceFloatControlsProperties": {
+ "shaderSignedZeroInfNanPreserveFloat16": true,
+ "shaderSignedZeroInfNanPreserveFloat32": true
+ },
+ "VkPhysicalDeviceVulkan11Properties": {
+ "subgroupSupportedStages": ["VK_SHADER_STAGE_COMPUTE_BIT"]
+ }
+ }
+ },
+ "multisampledToSingleSampled": {
+ "extensions": {
+ "VK_EXT_multisampled_render_to_single_sampled": 1
+ }
+ },
+ "shaderStencilExport": {
+ "extensions": {
+ "VK_EXT_shader_stencil_export": 1
+ }
+ }
+ },
+ "profiles": {
+ "VP_ANDROID_16_minimums": {
+ "version": 1,
+ "api-version": "1.3.276",
+ "label": "Vulkan Minimum Requirements for Android 16",
+ "description": "Collection of functionality that is mandated on Android 16",
+ "contributors": {
+ "Ian Elliott": {
+ "company": "Google",
+ "email": "ianelliott@google.com",
+ "contact": true
+ }
+ },
+ "history": [
+ {
+ "revision": 1,
+ "date": "2024-02-20",
+ "author": "Ian Elliott",
+ "comment": "First draft"
+ },
+ {
+ "revision": 2,
+ "date": "2024-07-22",
+ "author": "Ian Elliott",
+ "comment": "Added proposed Vulkan 1.4 scope"
+ },
+ {
+ "revision": 3,
+ "date": "2024-11-15",
+ "author": "Ian Elliott",
+ "comment": "Delay some requirements that Mali Bifrost chipsets cannot do"
+ },
+ {
+ "revision": 4,
+ "date": "2024-12-10",
+ "author": "Ian Elliott",
+ "comment": "Delay some requirements that Adreno A6xx chipsets cannot do"
+ },
+ {
+ "revision": 5,
+ "date": "2024-12-11",
+ "author": "Ian Elliott",
+ "comment": "Delay VK_EXT_device_fault"
+ },
+ {
+ "revision": 6,
+ "date": "2024-12-11",
+ "author": "Ian Elliott",
+ "comment": "Delay a requirement that IMG BXM-8-256 chipsets cannot do"
+ }
+ ],
+ "profiles": [
+ "VP_ANDROID_15_minimums"
+ ],
+ "capabilities": [
+ "MUST",
+ ["multisampledToSingleSampled", "shaderStencilExport"]
+ ]
+ }
+ }
+}
diff --git a/vulkan/vkprofiles/vkprofiles.cpp b/vulkan/vkprofiles/vkprofiles.cpp
index 465dc25..e5ad902 100644
--- a/vulkan/vkprofiles/vkprofiles.cpp
+++ b/vulkan/vkprofiles/vkprofiles.cpp
@@ -182,6 +182,13 @@
VP_ANDROID_15_MINIMUMS_MIN_API_VERSION);
}
+std::string vkVpa16GetSupport() {
+ VpProfileProperties profile{VP_ANDROID_16_MINIMUMS_NAME,
+ VP_ANDROID_16_MINIMUMS_SPEC_VERSION};
+ return vkProfileGetSupport(&profile,
+ VP_ANDROID_16_MINIMUMS_MIN_API_VERSION);
+}
+
std::string vkProfiles() {
return "{"
"\"" + std::string(VP_ANDROID_BASELINE_2021_NAME) + "\": "
@@ -191,7 +198,9 @@
"\"" + std::string(VP_ANDROID_BASELINE_2022_NAME) + "\": "
"\"" + vkAbp2022GetSupport() + "\","
"\"" + std::string(VP_ANDROID_15_MINIMUMS_NAME) + "\": "
- "\"" + vkVpa15GetSupport() + "\""
+ "\"" + vkVpa15GetSupport() + "\","
+ "\"" + std::string(VP_ANDROID_16_MINIMUMS_NAME) + "\": "
+ "\"" + vkVpa16GetSupport() + "\""
"}";
}
diff --git a/vulkan/vkprofiles/vkprofiles.h b/vulkan/vkprofiles/vkprofiles.h
index 8f42e9b..a411608 100644
--- a/vulkan/vkprofiles/vkprofiles.h
+++ b/vulkan/vkprofiles/vkprofiles.h
@@ -32,6 +32,7 @@
std::string vkAbp2021GetSupportCpuOnly();
std::string vkAbp2022GetSupport();
std::string vkVpa15GetSupport();
+std::string vkVpa16GetSupport();
// Returns a json string that enumerates support for any of the Vulkan profiles
// specified in the above functions