Merge "Set isRelativeOf flag when calling setZOrderRelativeOf"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 369c3de..657dfb6 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -253,7 +253,7 @@
MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
return 0L;
}
- MYLOGD("Module metadata package name: %s", package_name.c_str());
+ MYLOGD("Module metadata package name: %s\n", package_name.c_str());
int64_t version_code;
status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
&version_code);
@@ -876,6 +876,17 @@
CommandOptions::WithTimeoutInMs(timeout_ms).Build());
}
+static void DoSystemLogcat(time_t since) {
+ char since_str[80];
+ strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
+
+ unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
+ RunCommand("SYSTEM LOG",
+ {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
+ since_str},
+ CommandOptions::WithTimeoutInMs(timeout_ms).Build());
+}
+
static void DoLogcat() {
unsigned long timeout_ms;
// DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
@@ -1071,7 +1082,7 @@
std::string path(title);
path.append(" - ").append(String8(service).c_str());
size_t bytes_written = 0;
- status_t status = dumpsys.startDumpThread(service, args);
+ status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args);
if (status == OK) {
dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
std::chrono::duration<double> elapsed_seconds;
@@ -1143,7 +1154,7 @@
path.append("_HIGH");
}
path.append(kProtoExt);
- status_t status = dumpsys.startDumpThread(service, args);
+ status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args);
if (status == OK) {
status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
bool dumpTerminated = (status == OK);
@@ -1365,8 +1376,6 @@
ds.TakeScreenshot();
}
- DoLogcat();
-
AddAnrTraceFiles();
// NOTE: tombstones are always added as separate entries in the zip archive
@@ -1523,6 +1532,12 @@
// keep the system stats as close to its initial state as possible.
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysCritical);
+ // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
+ // buffer.
+ DoLogcat();
+ // Capture timestamp after first logcat to use in next logcat
+ time_t logcat_ts = time(nullptr);
+
/* collect stack traces from Dalvik and native processes (needs root) */
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpTraces, &dump_traces_path);
@@ -1569,7 +1584,10 @@
}
RETURN_IF_USER_DENIED_CONSENT();
- return dumpstate();
+ Dumpstate::RunStatus status = dumpstate();
+ // Capture logcat since the last time we did it.
+ DoSystemLogcat(logcat_ts);
+ return status;
}
// This method collects common dumpsys for telephony and wifi
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index 9f65425..abdf168 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -59,12 +59,13 @@
"usage: dumpsys\n"
" To dump all services.\n"
"or:\n"
- " dumpsys [-t TIMEOUT] [--priority LEVEL] [--help | -l | --skip SERVICES | "
- "SERVICE [ARGS]]\n"
+ " dumpsys [-t TIMEOUT] [--priority LEVEL] [--pid] [--help | -l | --skip SERVICES "
+ "| SERVICE [ARGS]]\n"
" --help: shows this help\n"
" -l: only list services, do not dump them\n"
" -t TIMEOUT_SEC: TIMEOUT to use in seconds instead of default 10 seconds\n"
" -T TIMEOUT_MS: TIMEOUT to use in milliseconds instead of default 10 seconds\n"
+ " --pid: dump PID instead of usual dump\n"
" --proto: filter services that support dumping data in proto format. Dumps\n"
" will be in proto format.\n"
" --priority LEVEL: filter services based on specified priority\n"
@@ -120,9 +121,11 @@
bool showListOnly = false;
bool skipServices = false;
bool asProto = false;
+ Type type = Type::DUMP;
int timeoutArgMs = 10000;
int priorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL;
- static struct option longOptions[] = {{"priority", required_argument, 0, 0},
+ static struct option longOptions[] = {{"pid", no_argument, 0, 0},
+ {"priority", required_argument, 0, 0},
{"proto", no_argument, 0, 0},
{"skip", no_argument, 0, 0},
{"help", no_argument, 0, 0},
@@ -157,6 +160,8 @@
usage();
return -1;
}
+ } else if (!strcmp(longOptions[optionIndex].name, "pid")) {
+ type = Type::PID;
}
break;
@@ -246,7 +251,7 @@
const String16& serviceName = services[i];
if (IsSkipped(skippedServices, serviceName)) continue;
- if (startDumpThread(serviceName, args) == OK) {
+ if (startDumpThread(type, serviceName, args) == OK) {
bool addSeparator = (N > 1);
if (addSeparator) {
writeDumpHeader(STDOUT_FILENO, serviceName, priorityFlags);
@@ -313,7 +318,18 @@
}
}
-status_t Dumpsys::startDumpThread(const String16& serviceName, const Vector<String16>& args) {
+static status_t dumpPidToFd(const sp<IBinder>& service, const unique_fd& fd) {
+ pid_t pid;
+ status_t status = service->getDebugPid(&pid);
+ if (status != OK) {
+ return status;
+ }
+ WriteStringToFd(std::to_string(pid) + "\n", fd.get());
+ return OK;
+}
+
+status_t Dumpsys::startDumpThread(Type type, const String16& serviceName,
+ const Vector<String16>& args) {
sp<IBinder> service = sm_->checkService(serviceName);
if (service == nullptr) {
aerr << "Can't find service: " << serviceName << endl;
@@ -333,16 +349,22 @@
// dump blocks until completion, so spawn a thread..
activeThread_ = std::thread([=, remote_end{std::move(remote_end)}]() mutable {
- int err = service->dump(remote_end.get(), args);
+ status_t err = 0;
- // It'd be nice to be able to close the remote end of the socketpair before the dump
- // call returns, to terminate our reads if the other end closes their copy of the
- // file descriptor, but then hangs for some reason. There doesn't seem to be a good
- // way to do this, though.
- remote_end.reset();
+ switch (type) {
+ case Type::DUMP:
+ err = service->dump(remote_end.get(), args);
+ break;
+ case Type::PID:
+ err = dumpPidToFd(service, remote_end);
+ break;
+ default:
+ aerr << "Unknown dump type" << static_cast<int>(type) << endl;
+ return;
+ }
- if (err != 0) {
- aerr << "Error dumping service info: (" << strerror(err) << ") "
+ if (err != OK) {
+ aerr << "Error dumping service info status_t: (" << err << ") "
<< serviceName << endl;
}
});
diff --git a/cmds/dumpsys/dumpsys.h b/cmds/dumpsys/dumpsys.h
index c48a1e9..929c55c 100644
--- a/cmds/dumpsys/dumpsys.h
+++ b/cmds/dumpsys/dumpsys.h
@@ -51,6 +51,11 @@
*/
static void setServiceArgs(Vector<String16>& args, bool asProto, int priorityFlags);
+ enum class Type {
+ DUMP, // dump using `dump` function
+ PID, // dump pid of server only
+ };
+
/**
* Starts a thread to connect to a service and get its dump output. The thread redirects
* the output to a pipe. Thread must be stopped by a subsequent callto {@code
@@ -61,7 +66,8 @@
* {@code NAME_NOT_FOUND} service could not be found.
* {@code != OK} error
*/
- status_t startDumpThread(const String16& serviceName, const Vector<String16>& args);
+ status_t startDumpThread(Type type, const String16& serviceName,
+ const Vector<String16>& args);
/**
* Writes a section header to a file descriptor.
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index cbac839..cf4e0b5 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -194,7 +194,7 @@
CaptureStdout();
CaptureStderr();
dump_.setServiceArgs(args, supportsProto, priorityFlags);
- status_t status = dump_.startDumpThread(serviceName, args);
+ status_t status = dump_.startDumpThread(Dumpsys::Type::DUMP, serviceName, args);
EXPECT_THAT(status, Eq(0));
status = dump_.writeDump(STDOUT_FILENO, serviceName, std::chrono::milliseconds(500), false,
elapsedDuration, bytesWritten);
@@ -539,6 +539,27 @@
AssertDumpedWithPriority("runninghigh2", "dump2", PriorityDumper::PRIORITY_ARG_HIGH);
}
+// Tests 'dumpsys --pid'
+TEST_F(DumpsysTest, ListAllServicesWithPid) {
+ ExpectListServices({"Locksmith", "Valet"});
+ ExpectCheckService("Locksmith");
+ ExpectCheckService("Valet");
+
+ CallMain({"--pid"});
+
+ AssertRunningServices({"Locksmith", "Valet"});
+ AssertOutputContains(std::to_string(getpid()));
+}
+
+// Tests 'dumpsys --pid service_name'
+TEST_F(DumpsysTest, ListServiceWithPid) {
+ ExpectCheckService("Locksmith");
+
+ CallMain({"--pid", "Locksmith"});
+
+ AssertOutput(std::to_string(getpid()) + "\n");
+}
+
TEST_F(DumpsysTest, GetBytesWritten) {
const char* serviceName = "service2";
const char* dumpContents = "dump1";
@@ -563,4 +584,4 @@
dump_.writeDump(STDOUT_FILENO, String16("service"), std::chrono::milliseconds(500),
/* as_proto = */ false, elapsedDuration, bytesWritten);
EXPECT_THAT(status, Eq(INVALID_OPERATION));
-}
\ No newline at end of file
+}
diff --git a/headers/media_plugin/media/openmax/OMX_VideoExt.h b/headers/media_plugin/media/openmax/OMX_VideoExt.h
index 435fcc8..dc37bbd 100644
--- a/headers/media_plugin/media/openmax/OMX_VideoExt.h
+++ b/headers/media_plugin/media/openmax/OMX_VideoExt.h
@@ -291,18 +291,19 @@
/** Dolby Vision Profile enum type */
typedef enum OMX_VIDEO_DOLBYVISIONPROFILETYPE {
- OMX_VIDEO_DolbyVisionProfileUnknown = 0x0,
- OMX_VIDEO_DolbyVisionProfileDvavPer = 0x1,
- OMX_VIDEO_DolbyVisionProfileDvavPen = 0x2,
- OMX_VIDEO_DolbyVisionProfileDvheDer = 0x4,
- OMX_VIDEO_DolbyVisionProfileDvheDen = 0x8,
- OMX_VIDEO_DolbyVisionProfileDvheDtr = 0x10,
- OMX_VIDEO_DolbyVisionProfileDvheStn = 0x20,
- OMX_VIDEO_DolbyVisionProfileDvheDth = 0x40,
- OMX_VIDEO_DolbyVisionProfileDvheDtb = 0x80,
- OMX_VIDEO_DolbyVisionProfileDvheSt = 0x100,
- OMX_VIDEO_DolbyVisionProfileDvavSe = 0x200,
- OMX_VIDEO_DolbyVisionProfileMax = 0x7FFFFFFF
+ OMX_VIDEO_DolbyVisionProfileUnknown = 0x0,
+ OMX_VIDEO_DolbyVisionProfileDvavPer = 0x1,
+ OMX_VIDEO_DolbyVisionProfileDvavPen = 0x2,
+ OMX_VIDEO_DolbyVisionProfileDvheDer = 0x4,
+ OMX_VIDEO_DolbyVisionProfileDvheDen = 0x8,
+ OMX_VIDEO_DolbyVisionProfileDvheDtr = 0x10,
+ OMX_VIDEO_DolbyVisionProfileDvheStn = 0x20,
+ OMX_VIDEO_DolbyVisionProfileDvheDth = 0x40,
+ OMX_VIDEO_DolbyVisionProfileDvheDtb = 0x80,
+ OMX_VIDEO_DolbyVisionProfileDvheSt = 0x100,
+ OMX_VIDEO_DolbyVisionProfileDvavSe = 0x200,
+ OMX_VIDEO_DolbyVisionProfileDvav110 = 0x400,
+ OMX_VIDEO_DolbyVisionProfileMax = 0x7FFFFFFF
} OMX_VIDEO_DOLBYVISIONPROFILETYPE;
/** Dolby Vision Level enum type */
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 643a956..e5646ef 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -73,6 +73,7 @@
// or dessert updates. Instead, apex users should use libbinder_ndk.
apex_available: [
"//apex_available:platform",
+ "com.android.vndk.current",
// TODO(b/139016109) remove these three
"com.android.media.swcodec",
"test_com.android.media.swcodec",
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 573a038..7d9846a 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -50,10 +50,6 @@
#include <private/binder/binder_module.h>
#include "Static.h"
-#ifndef INT32_MAX
-#define INT32_MAX ((int32_t)(2147483647))
-#endif
-
#define LOG_REFS(...)
//#define LOG_REFS(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOG_ALLOC(...)
@@ -509,7 +505,7 @@
}
}
-#if defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
constexpr int32_t kHeader = B_PACK_CHARS('V', 'N', 'D', 'R');
#else
constexpr int32_t kHeader = B_PACK_CHARS('S', 'Y', 'S', 'T');
@@ -750,61 +746,37 @@
return writeUtf8AsUtf16(*str);
}
-namespace {
-
-template<typename T>
-status_t writeByteVectorInternal(Parcel* parcel, const std::vector<T>& val)
-{
- status_t status;
- if (val.size() > std::numeric_limits<int32_t>::max()) {
- status = BAD_VALUE;
- return status;
+status_t Parcel::writeByteVectorInternal(const int8_t* data, size_t size) {
+ if (size > std::numeric_limits<int32_t>::max()) {
+ return BAD_VALUE;
}
- status = parcel->writeInt32(val.size());
+ status_t status = writeInt32(size);
if (status != OK) {
return status;
}
- void* data = parcel->writeInplace(val.size());
- if (!data) {
- status = BAD_VALUE;
- return status;
- }
-
- memcpy(data, val.data(), val.size());
- return status;
+ return write(data, size);
}
-template<typename T>
-status_t writeByteVectorInternalPtr(Parcel* parcel,
- const std::unique_ptr<std::vector<T>>& val)
-{
- if (!val) {
- return parcel->writeInt32(-1);
- }
-
- return writeByteVectorInternal(parcel, *val);
-}
-
-} // namespace
-
status_t Parcel::writeByteVector(const std::vector<int8_t>& val) {
- return writeByteVectorInternal(this, val);
+ return writeByteVectorInternal(val.data(), val.size());
}
status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val)
{
- return writeByteVectorInternalPtr(this, val);
+ if (!val) return writeInt32(-1);
+ return writeByteVectorInternal(val->data(), val->size());
}
status_t Parcel::writeByteVector(const std::vector<uint8_t>& val) {
- return writeByteVectorInternal(this, val);
+ return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size());
}
status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val)
{
- return writeByteVectorInternalPtr(this, val);
+ if (!val) return writeInt32(-1);
+ return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());
}
status_t Parcel::writeInt32Vector(const std::vector<int32_t>& val)
@@ -1477,81 +1449,41 @@
return err;
}
-namespace {
-
-template<typename T>
-status_t readByteVectorInternal(const Parcel* parcel,
- std::vector<T>* val) {
- val->clear();
-
- int32_t size;
- status_t status = parcel->readInt32(&size);
-
- if (status != OK) {
- return status;
+status_t Parcel::readByteVectorInternal(int8_t* data, size_t size) const {
+ if (size_t(size) > dataAvail()) {
+ return BAD_VALUE;
}
-
- if (size < 0) {
- status = UNEXPECTED_NULL;
- return status;
- }
- if (size_t(size) > parcel->dataAvail()) {
- status = BAD_VALUE;
- return status;
- }
-
- T* data = const_cast<T*>(reinterpret_cast<const T*>(parcel->readInplace(size)));
- if (!data) {
- status = BAD_VALUE;
- return status;
- }
- val->reserve(size);
- val->insert(val->end(), data, data + size);
-
- return status;
+ return read(data, size);
}
-template<typename T>
-status_t readByteVectorInternalPtr(
- const Parcel* parcel,
- std::unique_ptr<std::vector<T>>* val) {
- const int32_t start = parcel->dataPosition();
- int32_t size;
- status_t status = parcel->readInt32(&size);
- val->reset();
-
- if (status != OK || size < 0) {
- return status;
- }
-
- parcel->setDataPosition(start);
- val->reset(new (std::nothrow) std::vector<T>());
-
- status = readByteVectorInternal(parcel, val->get());
-
- if (status != OK) {
- val->reset();
- }
-
- return status;
-}
-
-} // namespace
-
status_t Parcel::readByteVector(std::vector<int8_t>* val) const {
- return readByteVectorInternal(this, val);
+ if (status_t status = resizeOutVector(val); status != OK) return status;
+ return readByteVectorInternal(val->data(), val->size());
}
status_t Parcel::readByteVector(std::vector<uint8_t>* val) const {
- return readByteVectorInternal(this, val);
+ if (status_t status = resizeOutVector(val); status != OK) return status;
+ return readByteVectorInternal(reinterpret_cast<int8_t*>(val->data()), val->size());
}
status_t Parcel::readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const {
- return readByteVectorInternalPtr(this, val);
+ if (status_t status = resizeOutVector(val); status != OK) return status;
+ if (val->get() == nullptr) {
+ // resizeOutVector does not create the out vector if size is < 0.
+ // This occurs when writing a null byte vector.
+ return OK;
+ }
+ return readByteVectorInternal((*val)->data(), (*val)->size());
}
status_t Parcel::readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const {
- return readByteVectorInternalPtr(this, val);
+ if (status_t status = resizeOutVector(val); status != OK) return status;
+ if (val->get() == nullptr) {
+ // resizeOutVector does not create the out vector if size is < 0.
+ // This occurs when writing a null byte vector.
+ return OK;
+ }
+ return readByteVectorInternal(reinterpret_cast<int8_t*>((*val)->data()), (*val)->size());
}
status_t Parcel::readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const {
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 0336d3e..6971c72 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -373,7 +373,9 @@
}
}
+#ifdef __ANDROID__
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver '%s' could not be opened. Terminating.", driver);
+#endif
}
ProcessState::~ProcessState()
diff --git a/libs/binder/fuzzer/Android.bp b/libs/binder/fuzzer/Android.bp
index d2f0d37..a9d2b75 100644
--- a/libs/binder/fuzzer/Android.bp
+++ b/libs/binder/fuzzer/Android.bp
@@ -36,4 +36,8 @@
],
},
},
+ // This flag enables verbose output in the fuzz target, and is very useful
+ // for debugging a failure. If you are trying to diagnose how a crash was
+ // produced, you may find uncommenting the below line very useful.
+ // cflags: ["-DENABLE_LOG_FUZZ"],
}
diff --git a/libs/binder/fuzzer/binder.cpp b/libs/binder/fuzzer/binder.cpp
index 86264db..04fe0e7 100644
--- a/libs/binder/fuzzer/binder.cpp
+++ b/libs/binder/fuzzer/binder.cpp
@@ -93,26 +93,16 @@
PARCEL_READ_NO_STATUS(size_t, allowFds),
PARCEL_READ_NO_STATUS(size_t, hasFileDescriptors),
[] (const ::android::Parcel& p, uint8_t len) {
-#ifdef __ANDROID__
std::string interface(len, 'a');
FUZZ_LOG() << "about to enforceInterface: " << interface;
bool b = p.enforceInterface(::android::String16(interface.c_str()));
FUZZ_LOG() << "enforced interface: " << b;
-#else
- FUZZ_LOG() << "skipping enforceInterface";
- (void)p;
- (void)len;
-#endif // __ANDROID__
},
[] (const ::android::Parcel& p, uint8_t /*len*/) {
-#ifdef __ANDROID__
FUZZ_LOG() << "about to checkInterface";
- bool b = p.checkInterface(new android::BBinder());
+ android::sp<android::IBinder> aBinder = new android::BBinder();
+ bool b = p.checkInterface(aBinder.get());
FUZZ_LOG() << "checked interface: " << b;
-#else
- FUZZ_LOG() << "skipping checkInterface";
- (void)p;
-#endif // __ANDROID__
},
PARCEL_READ_NO_STATUS(size_t, objectsCount),
PARCEL_READ_NO_STATUS(status_t, errorCheck),
diff --git a/libs/binder/fuzzer/hwbinder.cpp b/libs/binder/fuzzer/hwbinder.cpp
index b8cce72..0fec393 100644
--- a/libs/binder/fuzzer/hwbinder.cpp
+++ b/libs/binder/fuzzer/hwbinder.cpp
@@ -30,6 +30,9 @@
return os;
}
+#define PARCEL_READ_OPT_STATUS(T, FUN) \
+ PARCEL_READ_NO_STATUS(T, FUN), PARCEL_READ_WITH_STATUS(T, FUN)
+
#define PARCEL_READ_NO_STATUS(T, FUN) \
[] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {\
FUZZ_LOG() << "about to read " #T " using " #FUN " with no status";\
@@ -45,6 +48,7 @@
FUZZ_LOG() << #T " status: " << status << " value: " << t;\
}
+// clang-format off
std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTIONS {
PARCEL_READ_NO_STATUS(size_t, dataSize),
PARCEL_READ_NO_STATUS(size_t, dataAvail),
@@ -62,30 +66,44 @@
FUZZ_LOG() << "enforceInterface status: " << okay;
},
PARCEL_READ_NO_STATUS(size_t, objectsCount),
+ [] (const ::android::hardware::Parcel& p, uint8_t length) {
+ FUZZ_LOG() << "about to read";
+ std::vector<uint8_t> data (length);
+ status_t status = p.read(data.data(), length);
+ FUZZ_LOG() << "read status: " << status << " data: " << hexString(data.data(), data.size());
+ },
+ [] (const ::android::hardware::Parcel& p, uint8_t length) {
+ FUZZ_LOG() << "about to read";
+ std::vector<uint8_t> data (length);
+ const void* inplace = p.readInplace(length);
+ FUZZ_LOG() << "read status: " << hexString(inplace, length);
+ },
PARCEL_READ_WITH_STATUS(int8_t, readInt8),
PARCEL_READ_WITH_STATUS(uint8_t, readUint8),
PARCEL_READ_WITH_STATUS(int16_t, readInt16),
PARCEL_READ_WITH_STATUS(uint16_t, readUint16),
- PARCEL_READ_WITH_STATUS(int32_t, readInt32),
- PARCEL_READ_WITH_STATUS(uint32_t, readUint32),
- PARCEL_READ_WITH_STATUS(int64_t, readInt64),
- PARCEL_READ_WITH_STATUS(uint64_t, readUint64),
- PARCEL_READ_WITH_STATUS(float, readFloat),
- PARCEL_READ_WITH_STATUS(double, readDouble),
- PARCEL_READ_WITH_STATUS(bool, readBool),
- PARCEL_READ_WITH_STATUS(::android::String16, readString16),
- PARCEL_READ_WITH_STATUS(::android::sp<::android::hardware::IBinder>, readStrongBinder),
- PARCEL_READ_WITH_STATUS(::android::sp<::android::hardware::IBinder>, readNullableStrongBinder),
- [] (const ::android::hardware::Parcel& p, uint8_t amount) {
- FUZZ_LOG() << "about to readInPlace " << amount;
- const uint8_t* data = (const uint8_t*)p.readInplace(amount);
- if (data) {
- std::vector<uint8_t> vdata(data, data + amount);
- FUZZ_LOG() << "readInPlace " << amount << " data: " << hexString(vdata);
- } else {
- FUZZ_LOG() << "readInPlace " << amount << " no data";
- }
+ PARCEL_READ_OPT_STATUS(int32_t, readInt32),
+ PARCEL_READ_OPT_STATUS(uint32_t, readUint32),
+ PARCEL_READ_OPT_STATUS(int64_t, readInt64),
+ PARCEL_READ_OPT_STATUS(uint64_t, readUint64),
+ PARCEL_READ_OPT_STATUS(float, readFloat),
+ PARCEL_READ_OPT_STATUS(double, readDouble),
+ PARCEL_READ_OPT_STATUS(bool, readBool),
+ [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {
+ FUZZ_LOG() << "about to readCString";
+ const char* str = p.readCString();
+ FUZZ_LOG() << "readCString " << (str ? str : "<null>");
},
+ PARCEL_READ_OPT_STATUS(::android::String16, readString16),
+ PARCEL_READ_WITH_STATUS(std::unique_ptr<::android::String16>, readString16),
+ [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {
+ FUZZ_LOG() << "about to readString16Inplace";
+ size_t outSize = 0;
+ const char16_t* str = p.readString16Inplace(&outSize);
+ FUZZ_LOG() << "readString16Inplace: " << hexString(str, sizeof(char16_t) * outSize);
+ },
+ PARCEL_READ_OPT_STATUS(::android::sp<::android::hardware::IBinder>, readStrongBinder),
+ PARCEL_READ_WITH_STATUS(::android::sp<::android::hardware::IBinder>, readNullableStrongBinder),
[] (const ::android::hardware::Parcel& p, uint8_t size) {
FUZZ_LOG() << "about to readBuffer";
size_t handle = 0;
@@ -130,6 +148,28 @@
// should be null since we don't create any IPC objects
CHECK(data == nullptr) << data;
},
+ [] (const ::android::hardware::Parcel& p, uint8_t size) {
+ FUZZ_LOG() << "about to readEmbeddedNativeHandle";
+ size_t parent_buffer_handle = size & 0xf;
+ size_t parent_offset = size >> 4;
+ const native_handle_t* handle = nullptr;
+ status_t status = p.readEmbeddedNativeHandle(parent_buffer_handle, parent_offset, &handle);
+ FUZZ_LOG() << "readEmbeddedNativeHandle status: " << status << " handle: " << handle << " handle: " << handle;
+
+ // should be null since we don't create any IPC objects
+ CHECK(handle == nullptr) << handle;
+ },
+ [] (const ::android::hardware::Parcel& p, uint8_t size) {
+ FUZZ_LOG() << "about to readNullableEmbeddedNativeHandle";
+ size_t parent_buffer_handle = size & 0xf;
+ size_t parent_offset = size >> 4;
+ const native_handle_t* handle = nullptr;
+ status_t status = p.readNullableEmbeddedNativeHandle(parent_buffer_handle, parent_offset, &handle);
+ FUZZ_LOG() << "readNullableEmbeddedNativeHandle status: " << status << " handle: " << handle << " handle: " << handle;
+
+ // should be null since we don't create any IPC objects
+ CHECK(handle == nullptr) << handle;
+ },
[] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {
FUZZ_LOG() << "about to readNativeHandleNoDup";
const native_handle_t* handle = nullptr;
@@ -150,3 +190,4 @@
CHECK(handle == nullptr) << handle;
},
};
+// clang-format on
diff --git a/libs/binder/fuzzer/main.cpp b/libs/binder/fuzzer/main.cpp
index 369aa34..3b7caea 100644
--- a/libs/binder/fuzzer/main.cpp
+++ b/libs/binder/fuzzer/main.cpp
@@ -34,24 +34,45 @@
P p;
p.setData(input.data(), input.size());
+ // since we are only using a byte to index
+ CHECK(reads.size() <= 255) << reads.size();
+
for (size_t i = 0; i < instructions.size() - 1; i += 2) {
uint8_t a = instructions[i];
+ uint8_t readIdx = a % reads.size();
+
uint8_t b = instructions[i + 1];
- FUZZ_LOG() << "size: " << p.dataSize() << " avail: " << p.dataAvail()
- << " pos: " << p.dataPosition() << " cap: " << p.dataCapacity();
+ FUZZ_LOG() << "Instruction: " << (i / 2) + 1 << "/" << instructions.size() / 2
+ << " cmd: " << static_cast<size_t>(a) << " (" << static_cast<size_t>(readIdx)
+ << ") arg: " << static_cast<size_t>(b) << " size: " << p.dataSize()
+ << " avail: " << p.dataAvail() << " pos: " << p.dataPosition()
+ << " cap: " << p.dataCapacity();
- reads[a % reads.size()](p, b);
+ reads[readIdx](p, b);
}
}
void fuzz(uint8_t options, const std::vector<uint8_t>& input, const std::vector<uint8_t>& instructions) {
- (void) options;
+ uint8_t parcelType = options & 0x3;
- // although they will do completely different things, might as well fuzz both
- doFuzz<::android::hardware::Parcel>(HWBINDER_PARCEL_READ_FUNCTIONS, input, instructions);
- doFuzz<::android::Parcel>(BINDER_PARCEL_READ_FUNCTIONS, input, instructions);
- doFuzz<NdkParcelAdapter>(BINDER_NDK_PARCEL_READ_FUNCTIONS, input, instructions);
+ switch (parcelType) {
+ case 0x0:
+ doFuzz<::android::hardware::Parcel>(HWBINDER_PARCEL_READ_FUNCTIONS, input,
+ instructions);
+ break;
+ case 0x1:
+ doFuzz<::android::Parcel>(BINDER_PARCEL_READ_FUNCTIONS, input, instructions);
+ break;
+ case 0x2:
+ doFuzz<NdkParcelAdapter>(BINDER_NDK_PARCEL_READ_FUNCTIONS, input, instructions);
+ break;
+ case 0x3:
+ /*reserved for future use*/
+ break;
+ default:
+ LOG_ALWAYS_FATAL("unknown parcel type %d", static_cast<int>(parcelType));
+ }
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
diff --git a/libs/binder/fuzzer/util.cpp b/libs/binder/fuzzer/util.cpp
index b1213e9..479f406 100644
--- a/libs/binder/fuzzer/util.cpp
+++ b/libs/binder/fuzzer/util.cpp
@@ -24,13 +24,17 @@
std::string hexString(const void* bytes, size_t len) {
if (bytes == nullptr) return "<null>";
- std::ostringstream s;
- s << std::hex << std::setfill('0');
+ const uint8_t* bytes8 = static_cast<const uint8_t*>(bytes);
+ char chars[] = "0123456789abcdef";
+ std::string result;
+ result.resize(len * 2);
+
for (size_t i = 0; i < len; i++) {
- s << std::setw(2) << static_cast<int>(
- static_cast<const uint8_t*>(bytes)[i]);
+ result[2 * i] = chars[bytes8[i] >> 4];
+ result[2 * i + 1] = chars[bytes8[i] & 0xf];
}
- return s.str();
+
+ return result;
}
std::string hexString(const std::vector<uint8_t>& bytes) {
return hexString(bytes.data(), bytes.size());
diff --git a/libs/binder/fuzzer/util.h b/libs/binder/fuzzer/util.h
index 416c3a7..aa504d2 100644
--- a/libs/binder/fuzzer/util.h
+++ b/libs/binder/fuzzer/util.h
@@ -23,27 +23,31 @@
#error "Must define FUZZ_LOG_TAG"
#endif
-#define ENABLE_LOG_FUZZ 1
-#define FUZZ_LOG() FuzzLog(FUZZ_LOG_TAG, ENABLE_LOG_FUZZ).log()
+#define FUZZ_LOG() FuzzLog(FUZZ_LOG_TAG).log()
+#ifdef ENABLE_LOG_FUZZ
class FuzzLog {
public:
- FuzzLog(const std::string& tag, bool log) : mTag(tag), mLog(log) {}
- ~FuzzLog() {
- if (mLog) {
- std::cout << mTag << ": " << mOs.str() << std::endl;
- }
- }
+ FuzzLog(const char* tag) : mTag(tag) {}
+ ~FuzzLog() { std::cout << mTag << ": " << mOs.str() << std::endl; }
- std::stringstream& log() {
- return mOs;
- }
+ std::stringstream& log() { return mOs; }
private:
- std::string mTag;
- bool mLog;
+ const char* mTag = nullptr;
std::stringstream mOs;
};
+#else
+class FuzzLog {
+public:
+ FuzzLog(const char* /*tag*/) {}
+ template <typename T>
+ FuzzLog& operator<<(const T& /*t*/) {
+ return *this;
+ }
+ FuzzLog& log() { return *this; }
+};
+#endif
std::string hexString(const void* bytes, size_t len);
std::string hexString(const std::vector<uint8_t>& bytes);
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 8726681..0f8abab 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -19,6 +19,7 @@
#include <map> // for legacy reasons
#include <string>
+#include <type_traits>
#include <vector>
#include <android-base/unique_fd.h>
@@ -157,6 +158,18 @@
status_t writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val);
status_t writeStrongBinderVector(const std::vector<sp<IBinder>>& val);
+ // Write an Enum vector with underlying type int8_t.
+ // Does not use padding; each byte is contiguous.
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t writeEnumVector(const std::vector<T>& val);
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val);
+ // Write an Enum vector with underlying type != int8_t.
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t writeEnumVector(const std::vector<T>& val);
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val);
+
template<typename T>
status_t writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val);
template<typename T>
@@ -275,6 +288,19 @@
status_t readStrongBinder(sp<IBinder>* val) const;
status_t readNullableStrongBinder(sp<IBinder>* val) const;
+
+ // Read an Enum vector with underlying type int8_t.
+ // Does not use padding; each byte is contiguous.
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t readEnumVector(std::vector<T>* val) const;
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const;
+ // Read an Enum vector with underlying type != int8_t.
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t readEnumVector(std::vector<T>* val) const;
+ template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+ status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const;
+
template<typename T>
status_t readParcelableVector(
std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const;
@@ -438,6 +464,19 @@
status_t writeRawNullableParcelable(const Parcelable*
parcelable);
+ template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool> = 0>
+ status_t writeEnum(const T& val);
+ template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool> = 0>
+ status_t writeEnum(const T& val);
+
+ template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool> = 0>
+ status_t readEnum(T* pArg) const;
+ template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool> = 0>
+ status_t readEnum(T* pArg) const;
+
+ status_t writeByteVectorInternal(const int8_t* data, size_t size);
+ status_t readByteVectorInternal(int8_t* data, size_t size) const;
+
template<typename T, typename U>
status_t unsafeReadTypedVector(std::vector<T>* val,
status_t(Parcel::*read_func)(U*) const) const;
@@ -913,6 +952,66 @@
return unsafeWriteTypedVector(*val, &Parcel::writeNullableParcelable<T>);
}
+template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>>
+status_t Parcel::writeEnum(const T& val) {
+ return writeInt32(static_cast<int32_t>(val));
+}
+template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool>>
+status_t Parcel::writeEnum(const T& val) {
+ return writeInt64(static_cast<int64_t>(val));
+}
+
+template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::writeEnumVector(const std::vector<T>& val) {
+ return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size());
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::writeEnumVector(const std::unique_ptr<std::vector<T>>& val) {
+ if (!val) return writeInt32(-1);
+ return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::writeEnumVector(const std::vector<T>& val) {
+ return writeTypedVector(val, &Parcel::writeEnum);
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::writeEnumVector(const std::unique_ptr<std::vector<T>>& val) {
+ return writeNullableTypedVector(val, &Parcel::writeEnum);
+}
+
+template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>>
+status_t Parcel::readEnum(T* pArg) const {
+ return readInt32(reinterpret_cast<int32_t *>(pArg));
+}
+template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool>>
+status_t Parcel::readEnum(T* pArg) const {
+ return readInt64(reinterpret_cast<int64_t *>(pArg));
+}
+
+template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::readEnumVector(std::vector<T>* val) const {
+ if (status_t status = resizeOutVector(val); status != OK) return status;
+ return readByteVectorInternal(reinterpret_cast<int8_t*>(val->data()), val->size());
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const {
+ if (status_t status = resizeOutVector(val); status != OK) return status;
+ if (val->get() == nullptr) {
+ // resizeOutVector does not create the out vector if size is < 0.
+ // This occurs when writing a null Enum vector.
+ return OK;
+ }
+ return readByteVectorInternal(reinterpret_cast<int8_t*>((*val)->data()), (*val)->size());
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::readEnumVector(std::vector<T>* val) const {
+ return readTypedVector(val, &Parcel::readEnum);
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const {
+ return readNullableTypedVector(val, &Parcel::readEnum);
+}
+
// ---------------------------------------------------------------------------
inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)
diff --git a/libs/binder/include/binder/Stability.h b/libs/binder/include/binder/Stability.h
index 2894482..b2f51d3 100644
--- a/libs/binder/include/binder/Stability.h
+++ b/libs/binder/include/binder/Stability.h
@@ -81,7 +81,7 @@
VINTF = 0b111111,
};
-#if defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
static constexpr Level kLocalStability = Level::VENDOR;
#else
static constexpr Level kLocalStability = Level::SYSTEM;
diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h
index b03fce1..924812e 100644
--- a/libs/binder/ndk/include_platform/android/binder_stability.h
+++ b/libs/binder/ndk/include_platform/android/binder_stability.h
@@ -20,7 +20,8 @@
__BEGIN_DECLS
-#if defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || \
+ (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
/**
* This interface has the stability of the vendor image.
@@ -31,7 +32,8 @@
AIBinder_markVendorStability(binder);
}
-#else // defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#else // defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) &&
+ // !defined(__ANDROID_APEX__))
/**
* This interface has the stability of the system image.
@@ -42,7 +44,8 @@
AIBinder_markSystemStability(binder);
}
-#endif // defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#endif // defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) &&
+ // !defined(__ANDROID_APEX__))
/**
* This interface has system<->vendor stability
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 30f5f73..2859111 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -307,6 +307,13 @@
}
}
+bool GraphicsEnv::setInjectLayersPrSetDumpable() {
+ if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
+ return false;
+ }
+ return true;
+}
+
void* GraphicsEnv::loadLibrary(std::string name) {
const android_dlextinfo dlextinfo = {
.flags = ANDROID_DLEXT_USE_NAMESPACE,
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index a47f468..83448d4 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -68,6 +68,14 @@
void setDriverLoaded(GpuStatsInfo::Api api, bool isDriverLoaded, int64_t driverLoadingTime);
/*
+ * Api for Vk/GL layer injection. Presently, drivers enable certain
+ * profiling features when prctl(PR_GET_DUMPABLE) returns true.
+ * Calling this when layer injection metadata is present allows the driver
+ * to enable profiling even when in a non-debuggable app
+ */
+ bool setInjectLayersPrSetDumpable();
+
+ /*
* Apis for ANGLE
*/
// Check if the requested app should use ANGLE.
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index da51675..e6d442d 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -35,6 +35,7 @@
":libgui_bufferqueue_sources",
"BitTube.cpp",
+ "BLASTBufferQueue.cpp",
"BufferHubConsumer.cpp",
"BufferHubProducer.cpp",
"BufferItemConsumer.cpp",
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
new file mode 100644
index 0000000..3a369cd
--- /dev/null
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 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 <gui/BLASTBufferQueue.h>
+#include <gui/BufferItemConsumer.h>
+
+#include <chrono>
+
+using namespace std::chrono_literals;
+
+namespace android {
+
+BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, int height)
+ : mSurfaceControl(surface), mWidth(width), mHeight(height) {
+ BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+ mBufferItemConsumer =
+ new BufferItemConsumer(mConsumer, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, 1, true);
+ mBufferItemConsumer->setName(String8("BLAST Consumer"));
+ mBufferItemConsumer->setFrameAvailableListener(this);
+ mBufferItemConsumer->setBufferFreedListener(this);
+ mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
+ mBufferItemConsumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888);
+}
+
+void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, int width, int height) {
+ std::unique_lock _lock{mMutex};
+ mSurfaceControl = surface;
+ mWidth = width;
+ mHeight = height;
+ mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
+}
+
+static void transactionCallbackThunk(void* context, nsecs_t latchTime,
+ const sp<Fence>& presentFence,
+ const std::vector<SurfaceControlStats>& stats) {
+ if (context == nullptr) {
+ return;
+ }
+ BLASTBufferQueue* bq = static_cast<BLASTBufferQueue*>(context);
+ bq->transactionCallback(latchTime, presentFence, stats);
+}
+
+void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence>& /*presentFence*/,
+ const std::vector<SurfaceControlStats>& stats) {
+ std::unique_lock _lock{mMutex};
+
+ if (stats.size() > 0 && mNextCallbackBufferItem.mGraphicBuffer != nullptr) {
+ mBufferItemConsumer->releaseBuffer(mNextCallbackBufferItem,
+ stats[0].previousReleaseFence
+ ? stats[0].previousReleaseFence
+ : Fence::NO_FENCE);
+ mNextCallbackBufferItem = BufferItem();
+ }
+ mDequeueWaitCV.notify_one();
+ decStrong((void*)transactionCallbackThunk);
+}
+
+void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {
+ std::unique_lock _lock{mMutex};
+
+ SurfaceComposerClient::Transaction localTransaction;
+ bool applyTransaction = true;
+ SurfaceComposerClient::Transaction* t = &localTransaction;
+ if (mNextTransaction != nullptr) {
+ t = mNextTransaction;
+ mNextTransaction = nullptr;
+ applyTransaction = false;
+ }
+
+ int status = OK;
+ mNextCallbackBufferItem = mLastSubmittedBufferItem;
+
+ mLastSubmittedBufferItem = BufferItem();
+ status = mBufferItemConsumer->acquireBuffer(&mLastSubmittedBufferItem, -1, false);
+ if (status != OK) {
+ ALOGE("Failed to acquire?");
+ }
+
+ auto buffer = mLastSubmittedBufferItem.mGraphicBuffer;
+
+ if (buffer == nullptr) {
+ ALOGE("Null buffer");
+ return;
+ }
+
+
+ // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback.
+ incStrong((void*)transactionCallbackThunk);
+
+ t->setBuffer(mSurfaceControl, buffer);
+ t->setAcquireFence(mSurfaceControl,
+ item.mFence ? new Fence(item.mFence->dup()) : Fence::NO_FENCE);
+ t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this));
+
+ t->setFrame(mSurfaceControl, {0, 0, (int32_t)buffer->getWidth(), (int32_t)buffer->getHeight()});
+ t->setCrop(mSurfaceControl, {0, 0, (int32_t)buffer->getWidth(), (int32_t)buffer->getHeight()});
+
+ if (applyTransaction) {
+ ALOGE("Apply transaction");
+ t->apply();
+
+ if (mNextCallbackBufferItem.mGraphicBuffer != nullptr) {
+ mDequeueWaitCV.wait_for(_lock, 5000ms);
+ }
+ }
+}
+
+void BLASTBufferQueue::setNextTransaction(SurfaceComposerClient::Transaction* t) {
+ std::unique_lock _lock{mMutex};
+ mNextTransaction = t;
+}
+
+} // namespace android
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
new file mode 100644
index 0000000..6320556
--- /dev/null
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef ANDROID_GUI_BLAST_BUFFER_QUEUE_H
+#define ANDROID_GUI_BLAST_BUFFER_QUEUE_H
+
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/BufferItemConsumer.h>
+#include <gui/BufferItem.h>
+#include <gui/SurfaceComposerClient.h>
+
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+
+#include <system/window.h>
+
+namespace android {
+
+class BufferItemConsumer;
+
+class BLASTBufferQueue
+ : public ConsumerBase::FrameAvailableListener, public BufferItemConsumer::BufferFreedListener
+{
+public:
+ BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, int height);
+ sp<IGraphicBufferProducer> getIGraphicBufferProducer() const {
+ return mProducer;
+ }
+
+ void onBufferFreed(const wp<GraphicBuffer>&/* graphicBuffer*/) override { /* TODO */ }
+ void onFrameReplaced(const BufferItem& item) override {onFrameAvailable(item);}
+ void onFrameAvailable(const BufferItem& item) override;
+
+ void transactionCallback(nsecs_t latchTime, const sp<Fence>& presentFence,
+ const std::vector<SurfaceControlStats>& stats);
+ void setNextTransaction(SurfaceComposerClient::Transaction *t);
+
+ void update(const sp<SurfaceControl>& surface, int width, int height);
+
+
+ virtual ~BLASTBufferQueue() = default;
+
+private:
+ friend class BLASTBufferQueueHelper;
+
+ // can't be copied
+ BLASTBufferQueue& operator = (const BLASTBufferQueue& rhs);
+ BLASTBufferQueue(const BLASTBufferQueue& rhs);
+
+ sp<SurfaceControl> mSurfaceControl;
+
+ mutable std::mutex mMutex;
+
+ static const int MAX_BUFFERS = 2;
+ struct BufferInfo {
+ sp<GraphicBuffer> buffer;
+ int fence;
+ };
+
+ int mDequeuedBuffers = 0;
+
+ int mWidth;
+ int mHeight;
+
+ BufferItem mLastSubmittedBufferItem;
+ BufferItem mNextCallbackBufferItem;
+ sp<Fence> mLastFence;
+
+ std::condition_variable mDequeueWaitCV;
+
+ sp<IGraphicBufferConsumer> mConsumer;
+ sp<IGraphicBufferProducer> mProducer;
+ sp<BufferItemConsumer> mBufferItemConsumer;
+
+ SurfaceComposerClient::Transaction* mNextTransaction = nullptr;
+};
+
+} // namespace android
+
+#endif // ANDROID_GUI_SURFACE_H
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index cbda6b2..7f960ab 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -13,7 +13,8 @@
],
srcs: [
- "BufferItemConsumer_test.cpp",
+ "BLASTBufferQueue_test.cpp",
+ "BufferItemConsumer_test.cpp",
"BufferQueue_test.cpp",
"CpuConsumer_test.cpp",
"EndToEndNativeInputTest.cpp",
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
new file mode 100644
index 0000000..a5f115e
--- /dev/null
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#define LOG_TAG "BLASTBufferQueue_test"
+
+#include <gui/BLASTBufferQueue.h>
+
+#include <gui/SurfaceComposerClient.h>
+#include <ui/GraphicBuffer.h>
+
+#include <gtest/gtest.h>
+
+using namespace std::chrono_literals;
+
+namespace android {
+
+const int DEFAULT_WIDTH = 100;
+const int DEFAULT_HEIGHT = 100;
+
+using Transaction = SurfaceComposerClient::Transaction;
+
+class BLASTBufferQueueHelper {
+public:
+ BLASTBufferQueueHelper(const sp<SurfaceControl>& sc, int width, int height) {
+ mBlastBufferQueueAdapter = new BLASTBufferQueue(sc, width, height);
+ }
+
+ void update(const sp<SurfaceControl>& sc, int width, int height) {
+ mBlastBufferQueueAdapter->update(sc, width, height);
+ }
+
+ void setNextTransaction(Transaction* next) {
+ mBlastBufferQueueAdapter->setNextTransaction(next);
+ }
+
+ int getWidth() { return mBlastBufferQueueAdapter->mWidth; }
+ int getHeight() { return mBlastBufferQueueAdapter->mHeight; }
+ Transaction* getNextTransaction() { return mBlastBufferQueueAdapter->mNextTransaction; }
+ const sp<SurfaceControl> getSurfaceControl() {
+ return mBlastBufferQueueAdapter->mSurfaceControl;
+ }
+
+private:
+ sp<BLASTBufferQueue> mBlastBufferQueueAdapter;
+};
+
+class BLASTBufferQueueTest : public ::testing::Test {
+public:
+protected:
+ BLASTBufferQueueTest() {
+ const ::testing::TestInfo* const testInfo =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGV("Begin test: %s.%s", testInfo->test_case_name(), testInfo->name());
+ }
+
+ ~BLASTBufferQueueTest() {
+ const ::testing::TestInfo* const testInfo =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGV("End test: %s.%s", testInfo->test_case_name(), testInfo->name());
+ }
+
+ void SetUp() {
+ mClient = new SurfaceComposerClient();
+ mSurfaceControl = mClient->createSurface(String8("TestSurface"), DEFAULT_WIDTH,
+ DEFAULT_HEIGHT, PIXEL_FORMAT_RGBA_8888);
+ }
+
+ sp<SurfaceComposerClient> mClient;
+ sp<SurfaceControl> mSurfaceControl;
+};
+
+TEST_F(BLASTBufferQueueTest, CreateBLASTBufferQueue) {
+ // create BLASTBufferQueue adapter associated with this surface
+ BLASTBufferQueueHelper adapter(mSurfaceControl, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ ASSERT_EQ(mSurfaceControl, adapter.getSurfaceControl());
+ ASSERT_EQ(DEFAULT_WIDTH, adapter.getWidth());
+ ASSERT_EQ(DEFAULT_HEIGHT, adapter.getHeight());
+ ASSERT_EQ(nullptr, adapter.getNextTransaction());
+}
+
+TEST_F(BLASTBufferQueueTest, Update) {
+ BLASTBufferQueueHelper adapter(mSurfaceControl, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ sp<SurfaceControl> updateSurface =
+ mClient->createSurface(String8("UpdateTest"), DEFAULT_WIDTH / 2, DEFAULT_HEIGHT / 2,
+ PIXEL_FORMAT_RGB_888);
+ adapter.update(updateSurface, DEFAULT_WIDTH / 2, DEFAULT_HEIGHT / 2);
+ ASSERT_EQ(updateSurface, adapter.getSurfaceControl());
+ ASSERT_EQ(DEFAULT_WIDTH / 2, adapter.getWidth());
+ ASSERT_EQ(DEFAULT_HEIGHT / 2, adapter.getHeight());
+}
+
+TEST_F(BLASTBufferQueueTest, SetNextTransaction) {
+ BLASTBufferQueueHelper adapter(mSurfaceControl, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ Transaction next;
+ adapter.setNextTransaction(&next);
+ ASSERT_EQ(&next, adapter.getNextTransaction());
+}
+} // namespace android
diff --git a/opengl/tests/gl_perf/fill_common.cpp b/opengl/tests/gl_perf/fill_common.cpp
index fefedc0..613f1c6 100644
--- a/opengl/tests/gl_perf/fill_common.cpp
+++ b/opengl/tests/gl_perf/fill_common.cpp
@@ -191,10 +191,10 @@
static void randUniform(int pgm, const char *var) {
GLint loc = glGetUniformLocation(pgm, var);
if (loc >= 0) {
- float x = ((float)rand()) / RAND_MAX;
- float y = ((float)rand()) / RAND_MAX;
- float z = ((float)rand()) / RAND_MAX;
- float w = ((float)rand()) / RAND_MAX;
+ float x = ((float)rand()) / (float)RAND_MAX;
+ float y = ((float)rand()) / (float)RAND_MAX;
+ float z = ((float)rand()) / (float)RAND_MAX;
+ float w = ((float)rand()) / (float)RAND_MAX;
glUniform4f(loc, x, y, z, w);
}
}
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 7d30672..e7640dd 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -128,7 +128,7 @@
"from non shell/root entity (PID: %d)", ipc->getCallingPid());
return;
}
- mDispatcher->registerInputChannel(channel, false);
+ mDispatcher->registerInputChannel(channel);
}
void InputManager::unregisterInputChannel(const sp<InputChannel>& channel) {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 4db9ae2..ee8c344 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -3865,11 +3865,9 @@
}
}
-status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
- int32_t displayId) {
+status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
#if DEBUG_REGISTRATION
- ALOGD("channel '%s' ~ registerInputChannel - displayId=%" PRId32,
- inputChannel->getName().c_str(), displayId);
+ ALOGD("channel '%s' ~ registerInputChannel", inputChannel->getName().c_str());
#endif
{ // acquire lock
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 0d9d6b0..1f906e4 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -106,8 +106,7 @@
virtual bool transferTouchFocus(const sp<IBinder>& fromToken,
const sp<IBinder>& toToken) override;
- virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
- int32_t displayId) override;
+ virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel) override;
virtual status_t registerInputMonitor(const sp<InputChannel>& inputChannel, int32_t displayId,
bool isGestureMonitor) override;
virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) override;
diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp
index 18848a0..2baceba 100644
--- a/services/inputflinger/dispatcher/TouchState.cpp
+++ b/services/inputflinger/dispatcher/TouchState.cpp
@@ -93,15 +93,6 @@
std::end(newMonitors));
}
-void TouchState::removeWindow(const sp<InputWindowHandle>& windowHandle) {
- for (size_t i = 0; i < windows.size(); i++) {
- if (windows[i].windowHandle == windowHandle) {
- windows.erase(windows.begin() + i);
- return;
- }
- }
-}
-
void TouchState::removeWindowByToken(const sp<IBinder>& token) {
for (size_t i = 0; i < windows.size(); i++) {
if (windows[i].windowHandle->getToken() == token) {
diff --git a/services/inputflinger/dispatcher/TouchState.h b/services/inputflinger/dispatcher/TouchState.h
index 3e0e0eb..623c6a8 100644
--- a/services/inputflinger/dispatcher/TouchState.h
+++ b/services/inputflinger/dispatcher/TouchState.h
@@ -49,7 +49,6 @@
BitSet32 pointerIds);
void addPortalWindow(const sp<android::InputWindowHandle>& windowHandle);
void addGestureMonitors(const std::vector<TouchedMonitor>& monitors);
- void removeWindow(const sp<android::InputWindowHandle>& windowHandle);
void removeWindowByToken(const sp<IBinder>& token);
void filterNonAsIsTouchWindows();
void filterNonMonitors();
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index 9329ca6..ce7366f 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -126,8 +126,7 @@
*
* This method may be called on any thread (usually by the input manager).
*/
- virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
- int32_t displayId) = 0;
+ virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel) = 0;
/* Registers input channels to be used to monitor input events.
*
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index aa98ef7..7d69854 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -471,7 +471,7 @@
FakeInputReceiver(dispatcher, name, displayId),
mFocused(false), mFrame(Rect(0, 0, WIDTH, HEIGHT)), mLayoutParamFlags(0) {
mServerChannel->setToken(new BBinder());
- mDispatcher->registerInputChannel(mServerChannel, displayId);
+ mDispatcher->registerInputChannel(mServerChannel);
inputApplicationHandle->updateInfo();
mInfo.applicationInfo = *inputApplicationHandle->getInfo();
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index 3df8360..3e47ec6 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -28,7 +28,6 @@
#include <utils/Trace.h>
#include <algorithm>
-#include <regex>
namespace android {
@@ -156,22 +155,6 @@
return static_cast<int32_t>(delta);
}
-// This regular expression captures the following for instance:
-// StatusBar in StatusBar#0
-// com.appname in com.appname/com.appname.activity#0
-// com.appname in SurfaceView - com.appname/com.appname.activity#0
-static const std::regex packageNameRegex("(?:SurfaceView[-\\s\\t]+)?([^/]+).*#\\d+");
-
-static std::string getPackageName(const std::string& layerName) {
- std::smatch match;
- if (std::regex_match(layerName.begin(), layerName.end(), match, packageNameRegex)) {
- // There must be a match for group 1 otherwise the whole string is not
- // matched and the above will return false
- return match[1];
- }
- return "";
-}
-
void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerID) {
ATRACE_CALL();
@@ -187,7 +170,6 @@
const std::string& layerName = layerRecord.layerName;
if (!mTimeStats.stats.count(layerName)) {
mTimeStats.stats[layerName].layerName = layerName;
- mTimeStats.stats[layerName].packageName = getPackageName(layerName);
}
TimeStatsHelper::TimeStatsLayer& timeStatsLayer = mTimeStats.stats[layerName];
timeStatsLayer.totalFrames++;
@@ -236,19 +218,13 @@
}
}
-// This regular expression captures the following layer names for instance:
-// 1) StatusBat#0
-// 2) NavigationBar#1
-// 3) co(m).*#0
-// 4) SurfaceView - co(m).*#0
-// Using [-\\s\t]+ for the conjunction part between SurfaceView and co(m).*
-// is a bit more robust in case there's a slight change.
-// The layer name would only consist of . / $ _ 0-9 a-z A-Z in most cases.
-static const std::regex layerNameRegex(
- "(((SurfaceView[-\\s\\t]+)?com?\\.[./$\\w]+)|((Status|Navigation)Bar))#\\d+");
+static constexpr const char* kPopupWindowPrefix = "PopupWindow";
+static const size_t kMinLenLayerName = std::strlen(kPopupWindowPrefix);
+// Avoid tracking the "PopupWindow:<random hash>#<number>" layers
static bool layerNameIsValid(const std::string& layerName) {
- return std::regex_match(layerName.begin(), layerName.end(), layerNameRegex);
+ return layerName.length() >= kMinLenLayerName &&
+ layerName.compare(0, kMinLenLayerName, kPopupWindowPrefix) != 0;
}
void TimeStats::setPostTime(int32_t layerID, uint64_t frameNumber, const std::string& layerName,
diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
index dee2cae..4eb9ec3 100644
--- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
@@ -171,7 +171,7 @@
}
static std::string genLayerName(int32_t layerID) {
- return (layerID < 0 ? "invalid.dummy" : "com.dummy#") + std::to_string(layerID);
+ return (layerID < 0 ? "PopupWindow:b54fcd1#0" : "com.dummy#") + std::to_string(layerID);
}
void TimeStatsTest::setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts) {
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index d829e41..f676573 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -480,14 +480,14 @@
if (strcmp(name, "VK_EXT_swapchain_colorspace") == 0) return ProcHook::EXT_swapchain_colorspace;
if (strcmp(name, "VK_GOOGLE_display_timing") == 0) return ProcHook::GOOGLE_display_timing;
if (strcmp(name, "VK_KHR_android_surface") == 0) return ProcHook::KHR_android_surface;
+ if (strcmp(name, "VK_KHR_get_surface_capabilities2") == 0) return ProcHook::KHR_get_surface_capabilities2;
if (strcmp(name, "VK_KHR_incremental_present") == 0) return ProcHook::KHR_incremental_present;
if (strcmp(name, "VK_KHR_shared_presentable_image") == 0) return ProcHook::KHR_shared_presentable_image;
if (strcmp(name, "VK_KHR_surface") == 0) return ProcHook::KHR_surface;
if (strcmp(name, "VK_KHR_swapchain") == 0) return ProcHook::KHR_swapchain;
- if (strcmp(name, "VK_KHR_get_surface_capabilities2") == 0) return ProcHook::KHR_get_surface_capabilities2;
- if (strcmp(name, "VK_KHR_get_physical_device_properties2") == 0) return ProcHook::KHR_get_physical_device_properties2;
if (strcmp(name, "VK_ANDROID_external_memory_android_hardware_buffer") == 0) return ProcHook::ANDROID_external_memory_android_hardware_buffer;
if (strcmp(name, "VK_KHR_bind_memory2") == 0) return ProcHook::KHR_bind_memory2;
+ if (strcmp(name, "VK_KHR_get_physical_device_properties2") == 0) return ProcHook::KHR_get_physical_device_properties2;
// clang-format on
return ProcHook::EXTENSION_UNKNOWN;
}
@@ -562,5 +562,3 @@
} // namespace driver
} // namespace vulkan
-
-// clang-format on
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index fb2f257..cd7d8f8 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -40,14 +40,14 @@
EXT_swapchain_colorspace,
GOOGLE_display_timing,
KHR_android_surface,
+ KHR_get_surface_capabilities2,
KHR_incremental_present,
KHR_shared_presentable_image,
KHR_surface,
KHR_swapchain,
- KHR_get_surface_capabilities2,
- KHR_get_physical_device_properties2,
ANDROID_external_memory_android_hardware_buffer,
KHR_bind_memory2,
+ KHR_get_physical_device_properties2,
EXTENSION_CORE, // valid bit
EXTENSION_COUNT,
diff --git a/vulkan/nulldrv/null_driver_gen.h b/vulkan/nulldrv/null_driver_gen.h
index 668dc7d..0d3f688 100644
--- a/vulkan/nulldrv/null_driver_gen.h
+++ b/vulkan/nulldrv/null_driver_gen.h
@@ -207,9 +207,6 @@
VKAPI_ATTR VkResult GetSwapchainGrallocUsage2ANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, uint64_t* grallocConsumerUsage, uint64_t* grallocProducerUsage);
VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);
-VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
-VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
-VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);
// clang-format on
} // namespace null_driver
diff --git a/vulkan/scripts/api_generator.py b/vulkan/scripts/api_generator.py
index a0c648c..d1fff42 100644
--- a/vulkan/scripts/api_generator.py
+++ b/vulkan/scripts/api_generator.py
@@ -20,21 +20,36 @@
import os
import generator_common as gencom
-def isInstanceDispatchTableEntry(functionName):
- if functionName == 'vkEnumerateDeviceLayerProperties': # deprecated, unused internally - @dbd33bc
- return False
- if gencom.gencom.isFunctionExported(functionName) and gencom.isInstanceDispatched(functionName):
- return True
- return False
+_INTERCEPTED_COMMANDS = [
+ 'vkCreateDevice',
+ 'vkDestroyDevice',
+ 'vkDestroyInstance',
+ 'vkEnumerateDeviceExtensionProperties',
+ 'vkEnumerateDeviceLayerProperties',
+]
-def isDeviceDispatchTableEntry(functionName):
- if gencom.gencom.isFunctionExported(functionName) and gencom.gencom.isDeviceDispatched(functionName):
- return True
- return False
-def api_genh():
+def gen_h():
+ genfile = os.path.join(os.path.dirname(__file__),
+ '..', 'libvulkan', 'api_gen.h')
- header = """#ifndef LIBVULKAN_API_GEN_H
+ with open(genfile, 'w') as f:
+ instance_dispatch_table_entries = []
+ device_dispatch_table_entries = []
+
+ for cmd in gencom.command_list:
+ if cmd not in gencom.alias_dict:
+ if gencom.is_instance_dispatch_table_entry(cmd):
+ instance_dispatch_table_entries.append(
+ 'PFN_' + cmd + ' ' + gencom.base_name(cmd) + ';')
+ elif gencom.is_device_dispatch_table_entry(cmd):
+ device_dispatch_table_entries.append(
+ 'PFN_' + cmd + ' ' + gencom.base_name(cmd) + ';')
+
+ f.write(gencom.copyright_and_warning(2016))
+
+ f.write("""\
+#ifndef LIBVULKAN_API_GEN_H
#define LIBVULKAN_API_GEN_H
#include <vulkan/vulkan.h>
@@ -46,9 +61,26 @@
namespace vulkan {
namespace api {
-"""
+struct InstanceDispatchTable {
+ // clang-format off\n""")
- tail = """
+ for entry in instance_dispatch_table_entries:
+ f.write(gencom.indent(1) + entry + '\n')
+
+ f.write("""\
+ // clang-format on
+};
+
+struct DeviceDispatchTable {
+ // clang-format off\n""")
+
+ for entry in device_dispatch_table_entries:
+ f.write(gencom.indent(1) + entry + '\n')
+
+ f.write("""\
+ // clang-format on
+};
+
bool InitDispatchTable(
VkInstance instance,
PFN_vkGetInstanceProcAddr get_proc,
@@ -61,105 +93,54 @@
} // namespace api
} // namespace vulkan
-#endif // LIBVULKAN_API_GEN_H
-"""
- genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','api_gen.h')
- with open(genfile, 'w') as f:
- instanceDispatchTableEntries = []
- deviceDispatchTableEntries = []
- for commands in gencom.allCommandsList:
- if commands not in gencom.aliasDict:
- if gencom.isInstanceDispatchTableEntry(commands):
- instanceDispatchTableEntries.append('PFN_'+commands+' '+commands[2:]+';')
- elif gencom.isDeviceDispatchTableEntry(commands):
- deviceDispatchTableEntries.append('PFN_'+commands+' '+commands[2:]+';')
+#endif // LIBVULKAN_API_GEN_H\n""")
- f.write (gencom.copyright)
- f.write (gencom.warning)
- f.write (header)
- f.write ('struct InstanceDispatchTable {\n')
- gencom.clang_off(f,1)
- for functions in instanceDispatchTableEntries:
- f.write(gencom.clang_off_spaces + functions + '\n')
- gencom.clang_on(f,1)
- f.write ('};\n\n')
-
- f.write ('struct DeviceDispatchTable {\n')
- gencom.clang_off(f,1)
- for functions in deviceDispatchTableEntries:
- f.write(gencom.clang_off_spaces + functions + '\n')
- gencom.clang_on(f,1)
- f.write ('};\n')
-
- f.write (tail)
f.close()
- gencom.runClangFormat(genfile)
+ gencom.run_clang_format(genfile)
-def defineInitProc(name, f):
- f.write ('#define UNLIKELY(expr) __builtin_expect((expr), 0)\n')
- f.write ('\n')
- f.write ("""#define INIT_PROC(required, obj, proc) \\
- do { \\
- data.""" + name + """.proc = \\
- reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\
- if (UNLIKELY(required && !data.""" + name + """.proc)) { \\
- ALOGE("missing " #obj " proc: vk" #proc); \\
- success = false; \\
- } \\
- } while (0)\n\n""")
-def defineInitProcExt(f):
- f.write ('// Exported extension functions may be invoked even when their extensions\n')
- f.write ('// are disabled. Dispatch to stubs when that happens.\n')
- f.write ("""#define INIT_PROC_EXT(ext, required, obj, proc) \\
- do { \\
- if (extensions[driver::ProcHook::ext]) \\
- INIT_PROC(required, obj, proc); \\
- else \\
- data.dispatch.proc = disabled##proc; \\
- } while (0)\n\n""")
+def _define_extension_stub(cmd, f):
+ if (cmd in gencom.extension_dict and gencom.is_function_exported(cmd)):
+ ext_name = gencom.extension_dict[cmd]
+ ret = gencom.return_type_dict[cmd]
+ params = gencom.param_dict[cmd]
+ first_param = params[0][0] + params[0][1]
+ tail_params = ', '.join([i[0][:-1] for i in params[1:]])
-def defineExtensionStub(functionName, f):
- if functionName in gencom.extensionsDict and gencom.isFunctionExported(functionName):
- extname = gencom.extensionsDict[functionName]
- base_name = functionName[2:]
- pList = gencom.paramDict[functionName]
- firstParam = pList[0][0] + pList[0][1]
- tailParams = [x[0][:-1] for x in pList[1:]]
- tailP = ', '.join(tailParams)
- f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[functionName] + ' disabled' + base_name + '(' + firstParam + ', ' + tailP + ') {\n')
- f.write (gencom.clang_off_spaces)
- f.write ('driver::Logger(' + pList[0][1] + ').Err(' + pList[0][1] + ', \"' + extname + ' not enabled. Exported ' + functionName + ' not executed.\");\n')
- if gencom.returnTypeDict[functionName] != 'void':
- f.write(gencom.clang_off_spaces + 'return VK_SUCCESS;\n')
- f.write ('}\n\n')
+ f.write('VKAPI_ATTR ' + ret + ' disabled' + gencom.base_name(cmd) +
+ '(' + first_param + ', ' + tail_params + ') {\n')
-def isIntercepted(functionName):
- if gencom.isFunctionSupported(functionName):
- if gencom.isGloballyDispatched(functionName):
- return True
- elif functionName == 'vkCreateDevice':
- return True
- elif functionName == 'vkEnumerateDeviceLayerProperties':
- return True
- elif functionName == 'vkEnumerateDeviceExtensionProperties':
- return True
- elif functionName == 'vkDestroyInstance':
- return True
- elif functionName == 'vkDestroyDevice':
+ f.write(gencom.indent(1) + 'driver::Logger(' + params[0][1] +
+ ').Err(' + params[0][1] + ', \"' + ext_name +
+ ' not enabled. Exported ' + cmd + ' not executed.\");\n')
+
+ if gencom.return_type_dict[cmd] != 'void':
+ f.write(gencom.indent(1) + 'return VK_SUCCESS;\n')
+
+ f.write('}\n\n')
+
+
+def _is_intercepted(cmd):
+ if gencom.is_function_supported(cmd):
+ if gencom.is_globally_dispatched(cmd) or cmd in _INTERCEPTED_COMMANDS:
return True
return False
-def interceptInstanceProcAddr(functionName, f):
- indent = 1
- f.write (gencom.clang_off_spaces*indent + '// global functions\n' + gencom.clang_off_spaces*indent+ 'if (instance == VK_NULL_HANDLE) {\n')
- indent = indent + 1
- for cmds in gencom.allCommandsList:
- if gencom.isGloballyDispatched(cmds):
- f.write(gencom.clang_off_spaces*indent + 'if (strcmp(pName, \"' + cmds + '\") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ');\n')
- f.write ('\n')
- f.write (""" ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \\\"%s\\\") call", pName);
+def _intercept_instance_proc_addr(f):
+ f.write("""\
+ // global functions
+ if (instance == VK_NULL_HANDLE) {\n""")
+
+ for cmd in gencom.command_list:
+ if gencom.is_globally_dispatched(cmd):
+ f.write(gencom.indent(2) +
+ 'if (strcmp(pName, \"' + cmd +
+ '\") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' +
+ gencom.base_name(cmd) + ');\n')
+
+ f.write("""
+ ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \\\"%s\\\") call", pName);
return nullptr;
}
@@ -167,14 +148,21 @@
const char* name;
PFN_vkVoidFunction proc;
} hooks[] = {\n""")
- sortedCommandsList = sorted(gencom.allCommandsList)
- for cmds in sortedCommandsList:
- if gencom.isFunctionExported(cmds):
- if gencom.isGloballyDispatched(cmds):
- f.write (gencom.clang_off_spaces*2 + '{ \"' + cmds + '\", nullptr },\n')
- elif isIntercepted(cmds) or cmds == 'vkGetInstanceProcAddr' or gencom.isDeviceDispatched(cmds):
- f.write (gencom.clang_off_spaces*2 + '{ \"' + cmds + '\", reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ') },\n')
- f.write (gencom.clang_off_spaces + """};
+
+ sorted_command_list = sorted(gencom.command_list)
+ for cmd in sorted_command_list:
+ if gencom.is_function_exported(cmd):
+ if gencom.is_globally_dispatched(cmd):
+ f.write(gencom.indent(2) + '{ \"' + cmd + '\", nullptr },\n')
+ elif (_is_intercepted(cmd) or
+ cmd == 'vkGetInstanceProcAddr' or
+ gencom.is_device_dispatched(cmd)):
+ f.write(gencom.indent(2) + '{ \"' + cmd +
+ '\", reinterpret_cast<PFN_vkVoidFunction>(' +
+ gencom.base_name(cmd) + ') },\n')
+
+ f.write("""\
+ };
// clang-format on
constexpr size_t count = sizeof(hooks) / sizeof(hooks[0]);
auto hook = std::lower_bound(
@@ -190,19 +178,25 @@
}
// clang-format off\n\n""")
-def interceptDeviceProcAddr(functionName, f):
- f.write (gencom.clang_off_spaces + """if (device == VK_NULL_HANDLE) {
+
+def _intercept_device_proc_addr(f):
+ f.write("""\
+ if (device == VK_NULL_HANDLE) {
ALOGE("invalid vkGetDeviceProcAddr(VK_NULL_HANDLE, ...) call");
return nullptr;
- }\n\n""")
- f.write (gencom.clang_off_spaces + 'static const char* const known_non_device_names[] = {\n')
- sortedCommandsList = sorted(gencom.allCommandsList)
- for cmds in sortedCommandsList:
- if gencom.isFunctionSupported(cmds):
- if not gencom.isDeviceDispatched(cmds):
- f.write(gencom.clang_off_spaces*2 + '\"' + cmds + '\",\n')
- f.write(gencom.clang_off_spaces + '};\n')
- f.write(gencom.clang_off_spaces + """// clang-format on
+ }
+
+ static const char* const known_non_device_names[] = {\n""")
+
+ sorted_command_list = sorted(gencom.command_list)
+ for cmd in sorted_command_list:
+ if gencom.is_function_supported(cmd):
+ if not gencom.is_device_dispatched(cmd):
+ f.write(gencom.indent(2) + '\"' + cmd + '\",\n')
+
+ f.write("""\
+ };
+ // clang-format on
constexpr size_t count =
sizeof(known_non_device_names) / sizeof(known_non_device_names[0]);
if (!pName ||
@@ -215,27 +209,38 @@
return nullptr;
}
// clang-format off\n\n""")
- for cmds in gencom.allCommandsList:
- if gencom.isDeviceDispatched(cmds):
- if isIntercepted(cmds) or cmds == 'vkGetDeviceProcAddr':
- f.write (gencom.clang_off_spaces + 'if (strcmp(pName, "' + cmds + '") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ');\n')
- f.write ('\n')
-def apiDispatch(functionName, f):
- assert not isIntercepted(functionName)
-
- f.write (gencom.clang_off_spaces)
- if gencom.returnTypeDict[functionName] != 'void':
- f.write ('return ')
-
- paramList = gencom.paramDict[functionName]
- p0 = paramList[0][1]
- f.write('GetData(' + p0 + ').dispatch.' + functionName[2:] + '(' + ', '.join(i[1] for i in paramList) + ');\n')
+ for cmd in gencom.command_list:
+ if gencom.is_device_dispatched(cmd):
+ if _is_intercepted(cmd) or cmd == 'vkGetDeviceProcAddr':
+ f.write(gencom.indent(1) + 'if (strcmp(pName, "' + cmd +
+ '") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' +
+ gencom.base_name(cmd) + ');\n')
+ f.write('\n')
-def api_gencpp():
- genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','api_gen.cpp')
- header = """#include <log/log.h>
+def _api_dispatch(cmd, f):
+ assert not _is_intercepted(cmd)
+
+ f.write(gencom.indent(1))
+ if gencom.return_type_dict[cmd] != 'void':
+ f.write('return ')
+
+ param_list = gencom.param_dict[cmd]
+ handle = param_list[0][1]
+ f.write('GetData(' + handle + ').dispatch.' + gencom.base_name(cmd) +
+ '(' + ', '.join(i[1] for i in param_list) + ');\n')
+
+
+def gen_cpp():
+ genfile = os.path.join(os.path.dirname(__file__),
+ '..', 'libvulkan', 'api_gen.cpp')
+
+ with open(genfile, 'w') as f:
+ f.write(gencom.copyright_and_warning(2016))
+
+ f.write("""\
+#include <log/log.h>
#include <string.h>
#include <algorithm>
@@ -247,80 +252,106 @@
namespace vulkan {
namespace api {
-"""
- with open(genfile, 'w') as f:
- f.write (gencom.copyright)
- f.write (gencom.warning)
- f.write ("""#include <log/log.h>
-#include <string.h>
+#define UNLIKELY(expr) __builtin_expect((expr), 0)
-#include <algorithm>
+#define INIT_PROC(required, obj, proc) \\
+ do { \\
+ data.dispatch.proc = \\
+ reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\
+ if (UNLIKELY(required && !data.dispatch.proc)) { \\
+ ALOGE("missing " #obj " proc: vk" #proc); \\
+ success = false; \\
+ } \\
+ } while (0)
-// to catch mismatches between vulkan.h and this file
-#undef VK_NO_PROTOTYPES
-#include "api.h"
+// Exported extension functions may be invoked even when their extensions
+// are disabled. Dispatch to stubs when that happens.
+#define INIT_PROC_EXT(ext, required, obj, proc) \\
+ do { \\
+ if (extensions[driver::ProcHook::ext]) \\
+ INIT_PROC(required, obj, proc); \\
+ else \\
+ data.dispatch.proc = disabled##proc; \\
+ } while (0)
-namespace vulkan {
-namespace api {\n\n""")
- defineInitProc('dispatch',f)
- defineInitProcExt(f)
- f.write ('namespace {\n\n')
- gencom.clang_off(f,0)
- f.write ('\n')
- for cmds in gencom.allCommandsList:
- defineExtensionStub(cmds,f)
- gencom.clang_on(f,0)
- f.write ('\n} // namespace\n\n')
- f.write ("""bool InitDispatchTable(
+namespace {
+
+// clang-format off\n\n""")
+
+ for cmd in gencom.command_list:
+ _define_extension_stub(cmd, f)
+
+ f.write("""\
+// clang-format on
+
+} // namespace
+
+bool InitDispatchTable(
VkInstance instance,
PFN_vkGetInstanceProcAddr get_proc,
const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions) {
auto& data = GetData(instance);
- bool success = true;\n\n""")
- gencom.clang_off(f,1)
- for cmds in gencom.allCommandsList:
- if gencom.isInstanceDispatchTableEntry(cmds):
- gencom.initProc(cmds, f)
- gencom.clang_on(f,1)
- f.write ('\n')
- f.write (' return success;\n}\n\n')
- f.write ("""bool InitDispatchTable(
+ bool success = true;
+
+ // clang-format off\n""")
+
+ for cmd in gencom.command_list:
+ if gencom.is_instance_dispatch_table_entry(cmd):
+ gencom.init_proc(cmd, f)
+
+ f.write("""\
+ // clang-format on
+
+ return success;
+}
+
+bool InitDispatchTable(
VkDevice dev,
PFN_vkGetDeviceProcAddr get_proc,
const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions) {
auto& data = GetData(dev);
- bool success = true;\n\n""")
+ bool success = true;
- gencom.clang_off(f,1)
- for cmds in gencom.allCommandsList:
- if gencom.isDeviceDispatchTableEntry(cmds):
- gencom.initProc(cmds, f)
- gencom.clang_on(f,1)
- f.write ('\n')
- f.write (' return success;\n}\n\n')
+ // clang-format off\n""")
- gencom.clang_off(f,0)
+ for cmd in gencom.command_list:
+ if gencom.is_device_dispatch_table_entry(cmd):
+ gencom.init_proc(cmd, f)
- f.write ('\nnamespace {\n\n')
- f.write('// forward declarations needed by GetInstanceProcAddr and GetDeviceProcAddr\n')
- for cmds in gencom.allCommandsList:
- if gencom.isFunctionExported(cmds) and not isIntercepted(cmds):
- paramList = [''.join(i) for i in gencom.paramDict[cmds]]
- f.write ('VKAPI_ATTR '+gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' + ', '.join(paramList) + ');\n')
+ f.write("""\
+ // clang-format on
- f.write ('\n')
+ return success;
+}
- for cmds in gencom.allCommandsList:
- if gencom.isFunctionExported(cmds) and not isIntercepted(cmds):
- paramList = [''.join(i) for i in gencom.paramDict[cmds]]
- f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' + ', '.join(paramList) + ') {\n')
- if cmds == 'vkGetInstanceProcAddr':
- interceptInstanceProcAddr(cmds, f)
- elif cmds == 'vkGetDeviceProcAddr':
- interceptDeviceProcAddr(cmds, f)
- apiDispatch(cmds, f)
+// clang-format off
+
+namespace {
+
+// forward declarations needed by GetInstanceProcAddr and GetDeviceProcAddr
+""")
+
+ for cmd in gencom.command_list:
+ if gencom.is_function_exported(cmd) and not _is_intercepted(cmd):
+ param_list = [''.join(i) for i in gencom.param_dict[cmd]]
+ f.write('VKAPI_ATTR ' + gencom.return_type_dict[cmd] + ' ' +
+ gencom.base_name(cmd) + '(' + ', '.join(param_list) + ');\n')
+
+ f.write('\n')
+ for cmd in gencom.command_list:
+ if gencom.is_function_exported(cmd) and not _is_intercepted(cmd):
+ param_list = [''.join(i) for i in gencom.param_dict[cmd]]
+ f.write('VKAPI_ATTR ' + gencom.return_type_dict[cmd] + ' ' +
+ gencom.base_name(cmd) + '(' + ', '.join(param_list) + ') {\n')
+ if cmd == 'vkGetInstanceProcAddr':
+ _intercept_instance_proc_addr(f)
+ elif cmd == 'vkGetDeviceProcAddr':
+ _intercept_device_proc_addr(f)
+ _api_dispatch(cmd, f)
f.write('}\n\n')
- f.write ("""\n} // anonymous namespace
+
+ f.write("""
+} // anonymous namespace
// clang-format on
@@ -329,18 +360,19 @@
// clang-format off\n\n""")
- for cmds in gencom.allCommandsList:
- if gencom.isFunctionExported(cmds):
- paramList = [''.join(i) for i in gencom.paramDict[cmds]]
- f.write ('__attribute__((visibility("default")))\n')
- f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds + '(' + ', '.join(paramList) + ') {\n')
- f.write (gencom.clang_off_spaces)
- if gencom.returnTypeDict[cmds] != 'void':
- f.write ('return ')
- paramList = gencom.paramDict[cmds]
- f.write ('vulkan::api::' + cmds[2:] + '(' + ', '.join(i[1] for i in paramList) + ');\n')
- f.write ('}\n\n')
+ for cmd in gencom.command_list:
+ if gencom.is_function_exported(cmd):
+ param_list = [''.join(i) for i in gencom.param_dict[cmd]]
+ f.write('__attribute__((visibility("default")))\n')
+ f.write('VKAPI_ATTR ' + gencom.return_type_dict[cmd] + ' ' +
+ cmd + '(' + ', '.join(param_list) + ') {\n')
+ f.write(gencom.indent(1))
+ if gencom.return_type_dict[cmd] != 'void':
+ f.write('return ')
+ param_list = gencom.param_dict[cmd]
+ f.write('vulkan::api::' + gencom.base_name(cmd) +
+ '(' + ', '.join(i[1] for i in param_list) + ');\n}\n\n')
- gencom.clang_on(f, 0)
+ f.write('// clang-format on\n')
f.close()
- gencom.runClangFormat(genfile)
+ gencom.run_clang_format(genfile)
diff --git a/vulkan/scripts/code_generator.py b/vulkan/scripts/code_generator.py
index 39fedf4..378a9c0 100755
--- a/vulkan/scripts/code_generator.py
+++ b/vulkan/scripts/code_generator.py
@@ -17,16 +17,16 @@
# This script provides the main function for generating
# vulkan framework directly from the vulkan registry (vk.xml).
-import generator_common as gencom
-import api_generator as apigen
-import driver_generator as drivergen
-import null_generator as nullgen
+import api_generator
+import driver_generator
+import generator_common
+import null_generator
if __name__ == '__main__':
- gencom.parseVulkanRegistry()
- apigen.api_genh()
- apigen.api_gencpp()
- drivergen.driver_genh()
- drivergen.driver_gencpp()
- nullgen.null_driver_genh()
- nullgen.null_driver_gencpp()
+ generator_common.parse_vulkan_registry()
+ api_generator.gen_h()
+ api_generator.gen_cpp()
+ driver_generator.gen_h()
+ driver_generator.gen_cpp()
+ null_generator.gen_h()
+ null_generator.gen_cpp()
diff --git a/vulkan/scripts/driver_generator.py b/vulkan/scripts/driver_generator.py
index ef36f8c..5fff83e 100644
--- a/vulkan/scripts/driver_generator.py
+++ b/vulkan/scripts/driver_generator.py
@@ -17,41 +17,147 @@
# This script provides the functions for generating the
# vulkan driver framework directly from the vulkan registry (vk.xml).
-import generator_common as gencom
import os
+import generator_common as gencom
-interceptedExtensions = [
- 'VK_ANDROID_native_buffer',
- 'VK_EXT_debug_report',
- 'VK_EXT_hdr_metadata',
- 'VK_EXT_swapchain_colorspace',
- 'VK_GOOGLE_display_timing',
- 'VK_KHR_android_surface',
- 'VK_KHR_incremental_present',
- 'VK_KHR_shared_presentable_image',
- 'VK_KHR_surface',
- 'VK_KHR_swapchain',
- 'VK_KHR_get_surface_capabilities2'
+_INTERCEPTED_EXTENSIONS = [
+ 'VK_ANDROID_native_buffer',
+ 'VK_EXT_debug_report',
+ 'VK_EXT_hdr_metadata',
+ 'VK_EXT_swapchain_colorspace',
+ 'VK_GOOGLE_display_timing',
+ 'VK_KHR_android_surface',
+ 'VK_KHR_get_surface_capabilities2',
+ 'VK_KHR_incremental_present',
+ 'VK_KHR_shared_presentable_image',
+ 'VK_KHR_surface',
+ 'VK_KHR_swapchain',
]
-knownExtensions = interceptedExtensions + [
- 'VK_KHR_get_physical_device_properties2',
- 'VK_ANDROID_external_memory_android_hardware_buffer',
- 'VK_KHR_bind_memory2'
+_KNOWN_EXTENSIONS = _INTERCEPTED_EXTENSIONS + [
+ 'VK_ANDROID_external_memory_android_hardware_buffer',
+ 'VK_KHR_bind_memory2',
+ 'VK_KHR_get_physical_device_properties2',
]
-def defineProcHookType(f):
- f.write ("""struct ProcHook {
+_NEEDED_COMMANDS = [
+ # Create functions of dispatchable objects
+ 'vkCreateDevice',
+ 'vkGetDeviceQueue',
+ 'vkGetDeviceQueue2',
+ 'vkAllocateCommandBuffers',
+
+ # Destroy functions of dispatchable objects
+ 'vkDestroyInstance',
+ 'vkDestroyDevice',
+
+ # Enumeration of extensions
+ 'vkEnumerateDeviceExtensionProperties',
+
+ # We cache physical devices in loader.cpp
+ 'vkEnumeratePhysicalDevices',
+ 'vkEnumeratePhysicalDeviceGroups',
+
+ 'vkGetInstanceProcAddr',
+ 'vkGetDeviceProcAddr',
+
+ 'vkQueueSubmit',
+
+ # VK_KHR_swapchain->VK_ANDROID_native_buffer translation
+ 'vkCreateImage',
+ 'vkDestroyImage',
+
+ 'vkGetPhysicalDeviceProperties',
+ 'vkGetPhysicalDeviceProperties2',
+ 'vkGetPhysicalDeviceProperties2KHR',
+
+ # VK_KHR_swapchain v69 requirement
+ 'vkBindImageMemory2',
+ 'vkBindImageMemory2KHR',
+]
+
+_INTERCEPTED_COMMANDS = [
+ # Create functions of dispatchable objects
+ 'vkCreateInstance',
+ 'vkCreateDevice',
+ 'vkEnumeratePhysicalDevices',
+ 'vkEnumeratePhysicalDeviceGroups',
+ 'vkGetDeviceQueue',
+ 'vkGetDeviceQueue2',
+ 'vkAllocateCommandBuffers',
+
+ # Destroy functions of dispatchable objects
+ 'vkDestroyInstance',
+ 'vkDestroyDevice',
+
+ # Enumeration of extensions
+ 'vkEnumerateInstanceExtensionProperties',
+ 'vkEnumerateDeviceExtensionProperties',
+
+ 'vkGetInstanceProcAddr',
+ 'vkGetDeviceProcAddr',
+
+ 'vkQueueSubmit',
+
+ # VK_KHR_swapchain v69 requirement
+ 'vkBindImageMemory2',
+ 'vkBindImageMemory2KHR',
+]
+
+
+def _is_driver_table_entry(cmd):
+ if gencom.is_function_supported(cmd):
+ if cmd in _NEEDED_COMMANDS:
+ return True
+ if cmd in gencom.extension_dict:
+ if (gencom.extension_dict[cmd] == 'VK_ANDROID_native_buffer' or
+ gencom.extension_dict[cmd] == 'VK_EXT_debug_report'):
+ return True
+ return False
+
+
+def _is_instance_driver_table_entry(cmd):
+ return (_is_driver_table_entry(cmd) and
+ gencom.is_instance_dispatched(cmd))
+
+
+def _is_device_driver_table_entry(cmd):
+ return (_is_driver_table_entry(cmd) and
+ gencom.is_device_dispatched(cmd))
+
+
+def gen_h():
+ genfile = os.path.join(os.path.dirname(__file__),
+ '..', 'libvulkan', 'driver_gen.h')
+
+ with open(genfile, 'w') as f:
+ f.write(gencom.copyright_and_warning(2016))
+
+ f.write("""\
+#ifndef LIBVULKAN_DRIVER_GEN_H
+#define LIBVULKAN_DRIVER_GEN_H
+
+#include <vulkan/vk_android_native_buffer.h>
+#include <vulkan/vulkan.h>
+
+#include <bitset>
+
+namespace vulkan {
+namespace driver {
+
+struct ProcHook {
enum Type {
GLOBAL,
INSTANCE,
DEVICE,
};
enum Extension {\n""")
- for exts in knownExtensions:
- f.write (gencom.clang_off_spaces*2 + exts[3:] + ',\n')
- f.write ('\n')
- f.write (gencom.clang_off_spaces*2 + """EXTENSION_CORE, // valid bit
+
+ for exts in _KNOWN_EXTENSIONS:
+ f.write(gencom.indent(2) + exts[3:] + ',\n')
+
+ f.write("""
+ EXTENSION_CORE, // valid bit
EXTENSION_COUNT,
EXTENSION_UNKNOWN,
};
@@ -62,99 +168,33 @@
PFN_vkVoidFunction proc;
PFN_vkVoidFunction checked_proc; // always nullptr for non-device hooks
-};\n\n""")
+};
-def isExtensionIntercepted(extensionName):
- if extensionName in interceptedExtensions:
- return True
- return False
+struct InstanceDriverTable {
+ // clang-format off\n""")
-def isDriverTableEntry(functionName):
- switchCase = {
- # Create functions of dispatchable objects
- 'vkCreateDevice' : True,
- 'vkGetDeviceQueue' : True,
- 'vkGetDeviceQueue2' : True,
- 'vkAllocateCommandBuffers' : True,
+ for cmd in gencom.command_list:
+ if _is_instance_driver_table_entry(cmd):
+ f.write(gencom.indent(1) + 'PFN_' + cmd + ' ' +
+ gencom.base_name(cmd) + ';\n')
- # Destroy functions of dispatchable objects
- 'vkDestroyInstance' : True,
- 'vkDestroyDevice' : True,
+ f.write("""\
+ // clang-format on
+};
- # Enumeration of extensions
- 'vkEnumerateDeviceExtensionProperties' : True,
+struct DeviceDriverTable {
+ // clang-format off\n""")
- # We cache physical devices in loader.cpp
- 'vkEnumeratePhysicalDevices' : True,
- 'vkEnumeratePhysicalDeviceGroups' : True,
+ for cmd in gencom.command_list:
+ if _is_device_driver_table_entry(cmd):
+ f.write(gencom.indent(1) + 'PFN_' + cmd + ' ' +
+ gencom.base_name(cmd) + ';\n')
- 'vkGetInstanceProcAddr' : True,
- 'vkGetDeviceProcAddr' : True,
+ f.write("""\
+ // clang-format on
+};
- 'vkQueueSubmit' : True,
-
- # VK_KHR_swapchain->VK_ANDROID_native_buffer translation
- 'vkCreateImage' : True,
- 'vkDestroyImage' : True,
-
- 'vkGetPhysicalDeviceProperties' : True,
- 'vkGetPhysicalDeviceProperties2' : True,
- 'vkGetPhysicalDeviceProperties2KHR' : True,
-
- # VK_KHR_swapchain v69 requirement
- 'vkBindImageMemory2' : True,
- 'vkBindImageMemory2KHR' : True
- }
- if gencom.isFunctionSupported(functionName):
- if functionName in switchCase:
- return True
- if functionName in gencom.extensionsDict:
- if gencom.extensionsDict[functionName] == 'VK_ANDROID_native_buffer' or gencom.extensionsDict[functionName] == 'VK_EXT_debug_report':
- return True
- return False
-
-def isInstanceDriverTableEntry(functionName):
- if isDriverTableEntry(functionName) and gencom.isInstanceDispatched(functionName):
- return True
- return False
-
-def isDeviceDriverTableEntry(functionName):
- if isDriverTableEntry(functionName) and gencom.isDeviceDispatched(functionName):
- return True
- return False
-
-def driver_genh():
- header = """#ifndef LIBVULKAN_DRIVER_GEN_H
-#define LIBVULKAN_DRIVER_GEN_H
-
-#include <vulkan/vk_android_native_buffer.h>
-#include <vulkan/vulkan.h>
-
-#include <bitset>
-
-namespace vulkan {
-namespace driver {\n\n"""
- genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','driver_gen.h')
- with open(genfile, 'w') as f:
- f.write (gencom.copyright)
- f.write (gencom.warning)
- f.write (header)
- defineProcHookType(f)
- f.write ('struct InstanceDriverTable {\n')
- gencom.clang_off(f, 1)
- for cmds in gencom.allCommandsList:
- if isInstanceDriverTableEntry(cmds):
- f.write (gencom.clang_off_spaces + 'PFN_' + cmds + ' ' + cmds[2:] + ';\n')
- gencom.clang_on(f, 1)
- f.write ('};\n\n')
- f.write ('struct DeviceDriverTable {\n')
- gencom.clang_off(f,1)
- for cmds in gencom.allCommandsList:
- if isDeviceDriverTableEntry(cmds):
- f.write (gencom.clang_off_spaces + 'PFN_' + cmds + ' ' + cmds[2:] + ';\n')
- gencom.clang_on(f,1)
- f.write ('};\n\n')
- f.write ("""const ProcHook* GetProcHook(const char* name);
+const ProcHook* GetProcHook(const char* name);
ProcHook::Extension GetProcHookExtension(const char* name);
bool InitDriverTable(VkInstance instance,
@@ -168,148 +208,131 @@
} // namespace vulkan
#endif // LIBVULKAN_DRIVER_TABLE_H\n""")
+
f.close()
- gencom.runClangFormat(genfile)
+ gencom.run_clang_format(genfile)
-def isIntercepted(functionName):
- switchCase = {
- # Create functions of dispatchable objects
- 'vkCreateInstance' : True,
- 'vkCreateDevice' : True,
- 'vkEnumeratePhysicalDevices' : True,
- 'vkEnumeratePhysicalDeviceGroups' : True,
- 'vkGetDeviceQueue' : True,
- 'vkGetDeviceQueue2' : True,
- 'vkAllocateCommandBuffers' : True,
- # Destroy functions of dispatchable objects
- 'vkDestroyInstance' : True,
- 'vkDestroyDevice' : True,
+def _is_intercepted(cmd):
+ if gencom.is_function_supported(cmd):
+ if cmd in _INTERCEPTED_COMMANDS:
+ return True
- # Enumeration of extensions
- 'vkEnumerateInstanceExtensionProperties' : True,
- 'vkEnumerateDeviceExtensionProperties' : True,
-
- 'vkGetInstanceProcAddr' : True,
- 'vkGetDeviceProcAddr' : True,
-
- 'vkQueueSubmit' : True,
-
- # VK_KHR_swapchain v69 requirement
- 'vkBindImageMemory2' : True,
- 'vkBindImageMemory2KHR' : True
- }
- if gencom.isFunctionSupported(functionName):
- if functionName in switchCase:
- return switchCase[functionName]
-
- if functionName in gencom.extensionsDict:
- return isExtensionIntercepted(gencom.extensionsDict[functionName])
+ if cmd in gencom.extension_dict:
+ return gencom.extension_dict[cmd] in _INTERCEPTED_EXTENSIONS
return False
-def needProcHookStub(functionName):
- if isIntercepted(functionName) and gencom.isDeviceDispatched(functionName):
- if functionName in gencom.extensionsDict:
- if not gencom.isExtensionInternal(gencom.extensionsDict[functionName]):
+
+def _need_proc_hook_stub(cmd):
+ if _is_intercepted(cmd) and gencom.is_device_dispatched(cmd):
+ if cmd in gencom.extension_dict:
+ if not gencom.is_extension_internal(gencom.extension_dict[cmd]):
return True
return False
-def defineInitProc(name, f):
- f.write ('#define UNLIKELY(expr) __builtin_expect((expr), 0)\n')
- f.write ('\n')
- f.write ("""#define INIT_PROC(required, obj, proc) \\
- do { \\
- data.""" + name + """.proc = \\
- reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\
- if (UNLIKELY(required && !data.""" + name + """.proc)) { \\
- ALOGE("missing " #obj " proc: vk" #proc); \\
- success = false; \\
- } \\
- } while (0)\n\n""")
-def defineInitProcExt(f):
- f.write ("""#define INIT_PROC_EXT(ext, required, obj, proc) \\
- do { \\
- if (extensions[ProcHook::ext]) \\
- INIT_PROC(required, obj, proc); \\
- } while (0)\n\n""")
-
-def defineProcHookStub(functionName, f):
- if needProcHookStub(functionName):
- ext_name = gencom.extensionsDict[functionName]
- base_name = functionName[2:]
- paramList = [''.join(i) for i in gencom.paramDict[functionName]]
- p0 = gencom.paramDict[functionName][0][1]
- f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[functionName] + ' checked' + base_name + '(' + ', '.join(paramList) + ') {\n')
+def _define_proc_hook_stub(cmd, f):
+ if _need_proc_hook_stub(cmd):
+ return_type = gencom.return_type_dict[cmd]
+ ext_name = gencom.extension_dict[cmd]
ext_hook = 'ProcHook::' + ext_name[3:]
+ handle = gencom.param_dict[cmd][0][1]
+ param_types = ', '.join([''.join(i) for i in gencom.param_dict[cmd]])
+ param_names = ', '.join([''.join(i[1]) for i in gencom.param_dict[cmd]])
- f.write (gencom.clang_off_spaces + 'if (GetData(' + p0 + ').hook_extensions[' + ext_hook + ']) {\n')
- f.write (gencom.clang_off_spaces *2)
- if gencom.returnTypeDict[functionName] != 'void':
- f.write ('return ')
- paramNames = [''.join(i[1]) for i in gencom.paramDict[functionName]]
- f.write (base_name + '(' + ', '.join(paramNames) + ');\n')
- f.write (gencom.clang_off_spaces + '} else {\n')
- f.write (gencom.clang_off_spaces*2 + 'Logger(' + p0 + ').Err(' + p0 + ', \"' + ext_name + ' not enabled. ' + functionName + ' not executed.\");\n')
- if gencom.returnTypeDict[functionName] != 'void':
- f.write (gencom.clang_off_spaces*2 + 'return VK_SUCCESS;\n')
- f.write (gencom.clang_off_spaces + '}\n')
- f.write ('}\n\n')
+ f.write('VKAPI_ATTR ' + return_type + ' checked' + gencom.base_name(cmd) +
+ '(' + param_types + ') {\n')
+ f.write(gencom.indent(1) + 'if (GetData(' + handle + ').hook_extensions[' +
+ ext_hook + ']) {\n')
-def defineGlobalProcHook(functionName, f):
- base_name = functionName[2:]
- assert (functionName not in gencom.extensionsDict)
- f.write (gencom.clang_off_spaces + '{\n' + gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n' + gencom.clang_off_spaces*2)
- f.write ("""ProcHook::GLOBAL,
+ f.write(gencom.indent(2))
+ if gencom.return_type_dict[cmd] != 'void':
+ f.write('return ')
+ f.write(gencom.base_name(cmd) + '(' + param_names + ');\n')
+
+ f.write(gencom.indent(1) + '} else {\n')
+ f.write(gencom.indent(2) + 'Logger(' + handle + ').Err(' + handle + ', \"' +
+ ext_name + ' not enabled. ' + cmd + ' not executed.\");\n')
+ if gencom.return_type_dict[cmd] != 'void':
+ f.write(gencom.indent(2) + 'return VK_SUCCESS;\n')
+ f.write(gencom.indent(1) + '}\n}\n\n')
+
+
+def _define_global_proc_hook(cmd, f):
+ assert cmd not in gencom.extension_dict
+
+ f.write(gencom.indent(1) + '{\n')
+ f.write(gencom.indent(2) + '\"' + cmd + '\",\n')
+ f.write("""\
+ ProcHook::GLOBAL,
ProcHook::EXTENSION_CORE,
- reinterpret_cast<PFN_vkVoidFunction>(""" + base_name + """),
+ reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """),
nullptr,
},\n""")
-def defineInstanceProcHook(functionName, f):
- base_name = functionName[2:]
- f.write (gencom.clang_off_spaces + '{\n')
- f.write (gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n')
- f.write (gencom.clang_off_spaces*2 + 'ProcHook::INSTANCE,\n')
- if functionName in gencom.extensionsDict:
- ext_name = gencom.extensionsDict[functionName]
- f.write (gencom.clang_off_spaces*2 + 'ProcHook::' + ext_name[3:] + ',\n')
- if gencom.isExtensionInternal(ext_name):
- f.write (gencom.clang_off_spaces*2 + 'nullptr,\n' + gencom.clang_off_spaces*2 + 'nullptr,\n')
+def _define_instance_proc_hook(cmd, f):
+ f.write(gencom.indent(1) + '{\n')
+ f.write(gencom.indent(2) + '\"' + cmd + '\",\n')
+ f.write(gencom.indent(2) + 'ProcHook::INSTANCE,\n')
+
+ if cmd in gencom.extension_dict:
+ ext_name = gencom.extension_dict[cmd]
+ f.write(gencom.indent(2) + 'ProcHook::' + ext_name[3:] + ',\n')
+
+ if gencom.is_extension_internal(ext_name):
+ f.write("""\
+ nullptr,
+ nullptr,\n""")
else:
- f.write (gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(' + base_name + '),\n' + gencom.clang_off_spaces*2 + 'nullptr,\n')
-
+ f.write("""\
+ reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """),
+ nullptr,\n""")
else:
- f.write (gencom.clang_off_spaces*2 + """ProcHook::EXTENSION_CORE,
- reinterpret_cast<PFN_vkVoidFunction>(""" + base_name + """),
+ f.write("""\
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """),
nullptr,\n""")
- f.write (gencom.clang_off_spaces + '},\n')
+ f.write(gencom.indent(1) + '},\n')
-def defineDeviceProcHook(functionName, f):
- base_name = functionName[2:]
- f.write (gencom.clang_off_spaces + '{\n')
- f.write (gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n')
- f.write (gencom.clang_off_spaces*2 + 'ProcHook::DEVICE,\n')
- if functionName in gencom.extensionsDict:
- ext_name = gencom.extensionsDict[functionName]
- f.write (gencom.clang_off_spaces*2 + 'ProcHook::' + ext_name[3:] + ',\n')
- if gencom.isExtensionInternal(ext_name):
- f.write (gencom.clang_off_spaces*2 + 'nullptr,\n' + gencom.clang_off_spaces*2 + 'nullptr,\n')
+def _define_device_proc_hook(cmd, f):
+ f.write(gencom.indent(1) + '{\n')
+ f.write(gencom.indent(2) + '\"' + cmd + '\",\n')
+ f.write(gencom.indent(2) + 'ProcHook::DEVICE,\n')
+
+ if cmd in gencom.extension_dict:
+ ext_name = gencom.extension_dict[cmd]
+ f.write(gencom.indent(2) + 'ProcHook::' + ext_name[3:] + ',\n')
+
+ if gencom.is_extension_internal(ext_name):
+ f.write("""\
+ nullptr,
+ nullptr,\n""")
else:
- f.write (gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(' + base_name + '),\n' + gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(checked' + base_name + '),\n')
+ f.write("""\
+ reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """),
+ reinterpret_cast<PFN_vkVoidFunction>(checked""" +
+ gencom.base_name(cmd) + '),\n')
else:
- f.write (gencom.clang_off_spaces*2 + """ProcHook::EXTENSION_CORE,
- reinterpret_cast<PFN_vkVoidFunction>(""" + base_name + """),
+ f.write("""\
+ ProcHook::EXTENSION_CORE,
+ reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """),
nullptr,\n""")
- f.write (gencom.clang_off_spaces + '},\n')
+ f.write(gencom.indent(1) + '},\n')
-def driver_gencpp():
- header = """#include <log/log.h>
+
+def gen_cpp():
+ genfile = os.path.join(os.path.dirname(__file__),
+ '..', 'libvulkan', 'driver_gen.cpp')
+
+ with open(genfile, 'w') as f:
+ f.write(gencom.copyright_and_warning(2016))
+ f.write("""\
+#include <log/log.h>
#include <string.h>
#include <algorithm>
@@ -321,35 +344,34 @@
namespace {
-// clang-format off\n\n"""
+// clang-format off\n\n""")
- genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','driver_gen.cpp')
+ for cmd in gencom.command_list:
+ _define_proc_hook_stub(cmd, f)
- with open(genfile, 'w') as f:
- f.write (gencom.copyright)
- f.write (gencom.warning)
- f.write (header)
+ f.write("""\
+// clang-format on
- for cmds in gencom.allCommandsList:
- defineProcHookStub(cmds, f)
- gencom.clang_on(f, 0)
- f.write ('\n')
+const ProcHook g_proc_hooks[] = {
+ // clang-format off\n""")
- f.write ('const ProcHook g_proc_hooks[] = {\n')
- gencom.clang_off(f, 1)
- sortedCommandsList = sorted(gencom.allCommandsList)
- for cmds in sortedCommandsList:
- if isIntercepted(cmds):
- if gencom.isGloballyDispatched(cmds):
- defineGlobalProcHook(cmds, f)
- elif gencom.isInstanceDispatched(cmds):
- defineInstanceProcHook(cmds, f)
- elif gencom.isDeviceDispatched(cmds):
- defineDeviceProcHook(cmds, f)
- gencom.clang_on(f, 1)
- f.write ('};\n\n} // namespace\n\n')
+ sorted_command_list = sorted(gencom.command_list)
+ for cmd in sorted_command_list:
+ if _is_intercepted(cmd):
+ if gencom.is_globally_dispatched(cmd):
+ _define_global_proc_hook(cmd, f)
+ elif gencom.is_instance_dispatched(cmd):
+ _define_instance_proc_hook(cmd, f)
+ elif gencom.is_device_dispatched(cmd):
+ _define_device_proc_hook(cmd, f)
- f.write ("""const ProcHook* GetProcHook(const char* name) {
+ f.write("""\
+ // clang-format on
+};
+
+} // namespace
+
+const ProcHook* GetProcHook(const char* name) {
const auto& begin = g_proc_hooks;
const auto& end =
g_proc_hooks + sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
@@ -357,44 +379,76 @@
begin, end, name,
[](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
return (hook < end && strcmp(hook->name, name) == 0) ? hook : nullptr;
-}\n\n""")
+}
- f.write ('ProcHook::Extension GetProcHookExtension(const char* name) {\n')
- gencom.clang_off(f, 1)
- for exts in knownExtensions:
- f.write (gencom.clang_off_spaces + 'if (strcmp(name, \"' + exts + '\") == 0) return ProcHook::' + exts[3:] + ';\n')
- gencom.clang_on(f, 1)
- f.write (gencom.clang_off_spaces + 'return ProcHook::EXTENSION_UNKNOWN;\n')
- f.write ('}\n\n')
+ProcHook::Extension GetProcHookExtension(const char* name) {
+ // clang-format off\n""")
- defineInitProc('driver', f)
- defineInitProcExt(f)
+ for exts in _KNOWN_EXTENSIONS:
+ f.write(gencom.indent(1) + 'if (strcmp(name, \"' + exts +
+ '\") == 0) return ProcHook::' + exts[3:] + ';\n')
- f.write ("""bool InitDriverTable(VkInstance instance,
+ f.write("""\
+ // clang-format on
+ return ProcHook::EXTENSION_UNKNOWN;
+}
+
+#define UNLIKELY(expr) __builtin_expect((expr), 0)
+
+#define INIT_PROC(required, obj, proc) \\
+ do { \\
+ data.driver.proc = \\
+ reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\
+ if (UNLIKELY(required && !data.driver.proc)) { \\
+ ALOGE("missing " #obj " proc: vk" #proc); \\
+ success = false; \\
+ } \\
+ } while (0)
+
+#define INIT_PROC_EXT(ext, required, obj, proc) \\
+ do { \\
+ if (extensions[ProcHook::ext]) \\
+ INIT_PROC(required, obj, proc); \\
+ } while (0)
+
+bool InitDriverTable(VkInstance instance,
PFN_vkGetInstanceProcAddr get_proc,
const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) {
auto& data = GetData(instance);
- bool success = true;\n\n""")
- gencom.clang_off(f, 1)
- for cmds in gencom.allCommandsList:
- if isInstanceDriverTableEntry(cmds):
- gencom.initProc(cmds, f)
- gencom.clang_on(f, 1)
- f.write ('\n' + gencom.clang_off_spaces + 'return success;\n')
- f.write ('}\n\n')
+ bool success = true;
- f.write ("""bool InitDriverTable(VkDevice dev,
+ // clang-format off\n""")
+
+ for cmd in gencom.command_list:
+ if _is_instance_driver_table_entry(cmd):
+ gencom.init_proc(cmd, f)
+
+ f.write("""\
+ // clang-format on
+
+ return success;
+}
+
+bool InitDriverTable(VkDevice dev,
PFN_vkGetDeviceProcAddr get_proc,
const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) {
auto& data = GetData(dev);
- bool success = true;\n\n""")
- gencom.clang_off(f, 1)
- for cmds in gencom.allCommandsList:
- if isDeviceDriverTableEntry(cmds):
- gencom.initProc(cmds, f)
- gencom.clang_on(f, 1)
- f.write ('\n' + gencom.clang_off_spaces + 'return success;\n')
- f.write ('}\n\n} // namespace driver\n} // namespace vulkan\n\n')
- gencom.clang_on(f, 0)
+ bool success = true;
+
+ // clang-format off\n""")
+
+ for cmd in gencom.command_list:
+ if _is_device_driver_table_entry(cmd):
+ gencom.init_proc(cmd, f)
+
+ f.write("""\
+ // clang-format on
+
+ return success;
+}
+
+} // namespace driver
+} // namespace vulkan\n""")
+
f.close()
- gencom.runClangFormat(genfile)
+ gencom.run_clang_format(genfile)
diff --git a/vulkan/scripts/generator_common.py b/vulkan/scripts/generator_common.py
index fe9dab4..03993e2 100644
--- a/vulkan/scripts/generator_common.py
+++ b/vulkan/scripts/generator_common.py
@@ -17,10 +17,77 @@
# This script provides the common functions for generating the
# vulkan framework directly from the vulkan registry (vk.xml).
-from subprocess import check_call
+import os
+import subprocess
+import xml.etree.ElementTree as element_tree
-copyright = """/*
- * Copyright 2016 The Android Open Source Project
+_BLACKLISTED_EXTENSIONS = [
+ 'VK_EXT_acquire_xlib_display',
+ 'VK_EXT_direct_mode_display',
+ 'VK_EXT_display_control',
+ 'VK_EXT_display_surface_counter',
+ 'VK_EXT_full_screen_exclusive',
+ 'VK_EXT_headless_surface',
+ 'VK_EXT_metal_surface',
+ 'VK_FUCHSIA_imagepipe_surface',
+ 'VK_GGP_stream_descriptor_surface',
+ 'VK_KHR_display',
+ 'VK_KHR_display_swapchain',
+ 'VK_KHR_external_fence_win32',
+ 'VK_KHR_external_memory_win32',
+ 'VK_KHR_external_semaphore_win32',
+ 'VK_KHR_mir_surface',
+ 'VK_KHR_wayland_surface',
+ 'VK_KHR_win32_keyed_mutex',
+ 'VK_KHR_win32_surface',
+ 'VK_KHR_xcb_surface',
+ 'VK_KHR_xlib_surface',
+ 'VK_MVK_ios_surface',
+ 'VK_MVK_macos_surface',
+ 'VK_NN_vi_surface',
+ 'VK_NV_cooperative_matrix',
+ 'VK_NV_coverage_reduction_mode',
+ 'VK_NV_external_memory_win32',
+ 'VK_NV_win32_keyed_mutex',
+ 'VK_NVX_image_view_handle',
+]
+
+_EXPORTED_EXTENSIONS = [
+ 'VK_ANDROID_external_memory_android_hardware_buffer',
+ 'VK_KHR_android_surface',
+ 'VK_KHR_surface',
+ 'VK_KHR_swapchain',
+]
+
+_OPTIONAL_COMMANDS = [
+ 'vkGetSwapchainGrallocUsageANDROID',
+ 'vkGetSwapchainGrallocUsage2ANDROID',
+]
+
+_DISPATCH_TYPE_DICT = {
+ 'VkInstance ': 'Instance',
+ 'VkPhysicalDevice ': 'Instance',
+ 'VkDevice ': 'Device',
+ 'VkQueue ': 'Device',
+ 'VkCommandBuffer ': 'Device'
+}
+
+alias_dict = {}
+command_list = []
+extension_dict = {}
+param_dict = {}
+return_type_dict = {}
+version_dict = {}
+
+
+def indent(num):
+ return ' ' * num
+
+
+def copyright_and_warning(year):
+ return """\
+/*
+ * Copyright """ + str(year) + """ 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.
@@ -35,221 +102,168 @@
* limitations under the License.
*/
+// WARNING: This file is generated. See ../README.md for instructions.
+
"""
-warning = '// WARNING: This file is generated. See ../README.md for instructions.\n\n'
-blacklistedExtensions = [
- 'VK_KHR_display',
- 'VK_KHR_display_swapchain',
- 'VK_KHR_mir_surface',
- 'VK_KHR_xcb_surface',
- 'VK_KHR_xlib_surface',
- 'VK_KHR_wayland_surface',
- 'VK_KHR_win32_surface',
- 'VK_KHR_external_memory_win32',
- 'VK_KHR_win32_keyed_mutex',
- 'VK_KHR_external_semaphore_win32',
- 'VK_KHR_external_fence_win32',
- 'VK_EXT_acquire_xlib_display',
- 'VK_EXT_direct_mode_display',
- 'VK_EXT_display_surface_counter',
- 'VK_EXT_display_control',
- 'VK_FUCHSIA_imagepipe_surface',
- 'VK_MVK_ios_surface',
- 'VK_MVK_macos_surface',
- 'VK_NN_vi_surface',
- 'VK_NV_external_memory_win32',
- 'VK_NV_win32_keyed_mutex',
- 'VK_EXT_metal_surface', #not present in vulkan.api
- 'VK_NVX_image_view_handle', #not present in vulkan.api
- 'VK_NV_cooperative_matrix', #not present in vulkan.api
- 'VK_EXT_headless_surface', #not present in vulkan.api
- 'VK_GGP_stream_descriptor_surface', #not present in vulkan.api
- 'VK_NV_coverage_reduction_mode', #not present in vulkan.api
- 'VK_EXT_full_screen_exclusive' #not present in vulkan.api
-]
+def run_clang_format(args):
+ clang_call = ['clang-format', '--style', 'file', '-i', args]
+ subprocess.check_call(clang_call)
-exportedExtensions = [
- 'VK_KHR_surface',
- 'VK_KHR_swapchain',
- 'VK_KHR_android_surface',
- 'VK_ANDROID_external_memory_android_hardware_buffer'
-]
-def runClangFormat(args):
- clang_call = ["clang-format", "--style", "file", "-i", args]
- check_call (clang_call)
+def is_extension_internal(extension_name):
+ return extension_name == 'VK_ANDROID_native_buffer'
-def isExtensionInternal(extensionName):
- if extensionName == 'VK_ANDROID_native_buffer':
- return True
- return False
-def isFunctionSupported(functionName):
- if functionName not in extensionsDict:
+def base_name(cmd):
+ return cmd[2:]
+
+
+def is_function_supported(cmd):
+ if cmd not in extension_dict:
return True
else:
- if extensionsDict[functionName] not in blacklistedExtensions:
+ if extension_dict[cmd] not in _BLACKLISTED_EXTENSIONS:
return True
return False
-def isInstanceDispatched(functionName):
- return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Instance'
-def isDeviceDispatched(functionName):
- return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Device'
-
-def isGloballyDispatched(functionName):
- return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Global'
-
-def isExtensionExported(extensionName):
- if extensionName in exportedExtensions:
- return True
- return False
-
-def isFunctionExported(functionName):
- if isFunctionSupported(functionName):
- if functionName in extensionsDict:
- return isExtensionExported(extensionsDict[functionName])
- return True
- return False
-
-def getDispatchTableType(functionName):
- if functionName not in paramDict:
+def get_dispatch_table_type(cmd):
+ if cmd not in param_dict:
return None
- switchCase = {
- 'VkInstance ' : 'Instance',
- 'VkPhysicalDevice ' : 'Instance',
- 'VkDevice ' : 'Device',
- 'VkQueue ' : 'Device',
- 'VkCommandBuffer ' : 'Device'
- }
-
- if len(paramDict[functionName]) > 0:
- return switchCase.get(paramDict[functionName][0][0], 'Global')
+ if param_dict[cmd]:
+ return _DISPATCH_TYPE_DICT.get(param_dict[cmd][0][0], 'Global')
return 'Global'
-def isInstanceDispatchTableEntry(functionName):
- if functionName == 'vkEnumerateDeviceLayerProperties': # deprecated, unused internally - @dbd33bc
+
+def is_globally_dispatched(cmd):
+ return is_function_supported(cmd) and get_dispatch_table_type(cmd) == 'Global'
+
+
+def is_instance_dispatched(cmd):
+ return (is_function_supported(cmd) and
+ get_dispatch_table_type(cmd) == 'Instance')
+
+
+def is_device_dispatched(cmd):
+ return is_function_supported(cmd) and get_dispatch_table_type(cmd) == 'Device'
+
+
+def is_extension_exported(extension_name):
+ return extension_name in _EXPORTED_EXTENSIONS
+
+
+def is_function_exported(cmd):
+ if is_function_supported(cmd):
+ if cmd in extension_dict:
+ return is_extension_exported(extension_dict[cmd])
+ return True
+ return False
+
+
+def is_instance_dispatch_table_entry(cmd):
+ if cmd == 'vkEnumerateDeviceLayerProperties':
+ # deprecated, unused internally - @dbd33bc
return False
- if isFunctionExported(functionName) and isInstanceDispatched(functionName):
- return True
- return False
-
-def isDeviceDispatchTableEntry(functionName):
- if isFunctionExported(functionName) and isDeviceDispatched(functionName):
- return True
- return False
+ return is_function_exported(cmd) and is_instance_dispatched(cmd)
-def clang_on(f, indent):
- f.write (clang_off_spaces * indent + '// clang-format on\n')
+def is_device_dispatch_table_entry(cmd):
+ return is_function_exported(cmd) and is_device_dispatched(cmd)
-def clang_off(f, indent):
- f.write (clang_off_spaces * indent + '// clang-format off\n')
-clang_off_spaces = ' ' * 4
+def init_proc(name, f):
+ f.write(indent(1))
+ if name in extension_dict:
+ f.write('INIT_PROC_EXT(' + extension_dict[name][3:] + ', ')
+ else:
+ f.write('INIT_PROC(')
-parametersList = []
-paramDict = {}
-allCommandsList = []
-extensionsDict = {}
-returnTypeDict = {}
-versionDict = {}
-aliasDict = {}
+ if name in version_dict and version_dict[name] == 'VK_VERSION_1_1':
+ f.write('false, ')
+ elif name in _OPTIONAL_COMMANDS:
+ f.write('false, ')
+ else:
+ f.write('true, ')
-def parseVulkanRegistry():
- import xml.etree.ElementTree as ET
- import os
- vulkan_registry = os.path.join(os.path.dirname(__file__),'..','..','..','..','external','vulkan-headers','registry','vk.xml')
- tree = ET.parse(vulkan_registry)
+ if is_instance_dispatched(name):
+ f.write('instance, ')
+ else:
+ f.write('dev, ')
+
+ f.write(base_name(name) + ');\n')
+
+
+def parse_vulkan_registry():
+ registry = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..',
+ 'external', 'vulkan-headers', 'registry', 'vk.xml')
+ tree = element_tree.parse(registry)
root = tree.getroot()
for commands in root.iter('commands'):
for command in commands:
if command.tag == 'command':
- parametersList.clear()
+ parameter_list = []
protoset = False
- fnName = ""
- fnType = ""
- if command.get('alias') != None:
+ cmd_name = ''
+ cmd_type = ''
+ if command.get('alias') is not None:
alias = command.get('alias')
- fnName = command.get('name')
- aliasDict[fnName] = alias
- allCommandsList.append(fnName)
- paramDict[fnName] = paramDict[alias].copy()
- returnTypeDict[fnName] = returnTypeDict[alias]
+ cmd_name = command.get('name')
+ alias_dict[cmd_name] = alias
+ command_list.append(cmd_name)
+ param_dict[cmd_name] = param_dict[alias].copy()
+ return_type_dict[cmd_name] = return_type_dict[alias]
for params in command:
if params.tag == 'param':
- paramtype = ""
- if params.text != None and params.text.strip() != '':
- paramtype = params.text.strip() + ' '
- typeval = params.find('type')
- paramtype = paramtype + typeval.text
- if typeval.tail != None:
- paramtype += typeval.tail.strip() + ' '
+ param_type = ''
+ if params.text is not None and params.text.strip():
+ param_type = params.text.strip() + ' '
+ type_val = params.find('type')
+ param_type = param_type + type_val.text
+ if type_val.tail is not None:
+ param_type += type_val.tail.strip() + ' '
pname = params.find('name')
- paramname = pname.text
- if pname.tail != None and pname.tail.strip() != '':
- parametersList.append((paramtype, paramname, pname.tail.strip()))
+ param_name = pname.text
+ if pname.tail is not None and pname.tail.strip():
+ parameter_list.append(
+ (param_type, param_name, pname.tail.strip()))
else:
- parametersList.append((paramtype, paramname))
+ parameter_list.append((param_type, param_name))
if params.tag == 'proto':
for c in params:
if c.tag == 'type':
- fnType = c.text
+ cmd_type = c.text
if c.tag == 'name':
- fnName = c.text
+ cmd_name = c.text
protoset = True
- allCommandsList.append(fnName)
- returnTypeDict[fnName] = fnType
- if protoset == True:
- paramDict[fnName] = parametersList.copy()
+ command_list.append(cmd_name)
+ return_type_dict[cmd_name] = cmd_type
+ if protoset:
+ param_dict[cmd_name] = parameter_list.copy()
for exts in root.iter('extensions'):
for extension in exts:
- apiversion = ""
+ apiversion = ''
if extension.tag == 'extension':
extname = extension.get('name')
for req in extension:
- if req.get('feature') != None:
+ if req.get('feature') is not None:
apiversion = req.get('feature')
for commands in req:
if commands.tag == 'command':
- commandname = commands.get('name')
- if commandname not in extensionsDict:
- extensionsDict[commandname] = extname
- if apiversion != "":
- versionDict[commandname] = apiversion
+ cmd_name = commands.get('name')
+ if cmd_name not in extension_dict:
+ extension_dict[cmd_name] = extname
+ if apiversion:
+ version_dict[cmd_name] = apiversion
for feature in root.iter('feature'):
apiversion = feature.get('name')
for req in feature:
for command in req:
if command.tag == 'command':
- cmdName = command.get('name')
- if cmdName in allCommandsList:
- versionDict[cmdName] = apiversion
-
-
-def initProc(name, f):
- if name in extensionsDict:
- f.write (' INIT_PROC_EXT(' + extensionsDict[name][3:] + ', ')
- else:
- f.write (' INIT_PROC(')
-
- if name in versionDict and versionDict[name] == 'VK_VERSION_1_1':
- f.write('false, ')
- elif name == 'vkGetSwapchainGrallocUsageANDROID' or name == 'vkGetSwapchainGrallocUsage2ANDROID': # optional in vulkan.api
- f.write('false, ')
- else:
- f.write('true, ')
-
- if isInstanceDispatched(name):
- f.write('instance, ')
- else:
- f.write('dev, ')
-
- f.write(name[2:] + ');\n')
-
+ cmd_name = command.get('name')
+ if cmd_name in command_list:
+ version_dict[cmd_name] = apiversion
diff --git a/vulkan/scripts/null_generator.py b/vulkan/scripts/null_generator.py
index ee8762e..2a99a1d 100644
--- a/vulkan/scripts/null_generator.py
+++ b/vulkan/scripts/null_generator.py
@@ -17,45 +17,31 @@
# This script provides the functions for generating the null driver
# framework directly from the vulkan registry (vk.xml).
-import generator_common as gencom
import os
+import generator_common as gencom
-copyright = """/*
- * Copyright 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+_DRIVER_EXTENSION_DICT = {
+ 'VK_ANDROID_native_buffer',
+ 'VK_EXT_debug_report',
+ 'VK_KHR_get_physical_device_properties2'
+}
-"""
-def isDriverExtension(extensionName):
- switchCase = {
- 'VK_ANDROID_native_buffer' : True,
- 'VK_EXT_debug_report' : True,
- 'VK_KHR_get_physical_device_properties2' : True
- }
-
- if extensionName in switchCase:
- return switchCase[extensionName]
- return False
-
-def isDriverFunction(functionName):
- if functionName in gencom.extensionsDict:
- return isDriverExtension(gencom.extensionsDict[functionName])
+def _is_driver_function(cmd):
+ if cmd in gencom.extension_dict:
+ return gencom.extension_dict[cmd] in _DRIVER_EXTENSION_DICT
return True
-def null_driver_genh():
- header = """#ifndef NULLDRV_NULL_DRIVER_H
+
+def gen_h():
+ genfile = os.path.join(os.path.dirname(__file__),
+ '..', 'nulldrv', 'null_driver_gen.h')
+
+ with open(genfile, 'w') as f:
+ f.write(gencom.copyright_and_warning(2015))
+
+ f.write("""\
+#ifndef NULLDRV_NULL_DRIVER_H
#define NULLDRV_NULL_DRIVER_H 1
#include <vulkan/vk_android_native_buffer.h>
@@ -66,30 +52,34 @@
PFN_vkVoidFunction GetGlobalProcAddr(const char* name);
PFN_vkVoidFunction GetInstanceProcAddr(const char* name);
-"""
- genfile = os.path.join(os.path.dirname(__file__),'..','nulldrv','null_driver_gen.h')
- with open(genfile, 'w') as f:
- f.write (copyright)
- f.write (gencom.warning)
- f.write (header)
- gencom.clang_off(f,0)
+// clang-format off\n""")
- for cmds in gencom.allCommandsList:
- if isDriverFunction(cmds):
- paramList = [''.join(i) for i in gencom.paramDict[cmds]]
- f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' +', '.join(paramList) + ');\n')
- f.write ("""VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
-VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
-VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);\n""")
- gencom.clang_on(f,0)
+ for cmd in gencom.command_list:
+ if _is_driver_function(cmd):
+ param_list = [''.join(i) for i in gencom.param_dict[cmd]]
+ f.write('VKAPI_ATTR ' + gencom.return_type_dict[cmd] + ' ' +
+ gencom.base_name(cmd) + '(' + ', '.join(param_list) + ');\n')
- f.write ('\n} // namespace null_driver\n')
- f.write ('\n#endif // NULLDRV_NULL_DRIVER_H\n')
+ f.write("""\
+// clang-format on
+
+} // namespace null_driver
+
+#endif // NULLDRV_NULL_DRIVER_H\n""")
+
f.close()
- gencom.runClangFormat(genfile)
+ gencom.run_clang_format(genfile)
-def null_driver_gencpp():
- header = """#include <algorithm>
+
+def gen_cpp():
+ genfile = os.path.join(os.path.dirname(__file__),
+ '..', 'nulldrv', 'null_driver_gen.cpp')
+
+ with open(genfile, 'w') as f:
+ f.write(gencom.copyright_and_warning(2015))
+
+ f.write("""\
+#include <algorithm>
#include "null_driver_gen.h"
@@ -119,30 +109,36 @@
}
const NameProc kGlobalProcs[] = {
-"""
- genfile = os.path.join(os.path.dirname(__file__),'..','nulldrv','null_driver_gen.cpp')
- with open(genfile, 'w') as f:
- f.write (copyright)
- f.write (gencom.warning)
- f.write (header)
- gencom.clang_off(f,1)
+ // clang-format off\n""")
- sortedCommandsList = sorted(gencom.allCommandsList)
- for cmds in sortedCommandsList:
- if isDriverFunction(cmds) and gencom.getDispatchTableType(cmds) == 'Global':
- f.write (gencom.clang_off_spaces + '{\"' + cmds + '\", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_' + cmds + '>(' + cmds[2:] + '))},\n')
- gencom.clang_on(f,1)
- f.write ('};\n\n')
+ sorted_command_list = sorted(gencom.command_list)
+ for cmd in sorted_command_list:
+ if (_is_driver_function(cmd) and
+ gencom.get_dispatch_table_type(cmd) == 'Global'):
+ f.write(gencom.indent(1) + '{\"' + cmd +
+ '\", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_' +
+ cmd + '>(' + gencom.base_name(cmd) + '))},\n')
- f.write ('const NameProc kInstanceProcs[] = {\n')
- gencom.clang_off(f,1)
- for cmds in sortedCommandsList:
- if isDriverFunction(cmds):
- f.write (gencom.clang_off_spaces + '{\"' + cmds + '\", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_' + cmds + '>(' + cmds[2:] + '))},\n')
- gencom.clang_on(f,1)
- f.write ('};\n\n} // namespace\n\n')
+ f.write("""\
+ // clang-format on
+};
- f.write ("""namespace null_driver {
+const NameProc kInstanceProcs[] = {
+ // clang-format off\n""")
+
+ for cmd in sorted_command_list:
+ if _is_driver_function(cmd):
+ f.write(gencom.indent(1) + '{\"' + cmd +
+ '\", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_' +
+ cmd + '>(' + gencom.base_name(cmd) + '))},\n')
+
+ f.write("""\
+ // clang-format on
+};
+
+} // namespace
+
+namespace null_driver {
PFN_vkVoidFunction GetGlobalProcAddr(const char* name) {
return Lookup(name, kGlobalProcs);
@@ -153,6 +149,6 @@
}
} // namespace null_driver\n""")
- f.close()
- gencom.runClangFormat(genfile)
+ f.close()
+ gencom.run_clang_format(genfile)