Merge "libpdx_uds: Always create channel sockets in the server process" into oc-dev
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index ed53af1..f8e0ad5 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -450,8 +450,8 @@
return false;
}
- char buf[100];
- ssize_t n = read(fd, buf, 99);
+ char buf[4097];
+ ssize_t n = read(fd, buf, 4096);
close(fd);
if (n == -1) {
fprintf(stderr, "error reading %s: %s (%d)\n", k_traceClockPath,
@@ -475,38 +475,13 @@
return strcmp(mode, start) == 0;
}
-// Read the trace_clock sysfs file and return true if it contains the requested
-// value. The trace_clock file format is:
-// local [global] counter uptime perf
-static bool traceClockContains(const char *mode)
-{
- int fd = open((g_traceFolder + k_traceClockPath).c_str(), O_RDONLY);
- if (fd == -1) {
- fprintf(stderr, "error opening %s: %s (%d)\n", k_traceClockPath,
- strerror(errno), errno);
- return false;
- }
-
- char buf[100];
- ssize_t n = read(fd, buf, 99);
- close(fd);
- if (n == -1) {
- fprintf(stderr, "error reading %s: %s (%d)\n", k_traceClockPath,
- strerror(errno), errno);
- return false;
- }
- buf[n] = '\0';
-
- return strstr(buf, mode) != NULL;
-}
-
-// Set the clock to the best available option while tracing. Use 'boot' if it's
-// available; otherwise, use 'mono'.
+// Enable or disable the kernel's use of the global clock. Disabling the global
+// clock will result in the kernel using a per-CPU local clock.
// Any write to the trace_clock sysfs file will reset the buffer, so only
// update it if the requested value is not the current value.
-static bool setClock()
+static bool setGlobalClockEnable(bool enable)
{
- const char* clock = traceClockContains("boot") ? "boot" : "mono";
+ const char *clock = enable ? "global" : "local";
if (isTraceClock(clock)) {
return true;
@@ -808,7 +783,7 @@
ok &= setCategoriesEnableFromFile(g_categoriesFile);
ok &= setTraceOverwriteEnable(g_traceOverwrite);
ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
- ok &= setClock();
+ ok &= setGlobalClockEnable(true);
ok &= setPrintTgidEnableIfPresent(true);
ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
@@ -884,6 +859,7 @@
// Set the options back to their defaults.
setTraceOverwriteEnable(true);
setTraceBufferSizeKB(1);
+ setGlobalClockEnable(false);
setPrintTgidEnableIfPresent(false);
setKernelTraceFuncs(NULL);
}
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index cfd2659..cef41be 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -124,10 +124,6 @@
write /sys/kernel/debug/tracing/tracing_on 0
write /sys/kernel/tracing/tracing_on 0
- # Set the trace clock to boot if it exists, falling back to mono if not.
- write /d/tracing/trace_clock mono
- write /d/tracing/trace_clock boot
-
# Allow only the shell group to read and truncate the kernel trace.
chown root shell /sys/kernel/debug/tracing/trace
chown root shell /sys/kernel/tracing/trace
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 5dad511..f84d86d 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -998,13 +998,8 @@
for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
- if (true) {
- // TODO: temporary disabled because /data/misc/bluetooth/logs/btsnoop_hci.log can be huge
- MYLOGD("Skipping /data/misc/bluetooth/logs");
- } else {
- /* Dump Bluetooth HCI logs */
- ds.AddDir("/data/misc/bluetooth/logs", true);
- }
+ /* Dump Bluetooth HCI logs */
+ ds.AddDir("/data/misc/bluetooth/logs", true);
if (!ds.do_early_screenshot_) {
MYLOGI("taking late screenshot\n");
diff --git a/cmds/installd/CacheItem.cpp b/cmds/installd/CacheItem.cpp
index 17eb7ff..515f915 100644
--- a/cmds/installd/CacheItem.cpp
+++ b/cmds/installd/CacheItem.cpp
@@ -67,6 +67,7 @@
}
int CacheItem::purge() {
+ int res = 0;
auto path = buildPath();
if (directory) {
FTS *fts;
@@ -88,29 +89,47 @@
break;
case FTS_F:
if (p->fts_parent->fts_number) {
- truncate(p->fts_path, 0);
+ if (truncate(p->fts_path, 0) != 0) {
+ PLOG(WARNING) << "Failed to truncate " << p->fts_path;
+ res = -1;
+ }
} else {
- unlink(p->fts_path);
+ if (unlink(p->fts_path) != 0) {
+ PLOG(WARNING) << "Failed to unlink " << p->fts_path;
+ res = -1;
+ }
}
break;
case FTS_DEFAULT:
case FTS_SL:
case FTS_SLNONE:
- unlink(p->fts_path);
+ if (unlink(p->fts_path) != 0) {
+ PLOG(WARNING) << "Failed to unlink " << p->fts_path;
+ res = -1;
+ }
break;
case FTS_DP:
- rmdir(p->fts_path);
+ if (rmdir(p->fts_path) != 0) {
+ PLOG(WARNING) << "Failed to rmdir " << p->fts_path;
+ res = -1;
+ }
break;
}
}
- return 0;
} else {
if (tombstone) {
- return truncate(path.c_str(), 0);
+ if (truncate(path.c_str(), 0) != 0) {
+ PLOG(WARNING) << "Failed to truncate " << path;
+ res = -1;
+ }
} else {
- return unlink(path.c_str());
+ if (unlink(path.c_str()) != 0) {
+ PLOG(WARNING) << "Failed to unlink " << path;
+ res = -1;
+ }
}
}
+ return res;
}
} // namespace installd
diff --git a/cmds/installd/CacheTracker.cpp b/cmds/installd/CacheTracker.cpp
index 4bfc834..e293948 100644
--- a/cmds/installd/CacheTracker.cpp
+++ b/cmds/installd/CacheTracker.cpp
@@ -51,22 +51,12 @@
}
void CacheTracker::loadStats() {
- int cacheGid = multiuser_get_cache_gid(mUserId, mAppId);
- if (cacheGid != -1 && !mQuotaDevice.empty()) {
- ATRACE_BEGIN("loadStats quota");
- struct dqblk dq;
- if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), cacheGid,
- reinterpret_cast<char*>(&dq)) != 0) {
- ATRACE_END();
- if (errno != ESRCH) {
- PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid;
- }
- } else {
- cacheUsed = dq.dqb_curspace;
- ATRACE_END();
- return;
- }
+ ATRACE_BEGIN("loadStats quota");
+ cacheUsed = 0;
+ if (loadQuotaStats()) {
+ return;
}
+ ATRACE_END();
ATRACE_BEGIN("loadStats tree");
cacheUsed = 0;
@@ -79,6 +69,36 @@
ATRACE_END();
}
+bool CacheTracker::loadQuotaStats() {
+ int cacheGid = multiuser_get_cache_gid(mUserId, mAppId);
+ int extCacheGid = multiuser_get_ext_cache_gid(mUserId, mAppId);
+ if (!mQuotaDevice.empty() && cacheGid != -1 && extCacheGid != -1) {
+ struct dqblk dq;
+ if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), cacheGid,
+ reinterpret_cast<char*>(&dq)) != 0) {
+ if (errno != ESRCH) {
+ PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid;
+ }
+ return false;
+ } else {
+ cacheUsed += dq.dqb_curspace;
+ }
+
+ if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), mQuotaDevice.c_str(), extCacheGid,
+ reinterpret_cast<char*>(&dq)) != 0) {
+ if (errno != ESRCH) {
+ PLOG(ERROR) << "Failed to quotactl " << mQuotaDevice << " for GID " << cacheGid;
+ }
+ return false;
+ } else {
+ cacheUsed += dq.dqb_curspace;
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
void CacheTracker::loadItemsFrom(const std::string& path) {
FTS *fts;
FTSENT *p;
diff --git a/cmds/installd/CacheTracker.h b/cmds/installd/CacheTracker.h
index 91692d7..44359b4 100644
--- a/cmds/installd/CacheTracker.h
+++ b/cmds/installd/CacheTracker.h
@@ -66,6 +66,7 @@
std::vector<std::string> mDataPaths;
+ bool loadQuotaStats();
void loadItemsFrom(const std::string& path);
DISALLOW_COPY_AND_ASSIGN(CacheTracker);
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 49a3b23..19dfb87 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -205,15 +205,20 @@
out << "installd is happy!" << endl;
{
- std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock);
- out << endl << "Devices with quota support:" << endl;
- for (const auto& n : mQuotaDevices) {
+ std::lock_guard<std::recursive_mutex> lock(mMountsLock);
+ out << endl << "Storage mounts:" << endl;
+ for (const auto& n : mStorageMounts) {
+ out << " " << n.first << " = " << n.second << endl;
+ }
+
+ out << endl << "Quota reverse mounts:" << endl;
+ for (const auto& n : mQuotaReverseMounts) {
out << " " << n.first << " = " << n.second << endl;
}
}
{
- std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock);
+ std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
out << endl << "Per-UID cache quotas:" << endl;
for (const auto& n : mCacheQuotas) {
out << " " << n.first << " = " << n.second << endl;
@@ -901,7 +906,7 @@
if (delete_dir_contents_and_dir(path, true) != 0) {
res = error("Failed to delete " + path);
}
- path = create_data_media_path(uuid_, userId);
+ path = findDataMediaPath(uuid, userId);
if (delete_dir_contents_and_dir(path, true) != 0) {
res = error("Failed to delete " + path);
}
@@ -952,13 +957,19 @@
FTSENT *p;
auto ce_path = create_data_user_ce_path(uuid_, user);
auto de_path = create_data_user_de_path(uuid_, user);
- char *argv[] = { (char*) ce_path.c_str(), (char*) de_path.c_str(), nullptr };
+ auto media_path = findDataMediaPath(uuid, user) + "/Android/data/";
+ char *argv[] = { (char*) ce_path.c_str(), (char*) de_path.c_str(),
+ (char*) media_path.c_str(), nullptr };
if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL))) {
return error("Failed to fts_open");
}
while ((p = fts_read(fts)) != NULL) {
if (p->fts_info == FTS_D && p->fts_level == 1) {
uid_t uid = p->fts_statp->st_uid;
+ if (multiuser_get_app_id(uid) == AID_MEDIA_RW) {
+ uid = (multiuser_get_app_id(p->fts_statp->st_gid) - AID_EXT_GID_START)
+ + AID_APP_START;
+ }
auto search = trackers.find(uid);
if (search != trackers.end()) {
search->second->addDataPath(p->fts_path);
@@ -967,7 +978,7 @@
multiuser_get_user_id(uid), multiuser_get_app_id(uid), device));
tracker->addDataPath(p->fts_path);
{
- std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock);
+ std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
tracker->cacheQuota = mCacheQuotas[uid];
}
if (tracker->cacheQuota == 0) {
@@ -1745,7 +1756,7 @@
int32_t userId, int32_t appId, int64_t cacheQuota) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
- std::lock_guard<std::recursive_mutex> lock(mCacheQuotasLock);
+ std::lock_guard<std::recursive_mutex> lock(mQuotasLock);
int32_t uid = multiuser_get_uid(userId, appId);
mCacheQuotas[uid] = cacheQuota;
@@ -2219,9 +2230,10 @@
binder::Status InstalldNativeService::invalidateMounts() {
ENFORCE_UID(AID_SYSTEM);
- std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock);
+ std::lock_guard<std::recursive_mutex> lock(mMountsLock);
- mQuotaDevices.clear();
+ mStorageMounts.clear();
+ mQuotaReverseMounts.clear();
std::ifstream in("/proc/mounts");
if (!in.is_open()) {
@@ -2231,17 +2243,25 @@
std::string source;
std::string target;
std::string ignored;
- struct dqblk dq;
while (!in.eof()) {
std::getline(in, source, ' ');
std::getline(in, target, ' ');
std::getline(in, ignored);
+#if !BYPASS_SDCARDFS
+ if (target.compare(0, 21, "/mnt/runtime/default/") == 0) {
+ LOG(DEBUG) << "Found storage mount " << source << " at " << target;
+ mStorageMounts[source] = target;
+ }
+#endif
+
+#if !BYPASS_QUOTA
if (source.compare(0, 11, "/dev/block/") == 0) {
+ struct dqblk dq;
if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), source.c_str(), 0,
reinterpret_cast<char*>(&dq)) == 0) {
- LOG(DEBUG) << "Found " << source << " with quota";
- mQuotaDevices[target] = source;
+ LOG(DEBUG) << "Found quota mount " << source << " at " << target;
+ mQuotaReverseMounts[target] = source;
// ext4 only enables DQUOT_USAGE_ENABLED by default, so we
// need to kick it again to enable DQUOT_LIMITS_ENABLED.
@@ -2255,15 +2275,29 @@
}
}
}
+#endif
}
return ok();
}
+std::string InstalldNativeService::findDataMediaPath(
+ const std::unique_ptr<std::string>& uuid, userid_t userid) {
+ std::lock_guard<std::recursive_mutex> lock(mMountsLock);
+ const char* uuid_ = uuid ? uuid->c_str() : nullptr;
+ auto path = StringPrintf("%s/media", create_data_path(uuid_).c_str());
+ auto resolved = mStorageMounts[path];
+ if (resolved.empty()) {
+ LOG(WARNING) << "Failed to find storage mount for " << path;
+ resolved = path;
+ }
+ return StringPrintf("%s/%u", resolved.c_str(), userid);
+}
+
std::string InstalldNativeService::findQuotaDeviceForUuid(
const std::unique_ptr<std::string>& uuid) {
- std::lock_guard<std::recursive_mutex> lock(mQuotaDevicesLock);
+ std::lock_guard<std::recursive_mutex> lock(mMountsLock);
auto path = create_data_path(uuid ? uuid->c_str() : nullptr);
- return mQuotaDevices[path];
+ return mQuotaReverseMounts[path];
}
binder::Status InstalldNativeService::isQuotaSupported(
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 7f73c2a..200fc77 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -121,14 +121,18 @@
private:
std::recursive_mutex mLock;
- std::recursive_mutex mQuotaDevicesLock;
- std::recursive_mutex mCacheQuotasLock;
+ std::recursive_mutex mMountsLock;
+ std::recursive_mutex mQuotasLock;
- /* Map from mount point to underlying device node */
- std::unordered_map<std::string, std::string> mQuotaDevices;
+ /* Map of all storage mounts from source to target */
+ std::unordered_map<std::string, std::string> mStorageMounts;
+ /* Map of all quota mounts from target to source */
+ std::unordered_map<std::string, std::string> mQuotaReverseMounts;
+
/* Map from UID to cache quota size */
std::unordered_map<uid_t, int64_t> mCacheQuotas;
+ std::string findDataMediaPath(const std::unique_ptr<std::string>& uuid, userid_t userid);
std::string findQuotaDeviceForUuid(const std::unique_ptr<std::string>& uuid);
};
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index dd94da9..070da84 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -33,6 +33,9 @@
#define MEASURE_DEBUG 0
#define FIXUP_DEBUG 0
+#define BYPASS_QUOTA 0
+#define BYPASS_SDCARDFS 0
+
namespace android {
namespace installd {
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 4b698c0..85d8938 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -322,8 +322,10 @@
break;
}
if (hal->hasVersion(version)) {
- hal->interfaces[interfaceName].name = interfaceName;
- hal->interfaces[interfaceName].instances.insert(instanceName);
+ if (&table != &mImplementationsTable) {
+ hal->interfaces[interfaceName].name = interfaceName;
+ hal->interfaces[interfaceName].instances.insert(instanceName);
+ }
done = true;
break;
}
@@ -331,12 +333,17 @@
if (done) {
continue; // to next TableEntry
}
+ decltype(vintf::ManifestHal::interfaces) interfaces;
+ if (&table != &mImplementationsTable) {
+ interfaces[interfaceName].name = interfaceName;
+ interfaces[interfaceName].instances.insert(instanceName);
+ }
if (!manifest.add(vintf::ManifestHal{
.format = vintf::HalFormat::HIDL,
.name = fqName.package(),
.versions = {version},
.transportArch = {transport, arch},
- .interfaces = {{interfaceName, {interfaceName, {{instanceName}}}}}})) {
+ .interfaces = interfaces})) {
mErr << "Warning: cannot add hal '" << fqInstanceName << "'" << std::endl;
}
}
diff --git a/cmds/vr/vrscreencap/Android.mk b/cmds/vr/vrscreencap/Android.mk
deleted file mode 100644
index 804afc9..0000000
--- a/cmds/vr/vrscreencap/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- vrscreencap.cpp
-
-LOCAL_STATIC_LIBRARIES := \
- libbufferhub \
- libdisplay \
- libimageio \
- libpdx_default_transport \
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- liblog \
- libpng \
- libsync \
- libui \
-
-LOCAL_MODULE := vrscreencap
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/vr/vrscreencap/vrscreencap.cpp b/cmds/vr/vrscreencap/vrscreencap.cpp
deleted file mode 100644
index 3d0d112..0000000
--- a/cmds/vr/vrscreencap/vrscreencap.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-// screencap is a tool for taking screenshots using the screenshot service.
-
-#include <fstream>
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include <private/dvr/image_io.h>
-#include <private/dvr/screenshot_client.h>
-
-namespace {
-
-// Attempt to take a screenshot and save it to |filename|.
-// Returns zero on success, or a non-zero exit code otherwise.
-int TakeScreenshot(const std::string& app_name, const std::string& filename,
- int index) {
- auto error_out = [app_name]() -> std::ostream& {
- return std::cerr << app_name << ": ";
- };
-
- auto info_out = [app_name]() -> std::ostream& {
- return std::cout << app_name << ": ";
- };
-
- auto client = android::dvr::ScreenshotClient::Create();
-
- if (client->format() != HAL_PIXEL_FORMAT_RGB_888) {
- error_out() << "The screenshot format for this device is not supported."
- << std::endl;
- return 1;
- }
-
- std::vector<uint8_t> image;
- int width = 0;
- int height = 0;
- if (client->Take(&image, index, &width, &height) != 0) {
- error_out() << "Failed to take screenshot." << std::endl;
- return 1;
- }
-
- info_out() << "Got " << width << "x" << height << " screenshot." << std::endl;
-
- if (!image_io_write_rgb888(filename.c_str(), width, height, image.data())) {
- error_out() << "Failed to write image to output file " << filename
- << std::endl;
- return 1;
- }
-
- return 0;
-}
-
-} // namespace
-
-int main(int argc, char** argv) {
- // Parse arguments
- if (argc != 2 && argc != 3) {
- std::cerr
- << "Usage: " << argv[0]
- << " filename.[" DVR_IMAGE_IO_SUPPORTED_WRITE
- "] [INDEX]\n"
- "INDEX: specify 1..n to grab hw_composer layers by index.\n"
- " specify -n to grab pre-warp layers (-1 is base layer).\n"
- " the default is 1 (the base hw_composer layer).\n"
- " an invalid index will result in an error.\n";
- return 1;
- }
- const std::string filename(argv[1]);
- int index = 1;
- if (argc > 2)
- index = atoi(argv[2]);
-
- // Perform the actual screenshot.
- return TakeScreenshot(argv[0], filename, index);
-}
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index d0cd8f2..e832961 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -338,6 +338,11 @@
gDisableBackgroundScheduling = disable;
}
+bool IPCThreadState::backgroundSchedulingDisabled()
+{
+ return gDisableBackgroundScheduling;
+}
+
sp<ProcessState> IPCThreadState::process()
{
return mProcess;
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 39bb078..aec8f10 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -211,7 +211,14 @@
{
flat_binder_object obj;
- obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
+ if (IPCThreadState::self()->backgroundSchedulingDisabled()) {
+ /* minimum priority for all nodes is nice 0 */
+ obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
+ } else {
+ /* minimum priority for all nodes is MAX_NICE(19) */
+ obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS;
+ }
+
if (binder != NULL) {
IBinder *local = binder->localBinder();
if (!local) {
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 7b826d6..245607e 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -83,6 +83,7 @@
// in to it but doesn't want to acquire locks in its services while in
// the background.
static void disableBackgroundScheduling(bool disable);
+ bool backgroundSchedulingDisabled();
// Call blocks until the number of executing binder threads is less than
// the maximum number of binder threads threads allowed for this process.
diff --git a/libs/vr/libbufferhub/buffer_hub_client.cpp b/libs/vr/libbufferhub/buffer_hub_client.cpp
index a1f952e..07c921f 100644
--- a/libs/vr/libbufferhub/buffer_hub_client.cpp
+++ b/libs/vr/libbufferhub/buffer_hub_client.cpp
@@ -216,8 +216,9 @@
event_fd(), width, height, format, producer_usage, consumer_usage,
metadata_size, slice_count);
+ // (b/37881101) Deprecate producer/consumer usage
auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
- width, height, format, producer_usage, consumer_usage, metadata_size,
+ width, height, format, (producer_usage | consumer_usage), metadata_size,
slice_count);
if (!status) {
ALOGE(
@@ -257,9 +258,10 @@
event_fd(), name.c_str(), user_id, group_id, width, height, format,
producer_usage, consumer_usage, meta_size_bytes, slice_count);
+ // (b/37881101) Deprecate producer/consumer usage
auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
- name, user_id, group_id, width, height, format, producer_usage,
- consumer_usage, meta_size_bytes, slice_count);
+ name, user_id, group_id, width, height, format,
+ (producer_usage | consumer_usage), meta_size_bytes, slice_count);
if (!status) {
ALOGE(
"BufferProducer::BufferProducer: Failed to create/get persistent "
@@ -295,8 +297,10 @@
const int format = HAL_PIXEL_FORMAT_BLOB;
const size_t meta_size_bytes = 0;
const size_t slice_count = 1;
+
+ // (b/37881101) Deprecate producer/consumer usage
auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
- width, height, format, producer_usage, consumer_usage, meta_size_bytes,
+ width, height, format, (producer_usage | consumer_usage), meta_size_bytes,
slice_count);
if (!status) {
ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s",
@@ -333,9 +337,11 @@
const int format = HAL_PIXEL_FORMAT_BLOB;
const size_t meta_size_bytes = 0;
const size_t slice_count = 1;
+
+ // (b/37881101) Deprecate producer/consumer usage
auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
- name, user_id, group_id, width, height, format, producer_usage,
- consumer_usage, meta_size_bytes, slice_count);
+ name, user_id, group_id, width, height, format,
+ (producer_usage | consumer_usage), meta_size_bytes, slice_count);
if (!status) {
ALOGE(
"BufferProducer::BufferProducer: Failed to create persistent "
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index 02e9f27..c6f0e1e 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -24,8 +24,7 @@
width_(buffer.width()),
height_(buffer.height()),
format_(buffer.format()),
- producer_usage_(buffer.usage()),
- consumer_usage_(buffer.usage()) {
+ usage_(buffer.usage()) {
// Populate the fd and int vectors: native_handle->data[] is an array of fds
// followed by an array of opaque ints.
const int fd_count = buffer.handle()->numFds;
@@ -48,11 +47,9 @@
for (const auto& fd : fds_)
fd_ints.push_back(fd.Get());
- // TODO(b/37881101) Get rid of producer/consumer usage.
- const int ret =
- buffer->Import(fd_ints.data(), fd_ints.size(), opaque_ints_.data(),
- opaque_ints_.size(), width_, height_, stride_, format_,
- (producer_usage_ | consumer_usage_));
+ const int ret = buffer->Import(fd_ints.data(), fd_ints.size(),
+ opaque_ints_.data(), opaque_ints_.size(),
+ width_, height_, stride_, format_, usage_);
if (ret < 0)
return ret;
@@ -76,20 +73,18 @@
uint32_t width_;
uint32_t height_;
uint32_t format_;
- uint64_t producer_usage_;
- uint64_t consumer_usage_;
+ uint64_t usage_;
std::vector<int> opaque_ints_;
std::vector<FileHandleType> fds_;
void Clear() {
id_ = -1;
- stride_ = width_ = height_ = format_ = producer_usage_ = consumer_usage_ =
- 0;
+ stride_ = width_ = height_ = format_ = usage_ = 0;
}
PDX_SERIALIZABLE_MEMBERS(NativeBufferHandle<FileHandleType>, id_, stride_,
- width_, height_, format_, producer_usage_,
- consumer_usage_, opaque_ints_, fds_);
+ width_, height_, format_, usage_, opaque_ints_,
+ fds_);
NativeBufferHandle(const NativeBufferHandle&) = delete;
void operator=(const NativeBufferHandle&) = delete;
@@ -140,20 +135,14 @@
};
struct UsagePolicy {
- uint64_t producer_set_mask;
- uint64_t producer_clear_mask;
- uint64_t producer_deny_set_mask;
- uint64_t producer_deny_clear_mask;
- uint64_t consumer_set_mask;
- uint64_t consumer_clear_mask;
- uint64_t consumer_deny_set_mask;
- uint64_t consumer_deny_clear_mask;
+ uint64_t usage_set_mask;
+ uint64_t usage_clear_mask;
+ uint64_t usage_deny_set_mask;
+ uint64_t usage_deny_clear_mask;
private:
- PDX_SERIALIZABLE_MEMBERS(UsagePolicy, producer_set_mask, producer_clear_mask,
- producer_deny_set_mask, producer_deny_clear_mask,
- consumer_set_mask, consumer_clear_mask,
- consumer_deny_set_mask, consumer_deny_clear_mask);
+ PDX_SERIALIZABLE_MEMBERS(UsagePolicy, usage_set_mask, usage_clear_mask,
+ usage_deny_set_mask, usage_deny_clear_mask);
};
// BufferHub Service RPC interface. Defines the endpoints, op codes, and method
@@ -203,13 +192,13 @@
// Methods.
PDX_REMOTE_METHOD(CreateBuffer, kOpCreateBuffer,
void(uint32_t width, uint32_t height, uint32_t format,
- uint64_t producer_usage, uint64_t consumer_usage,
- size_t meta_size_bytes, size_t slice_count));
+ uint64_t usage, size_t meta_size_bytes,
+ size_t slice_count));
PDX_REMOTE_METHOD(CreatePersistentBuffer, kOpCreatePersistentBuffer,
void(const std::string& name, int user_id, int group_id,
uint32_t width, uint32_t height, uint32_t format,
- uint64_t producer_usage, uint64_t consumer_usage,
- size_t meta_size_bytes, size_t slice_count));
+ uint64_t usage, size_t meta_size_bytes,
+ size_t slice_count));
PDX_REMOTE_METHOD(GetPersistentBuffer, kOpGetPersistentBuffer,
void(const std::string& name));
PDX_REMOTE_METHOD(GetBuffer, kOpGetBuffer,
@@ -241,8 +230,8 @@
kOpProducerQueueAllocateBuffers,
std::vector<std::pair<LocalChannelHandle, size_t>>(
uint32_t width, uint32_t height, uint32_t format,
- uint64_t producer_usage, uint64_t consumer_usage,
- size_t slice_count, size_t buffer_count));
+ uint64_t usage, size_t slice_count,
+ size_t buffer_count));
PDX_REMOTE_METHOD(ProducerQueueDetachBuffer, kOpProducerQueueDetachBuffer,
void(size_t slot));
PDX_REMOTE_METHOD(ConsumerQueueImportBuffers, kOpConsumerQueueImportBuffers,
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index b431d2f..b381d22 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -3,6 +3,7 @@
#include <inttypes.h>
#include <log/log.h>
#include <sys/epoll.h>
+#include <poll.h>
#include <array>
@@ -11,6 +12,15 @@
#include <pdx/file_handle.h>
#include <private/dvr/bufferhub_rpc.h>
+#define RETRY_EINTR(fnc_call) \
+ ([&]() -> decltype(fnc_call) { \
+ decltype(fnc_call) result; \
+ do { \
+ result = (fnc_call); \
+ } while (result == -1 && errno == EINTR); \
+ return result; \
+ })()
+
using android::pdx::ErrorStatus;
using android::pdx::LocalChannelHandle;
using android::pdx::Status;
@@ -87,6 +97,14 @@
return nullptr;
}
+std::unique_ptr<ConsumerQueue> BufferHubQueue::CreateSilentConsumerQueue() {
+ if (auto status = CreateConsumerQueueHandle())
+ return std::unique_ptr<ConsumerQueue>(
+ new ConsumerQueue(status.take(), true));
+ else
+ return nullptr;
+}
+
Status<LocalChannelHandle> BufferHubQueue::CreateConsumerQueueHandle() {
auto status = InvokeRemoteMethod<BufferHubRPC::CreateConsumerQueue>();
if (!status) {
@@ -103,12 +121,23 @@
bool BufferHubQueue::WaitForBuffers(int timeout) {
std::array<epoll_event, kMaxEvents> events;
- while (count() == 0) {
- int ret = epoll_fd_.Wait(events.data(), events.size(), timeout);
+ // Loop at least once to check for hangups.
+ do {
+ ALOGD_IF(
+ TRACE,
+ "BufferHubQueue::WaitForBuffers: queue_id=%d count=%zu capacity=%zu",
+ id(), count(), capacity());
+
+ // If there is already a buffer then just check for hangup without waiting.
+ const int ret = epoll_fd_.Wait(events.data(), events.size(),
+ count() == 0 ? timeout : 0);
if (ret == 0) {
- ALOGD_IF(TRACE, "Wait on epoll returns nothing before timeout.");
- return false;
+ ALOGI_IF(TRACE,
+ "BufferHubQueue::WaitForBuffers: No events before timeout: "
+ "queue_id=%d",
+ id());
+ return count() != 0;
}
if (ret < 0 && ret != -EINTR) {
@@ -125,45 +154,57 @@
for (int i = 0; i < num_events; i++) {
int64_t index = static_cast<int64_t>(events[i].data.u64);
- ALOGD_IF(TRACE, "New BufferHubQueue event %d: index=%" PRId64, i, index);
+ ALOGD_IF(TRACE,
+ "BufferHubQueue::WaitForBuffers: event %d: index=%" PRId64, i,
+ index);
if (is_buffer_event_index(index)) {
- HandleBufferEvent(static_cast<size_t>(index), events[i]);
+ HandleBufferEvent(static_cast<size_t>(index), events[i].events);
} else if (is_queue_event_index(index)) {
- HandleQueueEvent(events[i]);
+ HandleQueueEvent(events[i].events);
} else {
ALOGW("BufferHubQueue::WaitForBuffers: Unknown event index: %" PRId64,
index);
}
}
- }
+ } while (count() == 0 && capacity() > 0 && !hung_up());
- return true;
+ return count() != 0;
}
-void BufferHubQueue::HandleBufferEvent(size_t slot, const epoll_event& event) {
+void BufferHubQueue::HandleBufferEvent(size_t slot, int poll_events) {
auto buffer = buffers_[slot];
if (!buffer) {
ALOGW("BufferHubQueue::HandleBufferEvent: Invalid buffer slot: %zu", slot);
return;
}
- auto status = buffer->GetEventMask(event.events);
+ auto status = buffer->GetEventMask(poll_events);
if (!status) {
ALOGW("BufferHubQueue::HandleBufferEvent: Failed to get event mask: %s",
status.GetErrorMessage().c_str());
return;
}
- int events = status.get();
+ const int events = status.get();
if (events & EPOLLIN) {
- int ret = OnBufferReady(buffer, &fences_[slot]);
- if (ret < 0) {
- ALOGE("BufferHubQueue::HandleBufferEvent: Failed to set buffer ready: %s",
- strerror(-ret));
- return;
+ const int ret = OnBufferReady(buffer, &fences_[slot]);
+ if (ret == 0 || ret == -EALREADY || ret == -EBUSY) {
+ // Only enqueue the buffer if it moves to or is already in the state
+ // requested in OnBufferReady(). If the buffer is busy this means that the
+ // buffer moved from released to posted when a new consumer was created
+ // before the ProducerQueue had a chance to regain it. This is a valid
+ // transition that we have to handle because edge triggered poll events
+ // latch the ready state even if it is later de-asserted -- don't enqueue
+ // or print an error log in this case.
+ if (ret != -EBUSY)
+ Enqueue(buffer, slot);
+ } else {
+ ALOGE(
+ "BufferHubQueue::HandleBufferEvent: Failed to set buffer ready, "
+ "queue_id=%d buffer_id=%d: %s",
+ id(), buffer->id(), strerror(-ret));
}
- Enqueue(buffer, slot);
} else if (events & EPOLLHUP) {
// This might be caused by producer replacing an existing buffer slot, or
// when BufferHubQueue is shutting down. For the first case, currently the
@@ -186,15 +227,15 @@
}
}
-void BufferHubQueue::HandleQueueEvent(const epoll_event& event) {
- auto status = GetEventMask(event.events);
+void BufferHubQueue::HandleQueueEvent(int poll_event) {
+ auto status = GetEventMask(poll_event);
if (!status) {
ALOGW("BufferHubQueue::HandleQueueEvent: Failed to get event mask: %s",
status.GetErrorMessage().c_str());
return;
}
- int events = status.get();
+ const int events = status.get();
if (events & EPOLLIN) {
// Note that after buffer imports, if |count()| still returns 0, epoll
// wait will be tried again to acquire the newly imported buffer.
@@ -203,8 +244,11 @@
ALOGE("BufferHubQueue::HandleQueueEvent: Failed to import buffer: %s",
buffer_status.GetErrorMessage().c_str());
}
+ } else if (events & EPOLLHUP) {
+ ALOGD_IF(TRACE, "BufferHubQueue::HandleQueueEvent: hang up event!");
+ hung_up_ = true;
} else {
- ALOGW("BufferHubQueue::HandleQueueEvent: Unknown epoll events=%d", events);
+ ALOGW("BufferHubQueue::HandleQueueEvent: Unknown epoll events=%x", events);
}
}
@@ -260,7 +304,7 @@
return 0;
}
-void BufferHubQueue::Enqueue(std::shared_ptr<BufferHubBuffer> buf,
+void BufferHubQueue::Enqueue(const std::shared_ptr<BufferHubBuffer>& buf,
size_t slot) {
if (count() == capacity_) {
ALOGE("BufferHubQueue::Enqueue: Buffer queue is full!");
@@ -272,22 +316,19 @@
// the limitation of the RingBuffer we are using. Would be better to refactor
// that.
BufferInfo buffer_info(slot, meta_size_);
- // Swap buffer into vector.
- std::swap(buffer_info.buffer, buf);
+ buffer_info.buffer = buf;
// Swap metadata loaded during onBufferReady into vector.
std::swap(buffer_info.metadata, meta_buffer_tmp_);
available_buffers_.Append(std::move(buffer_info));
}
-std::shared_ptr<BufferHubBuffer> BufferHubQueue::Dequeue(int timeout,
- size_t* slot,
- void* meta,
- LocalHandle* fence) {
+Status<std::shared_ptr<BufferHubBuffer>> BufferHubQueue::Dequeue(
+ int timeout, size_t* slot, void* meta, LocalHandle* fence) {
ALOGD_IF(TRACE, "Dequeue: count=%zu, timeout=%d", count(), timeout);
- if (count() == 0 && !WaitForBuffers(timeout))
- return nullptr;
+ if (!WaitForBuffers(timeout))
+ return ErrorStatus(ETIMEDOUT);
std::shared_ptr<BufferHubBuffer> buf;
BufferInfo& buffer_info = available_buffers_.Front();
@@ -305,7 +346,7 @@
if (!buf) {
ALOGE("BufferHubQueue::Dequeue: Buffer to be dequeued is nullptr");
- return nullptr;
+ return ErrorStatus(ENOBUFS);
}
if (meta) {
@@ -313,11 +354,11 @@
reinterpret_cast<uint8_t*>(meta));
}
- return buf;
+ return {std::move(buf)};
}
ProducerQueue::ProducerQueue(size_t meta_size)
- : ProducerQueue(meta_size, 0, 0, 0, 0, 0, 0, 0, 0) {}
+ : ProducerQueue(meta_size, 0, 0, 0, 0) {}
ProducerQueue::ProducerQueue(LocalChannelHandle handle)
: BASE(std::move(handle)) {
@@ -329,22 +370,14 @@
}
}
-ProducerQueue::ProducerQueue(size_t meta_size, uint64_t producer_usage_set_mask,
- uint64_t producer_usage_clear_mask,
- uint64_t producer_usage_deny_set_mask,
- uint64_t producer_usage_deny_clear_mask,
- uint64_t consumer_usage_set_mask,
- uint64_t consumer_usage_clear_mask,
- uint64_t consumer_usage_deny_set_mask,
- uint64_t consumer_usage_deny_clear_mask)
+ProducerQueue::ProducerQueue(size_t meta_size, uint64_t usage_set_mask,
+ uint64_t usage_clear_mask,
+ uint64_t usage_deny_set_mask,
+ uint64_t usage_deny_clear_mask)
: BASE(BufferHubRPC::kClientPath) {
auto status = InvokeRemoteMethod<BufferHubRPC::CreateProducerQueue>(
- meta_size,
- UsagePolicy{producer_usage_set_mask, producer_usage_clear_mask,
- producer_usage_deny_set_mask, producer_usage_deny_clear_mask,
- consumer_usage_set_mask, consumer_usage_clear_mask,
- consumer_usage_deny_set_mask,
- consumer_usage_deny_clear_mask});
+ meta_size, UsagePolicy{usage_set_mask, usage_clear_mask,
+ usage_deny_set_mask, usage_deny_clear_mask});
if (!status) {
ALOGE("ProducerQueue::ProducerQueue: Failed to create producer queue: %s",
status.GetErrorMessage().c_str());
@@ -356,16 +389,8 @@
}
int ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
- uint32_t format, uint32_t usage,
+ uint32_t format, uint64_t usage,
size_t slice_count, size_t* out_slot) {
- return AllocateBuffer(width, height, format, usage, usage, slice_count,
- out_slot);
-}
-
-int ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
- uint32_t format, uint64_t producer_usage,
- uint64_t consumer_usage, size_t slice_count,
- size_t* out_slot) {
if (out_slot == nullptr) {
ALOGE("ProducerQueue::AllocateBuffer: Parameter out_slot cannot be null.");
return -EINVAL;
@@ -378,15 +403,12 @@
}
const size_t kBufferCount = 1U;
-
Status<std::vector<std::pair<LocalChannelHandle, size_t>>> status =
InvokeRemoteMethod<BufferHubRPC::ProducerQueueAllocateBuffers>(
- width, height, format, producer_usage, consumer_usage, slice_count,
- kBufferCount);
+ width, height, format, usage, slice_count, kBufferCount);
if (!status) {
- ALOGE(
- "ProducerQueue::AllocateBuffer failed to create producer buffer "
- "through BufferHub.");
+ ALOGE("ProducerQueue::AllocateBuffer failed to create producer buffer: %s",
+ status.GetErrorMessage().c_str());
return -status.error();
}
@@ -409,6 +431,8 @@
int ProducerQueue::AddBuffer(const std::shared_ptr<BufferProducer>& buf,
size_t slot) {
+ ALOGD_IF(TRACE, "ProducerQueue::AddBuffer: queue_id=%d buffer_id=%d slot=%zu",
+ id(), buf->id(), slot);
// For producer buffer, we need to enqueue the newly added buffer
// immediately. Producer queue starts with all buffers in available state.
const int ret = BufferHubQueue::AddBuffer(buf, slot);
@@ -423,37 +447,40 @@
auto status =
InvokeRemoteMethod<BufferHubRPC::ProducerQueueDetachBuffer>(slot);
if (!status) {
- ALOGE(
- "ProducerQueue::DetachBuffer failed to detach producer buffer through "
- "BufferHub, error: %s",
- status.GetErrorMessage().c_str());
+ ALOGE("ProducerQueue::DetachBuffer: Failed to detach producer buffer: %s",
+ status.GetErrorMessage().c_str());
return -status.error();
}
return BufferHubQueue::DetachBuffer(slot);
}
-std::shared_ptr<BufferProducer> ProducerQueue::Dequeue(
+Status<std::shared_ptr<BufferProducer>> ProducerQueue::Dequeue(
int timeout, size_t* slot, LocalHandle* release_fence) {
if (slot == nullptr || release_fence == nullptr) {
- ALOGE(
- "ProducerQueue::Dequeue: invalid parameter, slot=%p, release_fence=%p",
- slot, release_fence);
- return nullptr;
+ ALOGE("ProducerQueue::Dequeue: Invalid parameter: slot=%p release_fence=%p",
+ slot, release_fence);
+ return ErrorStatus(EINVAL);
}
- auto buf = BufferHubQueue::Dequeue(timeout, slot, nullptr, release_fence);
- return std::static_pointer_cast<BufferProducer>(buf);
+ auto buffer_status =
+ BufferHubQueue::Dequeue(timeout, slot, nullptr, release_fence);
+ if (!buffer_status)
+ return buffer_status.error_status();
+
+ return {std::static_pointer_cast<BufferProducer>(buffer_status.take())};
}
-int ProducerQueue::OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
+int ProducerQueue::OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
LocalHandle* release_fence) {
+ ALOGD_IF(TRACE, "ProducerQueue::OnBufferReady: queue_id=%d buffer_id=%d",
+ id(), buf->id());
auto buffer = std::static_pointer_cast<BufferProducer>(buf);
return buffer->Gain(release_fence);
}
-ConsumerQueue::ConsumerQueue(LocalChannelHandle handle)
- : BufferHubQueue(std::move(handle)) {
+ConsumerQueue::ConsumerQueue(LocalChannelHandle handle, bool ignore_on_import)
+ : BufferHubQueue(std::move(handle)), ignore_on_import_(ignore_on_import) {
auto status = ImportQueue();
if (!status) {
ALOGE("ConsumerQueue::ConsumerQueue: Failed to import queue: %s",
@@ -461,34 +488,55 @@
Close(-status.error());
}
- // TODO(b/34387835) Import buffers in case the ProducerQueue we are
- // based on was not empty.
+ auto import_status = ImportBuffers();
+ if (import_status) {
+ ALOGI("ConsumerQueue::ConsumerQueue: Imported %zu buffers.",
+ import_status.get());
+ } else {
+ ALOGE("ConsumerQueue::ConsumerQueue: Failed to import buffers: %s",
+ import_status.GetErrorMessage().c_str());
+ }
}
Status<size_t> ConsumerQueue::ImportBuffers() {
auto status = InvokeRemoteMethod<BufferHubRPC::ConsumerQueueImportBuffers>();
if (!status) {
- ALOGE(
- "ConsumerQueue::ImportBuffers failed to import consumer buffer through "
- "BufferBub, error: %s",
- status.GetErrorMessage().c_str());
+ ALOGE("ConsumerQueue::ImportBuffers: Failed to import consumer buffer: %s",
+ status.GetErrorMessage().c_str());
return ErrorStatus(status.error());
}
+ int ret;
int last_error = 0;
int imported_buffers = 0;
auto buffer_handle_slots = status.take();
for (auto& buffer_handle_slot : buffer_handle_slots) {
- ALOGD_IF(TRACE,
- "ConsumerQueue::ImportBuffers, new buffer, buffer_handle: %d",
+ ALOGD_IF(TRACE, "ConsumerQueue::ImportBuffers: buffer_handle=%d",
buffer_handle_slot.first.value());
std::unique_ptr<BufferConsumer> buffer_consumer =
BufferConsumer::Import(std::move(buffer_handle_slot.first));
- int ret = AddBuffer(std::move(buffer_consumer), buffer_handle_slot.second);
+
+ // Setup ignore state before adding buffer to the queue.
+ if (ignore_on_import_) {
+ ALOGD_IF(TRACE,
+ "ConsumerQueue::ImportBuffers: Setting buffer to ignored state: "
+ "buffer_id=%d",
+ buffer_consumer->id());
+ ret = buffer_consumer->SetIgnore(true);
+ if (ret < 0) {
+ ALOGE(
+ "ConsumerQueue::ImportBuffers: Failed to set ignored state on "
+ "imported buffer buffer_id=%d: %s",
+ buffer_consumer->id(), strerror(-ret));
+ last_error = ret;
+ }
+ }
+
+ ret = AddBuffer(std::move(buffer_consumer), buffer_handle_slot.second);
if (ret < 0) {
- ALOGE("ConsumerQueue::ImportBuffers failed to add buffer, ret: %s",
+ ALOGE("ConsumerQueue::ImportBuffers: Failed to add buffer: %s",
strerror(-ret));
last_error = ret;
continue;
@@ -505,11 +553,33 @@
int ConsumerQueue::AddBuffer(const std::shared_ptr<BufferConsumer>& buf,
size_t slot) {
- // Consumer queue starts with all buffers in unavailable state.
- return BufferHubQueue::AddBuffer(buf, slot);
+ ALOGD_IF(TRACE, "ConsumerQueue::AddBuffer: queue_id=%d buffer_id=%d slot=%zu",
+ id(), buf->id(), slot);
+ const int ret = BufferHubQueue::AddBuffer(buf, slot);
+ if (ret < 0)
+ return ret;
+
+ // Check to see if the buffer is already signaled. This is necessary to catch
+ // cases where buffers are already available; epoll edge triggered mode does
+ // not fire until and edge transition when adding new buffers to the epoll
+ // set.
+ const int kTimeoutMs = 0;
+ pollfd pfd{buf->event_fd(), POLLIN, 0};
+ const int count = RETRY_EINTR(poll(&pfd, 1, kTimeoutMs));
+ if (count < 0) {
+ const int error = errno;
+ ALOGE("ConsumerQueue::AddBuffer: Failed to poll consumer buffer: %s",
+ strerror(errno));
+ return -error;
+ }
+
+ if (count == 1)
+ HandleBufferEvent(slot, pfd.revents);
+
+ return 0;
}
-std::shared_ptr<BufferConsumer> ConsumerQueue::Dequeue(
+Status<std::shared_ptr<BufferConsumer>> ConsumerQueue::Dequeue(
int timeout, size_t* slot, void* meta, size_t meta_size,
LocalHandle* acquire_fence) {
if (meta_size != meta_size_) {
@@ -517,23 +587,29 @@
"ConsumerQueue::Dequeue: Metadata size (%zu) for the dequeuing buffer "
"does not match metadata size (%zu) for the queue.",
meta_size, meta_size_);
- return nullptr;
+ return ErrorStatus(EINVAL);
}
- if (slot == nullptr || meta == nullptr || acquire_fence == nullptr) {
+ if (slot == nullptr || acquire_fence == nullptr) {
ALOGE(
- "ConsumerQueue::Dequeue: Invalid parameter, slot=%p, meta=%p, "
+ "ConsumerQueue::Dequeue: Invalid parameter: slot=%p meta=%p "
"acquire_fence=%p",
slot, meta, acquire_fence);
- return nullptr;
+ return ErrorStatus(EINVAL);
}
- auto buf = BufferHubQueue::Dequeue(timeout, slot, meta, acquire_fence);
- return std::static_pointer_cast<BufferConsumer>(buf);
+ auto buffer_status =
+ BufferHubQueue::Dequeue(timeout, slot, meta, acquire_fence);
+ if (!buffer_status)
+ return buffer_status.error_status();
+
+ return {std::static_pointer_cast<BufferConsumer>(buffer_status.take())};
}
-int ConsumerQueue::OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
+int ConsumerQueue::OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
LocalHandle* acquire_fence) {
+ ALOGD_IF(TRACE, "ConsumerQueue::OnBufferReady: queue_id=%d buffer_id=%d",
+ id(), buf->id());
auto buffer = std::static_pointer_cast<BufferConsumer>(buf);
return buffer->Acquire(acquire_fence, meta_buffer_tmp_.get(), meta_size_);
}
@@ -548,7 +624,9 @@
ALOGW("ConsumerQueue::OnBufferAllocated: No new buffers allocated!");
return ErrorStatus(ENOBUFS);
} else {
- ALOGD_IF(TRACE, "Imported %zu consumer buffers.", status.get());
+ ALOGD_IF(TRACE,
+ "ConsumerQueue::OnBufferAllocated: Imported %zu consumer buffers.",
+ status.get());
return {};
}
}
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index 8216a39..0a36156 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -138,11 +138,13 @@
for (size_t retry = 0; retry < BufferHubQueue::kMaxQueueCapacity; retry++) {
LocalHandle fence;
- buffer_producer =
+ auto buffer_status =
core_->producer_->Dequeue(core_->dequeue_timeout_ms_, &slot, &fence);
if (!buffer_producer)
return NO_MEMORY;
+ buffer_producer = buffer_status.take();
+
if (width == buffer_producer->width() &&
height == buffer_producer->height() &&
static_cast<uint32_t>(format) == buffer_producer->format()) {
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
index 6467c3c..c5dbbde 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
@@ -33,6 +33,11 @@
// a new consumer queue client or nullptr on failure.
std::unique_ptr<ConsumerQueue> CreateConsumerQueue();
+ // Create a new consumer queue that is attached to the producer. This queue
+ // sets each of its imported consumer buffers to the ignored state to avoid
+ // participation in lifecycle events.
+ std::unique_ptr<ConsumerQueue> CreateSilentConsumerQueue();
+
// Return the default buffer width of this buffer queue.
size_t default_width() const { return default_width_; }
@@ -71,9 +76,19 @@
}
}
+ // Returns an fd that signals pending queue events using
+ // EPOLLIN/POLLIN/readible. Either HandleQueueEvents or WaitForBuffers may be
+ // called to handle pending queue events.
+ int queue_fd() const { return epoll_fd_.Get(); }
+
+ // Handles any pending events, returning available buffers to the queue and
+ // reaping disconnected buffers. Returns true if successful, false if an error
+ // occurred.
+ bool HandleQueueEvents() { return WaitForBuffers(0); }
+
// Enqueue a buffer marks buffer to be available (|Gain|'ed for producer
// and |Acquire|'ed for consumer. This is only used for internal bookkeeping.
- void Enqueue(std::shared_ptr<BufferHubBuffer> buf, size_t slot);
+ void Enqueue(const std::shared_ptr<BufferHubBuffer>& buf, size_t slot);
// |BufferHubQueue| will keep track of at most this value of buffers.
static constexpr size_t kMaxQueueCapacity =
@@ -88,6 +103,7 @@
static constexpr int kNoTimeOut = -1;
int id() const { return id_; }
+ bool hung_up() const { return hung_up_; }
protected:
BufferHubQueue(LocalChannelHandle channel);
@@ -113,15 +129,17 @@
// block. Specifying a timeout of -1 causes |Dequeue()| to block indefinitely,
// while specifying a timeout equal to zero cause |Dequeue()| to return
// immediately, even if no buffers are available.
- std::shared_ptr<BufferHubBuffer> Dequeue(int timeout, size_t* slot,
- void* meta, LocalHandle* fence);
+ pdx::Status<std::shared_ptr<BufferHubBuffer>> Dequeue(int timeout,
+ size_t* slot,
+ void* meta,
+ LocalHandle* fence);
// Wait for buffers to be released and re-add them to the queue.
bool WaitForBuffers(int timeout);
- void HandleBufferEvent(size_t slot, const epoll_event& event);
- void HandleQueueEvent(const epoll_event& event);
+ void HandleBufferEvent(size_t slot, int poll_events);
+ void HandleQueueEvent(int poll_events);
- virtual int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
+ virtual int OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
LocalHandle* fence) = 0;
// Called when a buffer is allocated remotely.
@@ -248,6 +266,12 @@
// Epoll fd used to wait for BufferHub events.
EpollFileDescriptor epoll_fd_;
+ // Flag indicating that the other side hung up. For ProducerQueues this
+ // triggers when BufferHub dies or explicitly closes the queue channel. For
+ // ConsumerQueues this can either mean the same or that the ProducerQueue on
+ // the other end hung up.
+ bool hung_up_{false};
+
// Global id for the queue that is consistent across processes.
int id_;
@@ -261,6 +285,9 @@
static std::unique_ptr<ProducerQueue> Create() {
return BASE::Create(sizeof(Meta));
}
+ static std::unique_ptr<ProducerQueue> Create(size_t meta_size_bytes) {
+ return BASE::Create(meta_size_bytes);
+ }
// Usage bits in |usage_set_mask| will be automatically masked on. Usage bits
// in |usage_clear_mask| will be automatically masked off. Note that
@@ -279,22 +306,15 @@
uint32_t usage_deny_set_mask,
uint32_t usage_deny_clear_mask) {
return BASE::Create(sizeof(Meta), usage_set_mask, usage_clear_mask,
- usage_deny_set_mask, usage_deny_clear_mask,
- usage_set_mask, usage_clear_mask, usage_deny_set_mask,
- usage_deny_clear_mask);
+ usage_deny_set_mask, usage_deny_clear_mask);
}
- template <typename Meta>
- static std::unique_ptr<ProducerQueue> Create(
- uint64_t producer_usage_set_mask, uint64_t producer_usage_clear_mask,
- uint64_t producer_usage_deny_set_mask,
- uint64_t producer_usage_deny_clear_mask, uint64_t consumer_usage_set_mask,
- uint64_t consumer_usage_clear_mask, uint64_t consumer_usage_deny_set_mask,
- uint64_t consumer_usage_deny_clear_mask) {
- return BASE::Create(sizeof(Meta), producer_usage_set_mask,
- producer_usage_clear_mask, producer_usage_deny_set_mask,
- producer_usage_deny_clear_mask, consumer_usage_set_mask,
- consumer_usage_clear_mask, consumer_usage_deny_set_mask,
- consumer_usage_deny_clear_mask);
+ static std::unique_ptr<ProducerQueue> Create(size_t meta_size_bytes,
+ uint32_t usage_set_mask,
+ uint32_t usage_clear_mask,
+ uint32_t usage_deny_set_mask,
+ uint32_t usage_deny_clear_mask) {
+ return BASE::Create(meta_size_bytes, usage_set_mask, usage_clear_mask,
+ usage_deny_set_mask, usage_deny_clear_mask);
}
// Import a |ProducerQueue| from a channel handle.
@@ -317,10 +337,7 @@
// Returns Zero on success and negative error code when buffer allocation
// fails.
int AllocateBuffer(uint32_t width, uint32_t height, uint32_t format,
- uint32_t usage, size_t slice_count, size_t* out_slot);
- int AllocateBuffer(uint32_t width, uint32_t height, uint32_t format,
- uint64_t producer_usage, uint64_t consumer_usage,
- size_t slice_count, size_t* out_slot);
+ uint64_t usage, size_t slice_count, size_t* out_slot);
// Add a producer buffer to populate the queue. Once added, a producer buffer
// is available to use (i.e. in |Gain|'ed mode).
@@ -334,8 +351,8 @@
// Dequeue a producer buffer to write. The returned buffer in |Gain|'ed mode,
// and caller should call Post() once it's done writing to release the buffer
// to the consumer side.
- std::shared_ptr<BufferProducer> Dequeue(int timeout, size_t* slot,
- LocalHandle* release_fence);
+ pdx::Status<std::shared_ptr<BufferProducer>> Dequeue(
+ int timeout, size_t* slot, LocalHandle* release_fence);
private:
friend BASE;
@@ -345,33 +362,47 @@
// arguments as the constructors.
explicit ProducerQueue(size_t meta_size);
ProducerQueue(LocalChannelHandle handle);
- ProducerQueue(size_t meta_size, uint64_t producer_usage_set_mask,
- uint64_t producer_usage_clear_mask,
- uint64_t producer_usage_deny_set_mask,
- uint64_t producer_usage_deny_clear_mask,
- uint64_t consumer_usage_set_mask,
- uint64_t consumer_usage_clear_mask,
- uint64_t consumer_usage_deny_set_mask,
- uint64_t consumer_usage_deny_clear_mask);
+ ProducerQueue(size_t meta_size, uint64_t usage_set_mask,
+ uint64_t usage_clear_mask, uint64_t usage_deny_set_mask,
+ uint64_t usage_deny_clear_mask);
- int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
+ int OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
LocalHandle* release_fence) override;
};
+// Explicit specializations of ProducerQueue::Create for void metadata type.
+template <>
+inline std::unique_ptr<ProducerQueue> ProducerQueue::Create<void>() {
+ return ProducerQueue::Create(0);
+}
+template <>
+inline std::unique_ptr<ProducerQueue> ProducerQueue::Create<void>(
+ uint32_t usage_set_mask, uint32_t usage_clear_mask,
+ uint32_t usage_deny_set_mask, uint32_t usage_deny_clear_mask) {
+ return ProducerQueue::Create(0, usage_set_mask, usage_clear_mask,
+ usage_deny_set_mask, usage_deny_clear_mask);
+}
+
class ConsumerQueue : public BufferHubQueue {
public:
// Get a buffer consumer. Note that the method doesn't check whether the
// buffer slot has a valid buffer that has been imported already. When no
- // buffer has been imported before it returns |nullptr|; otherwise it returns
- // a shared pointer to a |BufferConsumer|.
+ // buffer has been imported before it returns nullptr; otherwise returns a
+ // shared pointer to a BufferConsumer.
std::shared_ptr<BufferConsumer> GetBuffer(size_t slot) const {
return std::static_pointer_cast<BufferConsumer>(
BufferHubQueue::GetBuffer(slot));
}
- // Import a |ConsumerQueue| from a channel handle.
- static std::unique_ptr<ConsumerQueue> Import(LocalChannelHandle handle) {
- return std::unique_ptr<ConsumerQueue>(new ConsumerQueue(std::move(handle)));
+ // Import a ConsumerQueue from a channel handle. |ignore_on_import| controls
+ // whether or not buffers are set to be ignored when imported. This may be
+ // used to avoid participation in the buffer lifecycle by a consumer queue
+ // that is only used to spawn other consumer queues, such as in an
+ // intermediate service.
+ static std::unique_ptr<ConsumerQueue> Import(LocalChannelHandle handle,
+ bool ignore_on_import = false) {
+ return std::unique_ptr<ConsumerQueue>(
+ new ConsumerQueue(std::move(handle), ignore_on_import));
}
// Import newly created buffers from the service side.
@@ -385,19 +416,23 @@
// Dequeue() is done with the corect metadata type and size with those used
// when the buffer is orignally created.
template <typename Meta>
- std::shared_ptr<BufferConsumer> Dequeue(int timeout, size_t* slot, Meta* meta,
- LocalHandle* acquire_fence) {
+ pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
+ int timeout, size_t* slot, Meta* meta, LocalHandle* acquire_fence) {
return Dequeue(timeout, slot, meta, sizeof(*meta), acquire_fence);
}
+ pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
+ int timeout, size_t* slot, LocalHandle* acquire_fence) {
+ return Dequeue(timeout, slot, nullptr, 0, acquire_fence);
+ }
- std::shared_ptr<BufferConsumer> Dequeue(int timeout, size_t* slot, void* meta,
- size_t meta_size,
- LocalHandle* acquire_fence);
+ pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
+ int timeout, size_t* slot, void* meta, size_t meta_size,
+ LocalHandle* acquire_fence);
private:
friend BufferHubQueue;
- ConsumerQueue(LocalChannelHandle handle);
+ ConsumerQueue(LocalChannelHandle handle, bool ignore_on_import = false);
// Add a consumer buffer to populate the queue. Once added, a consumer buffer
// is NOT available to use until the producer side |Post| it. |WaitForBuffers|
@@ -405,32 +440,17 @@
// consumer.
int AddBuffer(const std::shared_ptr<BufferConsumer>& buf, size_t slot);
- int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
+ int OnBufferReady(const std::shared_ptr<BufferHubBuffer>& buf,
LocalHandle* acquire_fence) override;
Status<void> OnBufferAllocated() override;
+
+ // Flag indicating that imported (consumer) buffers should be ignored when
+ // imported to avoid participating in the buffer ownership flow.
+ bool ignore_on_import_;
};
} // namespace dvr
} // namespace android
-// Concrete C type definition for DVR API.
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct DvrWriteBufferQueue {
- std::shared_ptr<android::dvr::ProducerQueue> producer_queue_;
- ANativeWindow* native_window_{nullptr};
-};
-
-struct DvrReadBufferQueue {
- std::shared_ptr<android::dvr::ConsumerQueue> consumer_queue_;
-};
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
#endif // ANDROID_DVR_BUFFER_HUB_QUEUE_CLIENT_H_
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index 171577d..ba9c179 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -22,20 +22,33 @@
class BufferHubQueueTest : public ::testing::Test {
public:
template <typename Meta>
- bool CreateQueues(int usage_set_mask = 0, int usage_clear_mask = 0,
- int usage_deny_set_mask = 0,
- int usage_deny_clear_mask = 0) {
+ bool CreateProducerQueue(uint64_t usage_set_mask = 0,
+ uint64_t usage_clear_mask = 0,
+ uint64_t usage_deny_set_mask = 0,
+ uint64_t usage_deny_clear_mask = 0) {
producer_queue_ =
ProducerQueue::Create<Meta>(usage_set_mask, usage_clear_mask,
usage_deny_set_mask, usage_deny_clear_mask);
- if (!producer_queue_)
- return false;
+ return producer_queue_ != nullptr;
+ }
- consumer_queue_ = producer_queue_->CreateConsumerQueue();
- if (!consumer_queue_)
+ bool CreateConsumerQueue() {
+ if (producer_queue_) {
+ consumer_queue_ = producer_queue_->CreateConsumerQueue();
+ return consumer_queue_ != nullptr;
+ } else {
return false;
+ }
+ }
- return true;
+ template <typename Meta>
+ bool CreateQueues(int usage_set_mask = 0, int usage_clear_mask = 0,
+ int usage_deny_set_mask = 0,
+ int usage_deny_clear_mask = 0) {
+ return CreateProducerQueue<Meta>(usage_set_mask, usage_clear_mask,
+ usage_deny_set_mask,
+ usage_deny_clear_mask) &&
+ CreateConsumerQueue();
}
void AllocateBuffer() {
@@ -64,12 +77,16 @@
for (size_t i = 0; i < nb_dequeue_times; i++) {
size_t slot;
LocalHandle fence;
- auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
+ auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
+ ASSERT_TRUE(p1_status.ok());
+ auto p1 = p1_status.take();
ASSERT_NE(nullptr, p1);
size_t mi = i;
ASSERT_EQ(p1->Post(LocalHandle(), &mi, sizeof(mi)), 0);
size_t mo;
- auto c1 = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
+ auto c1_status = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
+ ASSERT_TRUE(c1_status.ok());
+ auto c1 = c1_status.take();
ASSERT_NE(nullptr, c1);
ASSERT_EQ(mi, mo);
c1->Release(LocalHandle());
@@ -94,23 +111,27 @@
ASSERT_EQ(consumer_queue_->count(), 0U);
// Consumer queue does not import buffers until a dequeue is issued.
ASSERT_EQ(consumer_queue_->capacity(), i);
- // Dequeue returns nullptr since no buffer is ready to consumer, but
+ // Dequeue returns timeout since no buffer is ready to consumer, but
// this implicitly triggers buffer import and bump up |capacity|.
LocalHandle fence;
- auto consumer_null = consumer_queue_->Dequeue(0, &slot, &seq, &fence);
- ASSERT_EQ(nullptr, consumer_null);
+ auto status = consumer_queue_->Dequeue(0, &slot, &seq, &fence);
+ ASSERT_FALSE(status.ok());
+ ASSERT_EQ(ETIMEDOUT, status.error());
ASSERT_EQ(consumer_queue_->capacity(), i + 1);
}
for (size_t i = 0; i < nb_buffer; i++) {
LocalHandle fence;
// First time, there is no buffer available to dequeue.
- auto buffer_null = consumer_queue_->Dequeue(0, &slot, &seq, &fence);
- ASSERT_EQ(nullptr, buffer_null);
+ auto consumer_status = consumer_queue_->Dequeue(0, &slot, &seq, &fence);
+ ASSERT_FALSE(consumer_status.ok());
+ ASSERT_EQ(ETIMEDOUT, consumer_status.error());
// Make sure Producer buffer is Post()'ed so that it's ready to Accquire
// in the consumer's Dequeue() function.
- auto producer = producer_queue_->Dequeue(0, &slot, &fence);
+ auto producer_status = producer_queue_->Dequeue(0, &slot, &fence);
+ ASSERT_TRUE(producer_status.ok());
+ auto producer = producer_status.take();
ASSERT_NE(nullptr, producer);
uint64_t seq_in = static_cast<uint64_t>(i);
@@ -118,12 +139,86 @@
// Second time, the just |Post()|'ed buffer should be dequeued.
uint64_t seq_out = 0;
- auto consumer = consumer_queue_->Dequeue(0, &slot, &seq_out, &fence);
+ consumer_status = consumer_queue_->Dequeue(0, &slot, &seq_out, &fence);
+ ASSERT_TRUE(consumer_status.ok());
+ auto consumer = consumer_status.take();
ASSERT_NE(nullptr, consumer);
ASSERT_EQ(seq_in, seq_out);
}
}
+TEST_F(BufferHubQueueTest, TestMultipleConsumers) {
+ ASSERT_TRUE(CreateProducerQueue<void>());
+
+ // Allocate buffers.
+ const size_t kBufferCount = 4u;
+ for (size_t i = 0; i < kBufferCount; i++) {
+ AllocateBuffer();
+ }
+ ASSERT_EQ(kBufferCount, producer_queue_->count());
+
+ // Build a silent consumer queue to test multi-consumer queue features.
+ auto silent_queue = producer_queue_->CreateSilentConsumerQueue();
+ ASSERT_NE(nullptr, silent_queue);
+
+ // Check that buffers are correctly imported on construction.
+ EXPECT_EQ(kBufferCount, silent_queue->capacity());
+
+ // Dequeue and post a buffer.
+ size_t slot;
+ LocalHandle fence;
+ auto producer_status = producer_queue_->Dequeue(0, &slot, &fence);
+ ASSERT_TRUE(producer_status.ok());
+ auto producer_buffer = producer_status.take();
+ ASSERT_NE(nullptr, producer_buffer);
+ ASSERT_EQ(0, producer_buffer->Post<void>({}));
+
+ // Currently we expect no buffer to be available prior to calling
+ // WaitForBuffers/HandleQueueEvents.
+ // TODO(eieio): Note this behavior may change in the future.
+ EXPECT_EQ(0u, silent_queue->count());
+ EXPECT_FALSE(silent_queue->HandleQueueEvents());
+ EXPECT_EQ(0u, silent_queue->count());
+
+ // Build a new consumer queue to test multi-consumer queue features.
+ consumer_queue_ = silent_queue->CreateConsumerQueue();
+ ASSERT_NE(nullptr, consumer_queue_);
+
+ // Check that buffers are correctly imported on construction.
+ EXPECT_EQ(kBufferCount, consumer_queue_->capacity());
+ EXPECT_EQ(1u, consumer_queue_->count());
+
+ // Reclaim released/ignored buffers.
+ producer_queue_->HandleQueueEvents();
+ ASSERT_EQ(kBufferCount - 1, producer_queue_->count());
+
+ // Post another buffer.
+ producer_status = producer_queue_->Dequeue(0, &slot, &fence);
+ ASSERT_TRUE(producer_status.ok());
+ producer_buffer = producer_status.take();
+ ASSERT_NE(nullptr, producer_buffer);
+ ASSERT_EQ(0, producer_buffer->Post<void>({}));
+
+ // Verify that the consumer queue receives it.
+ EXPECT_EQ(1u, consumer_queue_->count());
+ EXPECT_TRUE(consumer_queue_->HandleQueueEvents());
+ EXPECT_EQ(2u, consumer_queue_->count());
+
+ // Dequeue and acquire/release (discard) buffers on the consumer end.
+ auto consumer_status = consumer_queue_->Dequeue(0, &slot, &fence);
+ ASSERT_TRUE(consumer_status.ok());
+ auto consumer_buffer = consumer_status.take();
+ ASSERT_NE(nullptr, consumer_buffer);
+ consumer_buffer->Discard();
+
+ // Buffer should be returned to the producer queue without being handled by
+ // the silent consumer queue.
+ EXPECT_EQ(1u, consumer_queue_->count());
+ EXPECT_EQ(kBufferCount - 2, producer_queue_->count());
+ EXPECT_TRUE(producer_queue_->HandleQueueEvents());
+ EXPECT_EQ(kBufferCount - 1, producer_queue_->count());
+}
+
struct TestMetadata {
char a;
int32_t b;
@@ -140,11 +235,15 @@
for (auto mi : ms) {
size_t slot;
LocalHandle fence;
- auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
+ auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
+ ASSERT_TRUE(p1_status.ok());
+ auto p1 = p1_status.take();
ASSERT_NE(nullptr, p1);
ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0);
TestMetadata mo;
- auto c1 = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
+ auto c1_status = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
+ ASSERT_TRUE(c1_status.ok());
+ auto c1 = c1_status.take();
ASSERT_EQ(mi.a, mo.a);
ASSERT_EQ(mi.b, mo.b);
ASSERT_EQ(mi.c, mo.c);
@@ -159,14 +258,16 @@
int64_t mi = 3;
size_t slot;
LocalHandle fence;
- auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
+ auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
+ ASSERT_TRUE(p1_status.ok());
+ auto p1 = p1_status.take();
ASSERT_NE(nullptr, p1);
ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0);
int32_t mo;
// Acquire a buffer with mismatched metadata is not OK.
- auto c1 = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
- ASSERT_EQ(nullptr, c1);
+ auto c1_status = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
+ ASSERT_FALSE(c1_status.ok());
}
TEST_F(BufferHubQueueTest, TestEnqueue) {
@@ -175,13 +276,15 @@
size_t slot;
LocalHandle fence;
- auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
+ auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
+ ASSERT_TRUE(p1_status.ok());
+ auto p1 = p1_status.take();
ASSERT_NE(nullptr, p1);
int64_t mo;
producer_queue_->Enqueue(p1, slot);
- auto c1 = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
- ASSERT_EQ(nullptr, c1);
+ auto c1_status = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
+ ASSERT_FALSE(c1_status.ok());
}
TEST_F(BufferHubQueueTest, TestAllocateBuffer) {
@@ -190,13 +293,16 @@
size_t s1;
AllocateBuffer();
LocalHandle fence;
- auto p1 = producer_queue_->Dequeue(0, &s1, &fence);
+ auto p1_status = producer_queue_->Dequeue(0, &s1, &fence);
+ ASSERT_TRUE(p1_status.ok());
+ auto p1 = p1_status.take();
ASSERT_NE(nullptr, p1);
// producer queue is exhausted
size_t s2;
- auto p2_null = producer_queue_->Dequeue(0, &s2, &fence);
- ASSERT_EQ(nullptr, p2_null);
+ auto p2_status = producer_queue_->Dequeue(0, &s2, &fence);
+ ASSERT_FALSE(p2_status.ok());
+ ASSERT_EQ(ETIMEDOUT, p2_status.error());
// dynamically add buffer.
AllocateBuffer();
@@ -204,7 +310,9 @@
ASSERT_EQ(producer_queue_->capacity(), 2U);
// now we can dequeue again
- auto p2 = producer_queue_->Dequeue(0, &s2, &fence);
+ p2_status = producer_queue_->Dequeue(0, &s2, &fence);
+ ASSERT_TRUE(p2_status.ok());
+ auto p2 = p2_status.take();
ASSERT_NE(nullptr, p2);
ASSERT_EQ(producer_queue_->count(), 0U);
// p1 and p2 should have different slot number
@@ -217,20 +325,24 @@
int64_t seq = 1;
ASSERT_EQ(p1->Post(LocalHandle(), seq), 0);
size_t cs1, cs2;
- auto c1 = consumer_queue_->Dequeue(0, &cs1, &seq, &fence);
+ auto c1_status = consumer_queue_->Dequeue(0, &cs1, &seq, &fence);
+ ASSERT_TRUE(c1_status.ok());
+ auto c1 = c1_status.take();
ASSERT_NE(nullptr, c1);
ASSERT_EQ(consumer_queue_->count(), 0U);
ASSERT_EQ(consumer_queue_->capacity(), 2U);
ASSERT_EQ(cs1, s1);
ASSERT_EQ(p2->Post(LocalHandle(), seq), 0);
- auto c2 = consumer_queue_->Dequeue(0, &cs2, &seq, &fence);
+ auto c2_status = consumer_queue_->Dequeue(0, &cs2, &seq, &fence);
+ ASSERT_TRUE(c2_status.ok());
+ auto c2 = c2_status.take();
ASSERT_NE(nullptr, c2);
ASSERT_EQ(cs2, s2);
}
TEST_F(BufferHubQueueTest, TestUsageSetMask) {
- const int set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
+ const uint32_t set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
ASSERT_TRUE(CreateQueues<int64_t>(set_mask, 0, 0, 0));
// When allocation, leave out |set_mask| from usage bits on purpose.
@@ -238,15 +350,17 @@
int ret = producer_queue_->AllocateBuffer(
kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage & ~set_mask,
kBufferSliceCount, &slot);
- ASSERT_EQ(ret, 0);
+ ASSERT_EQ(0, ret);
LocalHandle fence;
- auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
+ auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
+ ASSERT_TRUE(p1_status.ok());
+ auto p1 = p1_status.take();
ASSERT_EQ(p1->usage() & set_mask, set_mask);
}
TEST_F(BufferHubQueueTest, TestUsageClearMask) {
- const int clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
+ const uint32_t clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
ASSERT_TRUE(CreateQueues<int64_t>(0, clear_mask, 0, 0));
// When allocation, add |clear_mask| into usage bits on purpose.
@@ -254,15 +368,17 @@
int ret = producer_queue_->AllocateBuffer(
kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage | clear_mask,
kBufferSliceCount, &slot);
- ASSERT_EQ(ret, 0);
+ ASSERT_EQ(0, ret);
LocalHandle fence;
- auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
- ASSERT_EQ(p1->usage() & clear_mask, 0);
+ auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
+ ASSERT_TRUE(p1_status.ok());
+ auto p1 = p1_status.take();
+ ASSERT_EQ(0u, p1->usage() & clear_mask);
}
TEST_F(BufferHubQueueTest, TestUsageDenySetMask) {
- const int deny_set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
+ const uint32_t deny_set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
ASSERT_TRUE(CreateQueues<int64_t>(0, 0, deny_set_mask, 0));
// Now that |deny_set_mask| is illegal, allocation without those bits should
@@ -281,7 +397,7 @@
}
TEST_F(BufferHubQueueTest, TestUsageDenyClearMask) {
- const int deny_clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
+ const uint32_t deny_clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
ASSERT_TRUE(CreateQueues<int64_t>(0, 0, 0, deny_clear_mask));
// Now that clearing |deny_clear_mask| is illegal (i.e. setting these bits are
diff --git a/libs/vr/libdisplay/Android.bp b/libs/vr/libdisplay/Android.bp
index de2a56e..41baef8 100644
--- a/libs/vr/libdisplay/Android.bp
+++ b/libs/vr/libdisplay/Android.bp
@@ -15,16 +15,14 @@
sourceFiles = [
"native_buffer_queue.cpp",
"display_client.cpp",
- "display_manager_client_impl.cpp",
- "display_rpc.cpp",
+ "display_manager_client.cpp",
+ "display_protocol.cpp",
"dummy_native_window.cpp",
+ "frame_history.cpp",
"gl_fenced_flush.cpp",
"graphics.cpp",
"late_latch.cpp",
- "video_mesh_surface_client.cpp",
"vsync_client.cpp",
- "screenshot_client.cpp",
- "frame_history.cpp",
]
localIncludeFiles = [
diff --git a/libs/vr/libdisplay/display_client.cpp b/libs/vr/libdisplay/display_client.cpp
index ef50a0f..dbee9f2 100644
--- a/libs/vr/libdisplay/display_client.cpp
+++ b/libs/vr/libdisplay/display_client.cpp
@@ -8,10 +8,11 @@
#include <mutex>
-#include <private/dvr/display_rpc.h>
+#include <private/dvr/display_protocol.h>
#include <private/dvr/late_latch.h>
#include <private/dvr/native_buffer.h>
+using android::pdx::ErrorStatus;
using android::pdx::LocalHandle;
using android::pdx::LocalChannelHandle;
using android::pdx::Status;
@@ -20,99 +21,61 @@
namespace android {
namespace dvr {
+namespace display {
-SurfaceClient::SurfaceClient(LocalChannelHandle channel_handle,
- SurfaceType type)
- : Client{pdx::default_transport::ClientChannel::Create(
- std::move(channel_handle))},
- type_(type) {}
-
-SurfaceClient::SurfaceClient(const std::string& endpoint_path, SurfaceType type)
- : Client{pdx::default_transport::ClientChannelFactory::Create(
- endpoint_path),
- kInfiniteTimeout},
- type_(type) {}
-
-int SurfaceClient::GetMetadataBufferFd(LocalHandle* out_fd) {
- auto buffer_producer = GetMetadataBuffer();
- if (!buffer_producer)
- return -ENOMEM;
-
- *out_fd = buffer_producer->GetBlobFd();
- return 0;
-}
-
-std::shared_ptr<BufferProducer> SurfaceClient::GetMetadataBuffer() {
- if (!metadata_buffer_) {
- auto status = InvokeRemoteMethod<DisplayRPC::GetMetadataBuffer>();
- if (!status) {
- ALOGE(
- "SurfaceClient::AllocateMetadataBuffer: Failed to allocate buffer: "
- "%s",
+Surface::Surface(LocalChannelHandle channel_handle, int* error)
+ : BASE{pdx::default_transport::ClientChannel::Create(
+ std::move(channel_handle))} {
+ auto status = InvokeRemoteMethod<DisplayProtocol::GetSurfaceInfo>();
+ if (!status) {
+ ALOGE("Surface::Surface: Failed to get surface info: %s",
status.GetErrorMessage().c_str());
- return nullptr;
- }
-
- metadata_buffer_ = BufferProducer::Import(status.take());
- }
-
- return metadata_buffer_;
-}
-
-DisplaySurfaceClient::DisplaySurfaceClient(int width, int height, int format,
- int usage, int flags)
- : BASE(DisplayRPC::kClientPath, SurfaceTypeEnum::Normal),
- width_(width),
- height_(height),
- format_(format),
- usage_(usage),
- flags_(flags),
- z_order_(0),
- visible_(true),
- exclude_from_blur_(false),
- blur_behind_(true),
- mapped_metadata_buffer_(nullptr) {
- auto status = InvokeRemoteMethod<DisplayRPC::CreateSurface>(
- width, height, format, usage, flags);
- if (!status) {
- ALOGE(
- "DisplaySurfaceClient::DisplaySurfaceClient: Failed to create display "
- "surface: %s",
- status.GetErrorMessage().c_str());
Close(status.error());
+ if (error)
+ *error = status.error();
}
+
+ surface_id_ = status.get().surface_id;
+ z_order_ = status.get().z_order;
+ visible_ = status.get().visible;
}
-void DisplaySurfaceClient::SetVisible(bool visible) {
- SetAttributes({{DisplaySurfaceAttributeEnum::Visible,
- DisplaySurfaceAttributeValue{visible}}});
+Surface::Surface(const SurfaceAttributes& attributes, int* error)
+ : BASE{pdx::default_transport::ClientChannelFactory::Create(
+ DisplayProtocol::kClientPath),
+ kInfiniteTimeout} {
+ auto status = InvokeRemoteMethod<DisplayProtocol::CreateSurface>(attributes);
+ if (!status) {
+ ALOGE("Surface::Surface: Failed to create display surface: %s",
+ status.GetErrorMessage().c_str());
+ Close(status.error());
+ if (error)
+ *error = status.error();
+ }
+
+ surface_id_ = status.get().surface_id;
+ z_order_ = status.get().z_order;
+ visible_ = status.get().visible;
}
-void DisplaySurfaceClient::SetZOrder(int z_order) {
- SetAttributes({{DisplaySurfaceAttributeEnum::ZOrder,
- DisplaySurfaceAttributeValue{z_order}}});
+Status<void> Surface::SetVisible(bool visible) {
+ return SetAttributes(
+ {{SurfaceAttribute::Visible, SurfaceAttributeValue{visible}}});
}
-void DisplaySurfaceClient::SetExcludeFromBlur(bool exclude_from_blur) {
- SetAttributes({{DisplaySurfaceAttributeEnum::ExcludeFromBlur,
- DisplaySurfaceAttributeValue{exclude_from_blur}}});
+Status<void> Surface::SetZOrder(int z_order) {
+ return SetAttributes(
+ {{SurfaceAttribute::ZOrder, SurfaceAttributeValue{z_order}}});
}
-void DisplaySurfaceClient::SetBlurBehind(bool blur_behind) {
- SetAttributes({{DisplaySurfaceAttributeEnum::BlurBehind,
- DisplaySurfaceAttributeValue{blur_behind}}});
-}
-
-void DisplaySurfaceClient::SetAttributes(
- const DisplaySurfaceAttributes& attributes) {
- Status<int> status =
- InvokeRemoteMethod<DisplayRPC::SetAttributes>(attributes);
+Status<void> Surface::SetAttributes(const SurfaceAttributes& attributes) {
+ auto status = InvokeRemoteMethod<DisplayProtocol::SetAttributes>(attributes);
if (!status) {
ALOGE(
- "DisplaySurfaceClient::SetAttributes: Failed to set display surface "
+ "Surface::SetAttributes: Failed to set display surface "
"attributes: %s",
status.GetErrorMessage().c_str());
- return;
+ return status.error_status();
}
// Set the local cached copies of the attributes we care about from the full
@@ -122,159 +85,130 @@
const auto* variant = &attribute.second;
bool invalid_value = false;
switch (key) {
- case DisplaySurfaceAttributeEnum::Visible:
+ case SurfaceAttribute::Visible:
invalid_value =
!IfAnyOf<int32_t, int64_t, bool>::Get(variant, &visible_);
break;
- case DisplaySurfaceAttributeEnum::ZOrder:
+ case SurfaceAttribute::ZOrder:
invalid_value = !IfAnyOf<int32_t>::Get(variant, &z_order_);
break;
- case DisplaySurfaceAttributeEnum::ExcludeFromBlur:
- invalid_value =
- !IfAnyOf<int32_t, int64_t, bool>::Get(variant, &exclude_from_blur_);
- break;
- case DisplaySurfaceAttributeEnum::BlurBehind:
- invalid_value =
- !IfAnyOf<int32_t, int64_t, bool>::Get(variant, &blur_behind_);
- break;
}
if (invalid_value) {
ALOGW(
- "DisplaySurfaceClient::SetAttributes: Failed to set display "
- "surface attribute '%s' because of incompatible type: %d",
- DisplaySurfaceAttributeEnum::ToString(key).c_str(), variant->index());
- }
- }
-}
-
-std::shared_ptr<ProducerQueue> DisplaySurfaceClient::GetProducerQueue() {
- if (producer_queue_ == nullptr) {
- // Create producer queue through DisplayRPC
- auto status = InvokeRemoteMethod<DisplayRPC::CreateBufferQueue>();
- if (!status) {
- ALOGE(
- "DisplaySurfaceClient::GetProducerQueue: failed to create producer "
- "queue: %s",
- status.GetErrorMessage().c_str());
- return nullptr;
- }
-
- producer_queue_ = ProducerQueue::Import(status.take());
- }
- return producer_queue_;
-}
-
-volatile DisplaySurfaceMetadata* DisplaySurfaceClient::GetMetadataBufferPtr() {
- if (!mapped_metadata_buffer_) {
- if (auto buffer_producer = GetMetadataBuffer()) {
- void* addr = nullptr;
- const int ret = buffer_producer->GetBlobReadWritePointer(
- sizeof(DisplaySurfaceMetadata), &addr);
- if (ret < 0) {
- ALOGE(
- "DisplaySurfaceClient::GetMetadataBufferPtr: Failed to map surface "
- "metadata: %s",
- strerror(-ret));
- return nullptr;
- }
- mapped_metadata_buffer_ = static_cast<DisplaySurfaceMetadata*>(addr);
+ "Surface::SetAttributes: Failed to set display surface "
+ "attribute %d because of incompatible type: %d",
+ key, variant->index());
}
}
- return mapped_metadata_buffer_;
+ return {};
}
-LocalChannelHandle DisplaySurfaceClient::CreateVideoMeshSurface() {
- auto status = InvokeRemoteMethod<DisplayRPC::CreateVideoMeshSurface>();
+Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue() {
+ ALOGD_IF(TRACE, "Surface::CreateQueue: Creating empty queue.");
+ auto status = InvokeRemoteMethod<DisplayProtocol::CreateQueue>(0);
if (!status) {
- ALOGE(
- "DisplaySurfaceClient::CreateVideoMeshSurface: Failed to create "
- "video mesh surface: %s",
- status.GetErrorMessage().c_str());
+ ALOGE("Surface::CreateQueue: Failed to create queue: %s",
+ status.GetErrorMessage().c_str());
+ return status.error_status();
}
- return status.take();
+
+ auto producer_queue = ProducerQueue::Import(status.take());
+ if (!producer_queue) {
+ ALOGE("Surface::CreateQueue: Failed to import producer queue!");
+ return ErrorStatus(ENOMEM);
+ }
+
+ return {std::move(producer_queue)};
+}
+
+Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(uint32_t width,
+ uint32_t height,
+ uint32_t format,
+ uint64_t usage,
+ size_t capacity) {
+ ALOGD_IF(TRACE,
+ "Surface::CreateQueue: width=%u height=%u format=%u usage=%" PRIx64
+ " capacity=%zu",
+ width, height, format, usage, capacity);
+ auto status = CreateQueue();
+ if (!status)
+ return status.error_status();
+
+ auto producer_queue = status.take();
+
+ ALOGD_IF(TRACE, "Surface::CreateQueue: Allocating %zu buffers...", capacity);
+ for (size_t i = 0; i < capacity; i++) {
+ size_t slot;
+ const size_t kSliceCount = 1;
+ const int ret = producer_queue->AllocateBuffer(width, height, format, usage,
+ kSliceCount, &slot);
+ if (ret < 0) {
+ ALOGE(
+ "Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
+ producer_queue->id(), strerror(-ret));
+ return ErrorStatus(ENOMEM);
+ }
+ ALOGD_IF(
+ TRACE,
+ "Surface::CreateQueue: Allocated buffer at slot=%zu of capacity=%zu",
+ slot, capacity);
+ }
+
+ return {std::move(producer_queue)};
}
DisplayClient::DisplayClient(int* error)
: BASE(pdx::default_transport::ClientChannelFactory::Create(
- DisplayRPC::kClientPath),
+ DisplayProtocol::kClientPath),
kInfiniteTimeout) {
if (error)
*error = Client::error();
}
-int DisplayClient::GetDisplayMetrics(SystemDisplayMetrics* metrics) {
- auto status = InvokeRemoteMethod<DisplayRPC::GetMetrics>();
- if (!status) {
- ALOGE("DisplayClient::GetDisplayMetrics: Failed to get metrics: %s",
- status.GetErrorMessage().c_str());
- return -status.error();
- }
-
- *metrics = status.get();
- return 0;
+Status<Metrics> DisplayClient::GetDisplayMetrics() {
+ return InvokeRemoteMethod<DisplayProtocol::GetMetrics>();
}
-pdx::Status<void> DisplayClient::SetViewerParams(
- const ViewerParams& viewer_params) {
- auto status = InvokeRemoteMethod<DisplayRPC::SetViewerParams>(viewer_params);
- if (!status) {
- ALOGE("DisplayClient::SetViewerParams: Failed to set viewer params: %s",
- status.GetErrorMessage().c_str());
- }
- return status;
+Status<std::unique_ptr<Surface>> DisplayClient::CreateSurface(
+ const SurfaceAttributes& attributes) {
+ int error;
+ if (auto client = Surface::Create(attributes, &error))
+ return {std::move(client)};
+ else
+ return ErrorStatus(error);
}
-int DisplayClient::GetLastFrameEdsTransform(LateLatchOutput* ll_out) {
- auto status = InvokeRemoteMethod<DisplayRPC::GetEdsCapture>();
- if (!status) {
- ALOGE(
- "DisplayClient::GetLastFrameLateLatch: Failed to get most recent late"
- " latch: %s",
- status.GetErrorMessage().c_str());
- return -status.error();
- }
-
- if (status.get().size() != sizeof(LateLatchOutput)) {
- ALOGE(
- "DisplayClient::GetLastFrameLateLatch: Error expected to receive %zu "
- "bytes but received %zu",
- sizeof(LateLatchOutput), status.get().size());
- return -EIO;
- }
-
- *ll_out = *reinterpret_cast<const LateLatchOutput*>(status.get().data());
- return 0;
-}
-
-std::unique_ptr<DisplaySurfaceClient> DisplayClient::CreateDisplaySurface(
- int width, int height, int format, int usage, int flags) {
- return DisplaySurfaceClient::Create(width, height, format, usage, flags);
-}
-
-std::unique_ptr<IonBuffer> DisplayClient::GetNamedBuffer(
+Status<std::unique_ptr<IonBuffer>> DisplayClient::GetNamedBuffer(
const std::string& name) {
- auto status = InvokeRemoteMethod<DisplayRPC::GetNamedBuffer>(name);
+ auto status = InvokeRemoteMethod<DisplayProtocol::GetNamedBuffer>(name);
if (!status) {
ALOGE(
- "DisplayClient::GetNamedBuffer: Failed to get pose buffer. name=%s, "
+ "DisplayClient::GetNamedBuffer: Failed to get named buffer: name=%s; "
"error=%s",
name.c_str(), status.GetErrorMessage().c_str());
- return nullptr;
+ return status.error_status();
}
auto ion_buffer = std::make_unique<IonBuffer>();
- status.take().Import(ion_buffer.get());
- return ion_buffer;
+ auto native_buffer_handle = status.take();
+ const int ret = native_buffer_handle.Import(ion_buffer.get());
+ if (ret < 0) {
+ ALOGE(
+ "DisplayClient::GetNamedBuffer: Failed to import named buffer: "
+ "name=%s; error=%s",
+ name.c_str(), strerror(-ret));
+ return ErrorStatus(-ret);
+ }
+
+ return {std::move(ion_buffer)};
}
-bool DisplayClient::IsVrAppRunning() {
- auto status = InvokeRemoteMethod<DisplayRPC::IsVrAppRunning>();
- if (!status)
- return 0;
- return static_cast<bool>(status.get());
+Status<bool> DisplayClient::IsVrAppRunning() {
+ return InvokeRemoteMethod<DisplayProtocol::IsVrAppRunning>();
}
+} // namespace display
} // namespace dvr
} // namespace android
diff --git a/libs/vr/libdisplay/display_manager_client.cpp b/libs/vr/libdisplay/display_manager_client.cpp
new file mode 100644
index 0000000..82dacf7
--- /dev/null
+++ b/libs/vr/libdisplay/display_manager_client.cpp
@@ -0,0 +1,78 @@
+#include "include/private/dvr/display_manager_client.h"
+
+#include <pdx/default_transport/client_channel_factory.h>
+#include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/buffer_hub_queue_client.h>
+#include <private/dvr/display_protocol.h>
+#include <utils/Log.h>
+
+using android::pdx::ErrorStatus;
+using android::pdx::LocalChannelHandle;
+using android::pdx::Transaction;
+
+namespace android {
+namespace dvr {
+namespace display {
+
+DisplayManagerClient::DisplayManagerClient()
+ : BASE(pdx::default_transport::ClientChannelFactory::Create(
+ DisplayManagerProtocol::kClientPath)) {}
+
+DisplayManagerClient::~DisplayManagerClient() {}
+
+pdx::Status<std::vector<display::SurfaceState>>
+DisplayManagerClient::GetSurfaceState() {
+ auto status = InvokeRemoteMethod<DisplayManagerProtocol::GetSurfaceState>();
+ if (!status) {
+ ALOGE(
+ "DisplayManagerClient::GetSurfaceState: Failed to get surface info: %s",
+ status.GetErrorMessage().c_str());
+ }
+
+ return status;
+}
+
+pdx::Status<std::unique_ptr<IonBuffer>> DisplayManagerClient::SetupNamedBuffer(
+ const std::string& name, size_t size, uint64_t usage) {
+ auto status = InvokeRemoteMethod<DisplayManagerProtocol::SetupNamedBuffer>(
+ name, size, usage);
+ if (!status) {
+ ALOGE(
+ "DisplayManagerClient::SetupPoseBuffer: Failed to create the named "
+ "buffer %s",
+ status.GetErrorMessage().c_str());
+ return status.error_status();
+ }
+
+ auto ion_buffer = std::make_unique<IonBuffer>();
+ auto native_buffer_handle = status.take();
+ const int ret = native_buffer_handle.Import(ion_buffer.get());
+ if (ret < 0) {
+ ALOGE(
+ "DisplayClient::GetNamedBuffer: Failed to import named buffer: "
+ "name=%s; error=%s",
+ name.c_str(), strerror(-ret));
+ return ErrorStatus(-ret);
+ }
+
+ return {std::move(ion_buffer)};
+}
+
+pdx::Status<std::unique_ptr<ConsumerQueue>>
+DisplayManagerClient::GetSurfaceQueue(int surface_id, int queue_id) {
+ auto status = InvokeRemoteMethod<DisplayManagerProtocol::GetSurfaceQueue>(
+ surface_id, queue_id);
+ if (!status) {
+ ALOGE(
+ "DisplayManagerClient::GetSurfaceQueue: Failed to get queue for "
+ "surface_id=%d queue_id=%d: %s",
+ surface_id, queue_id, status.GetErrorMessage().c_str());
+ return status.error_status();
+ }
+
+ return {ConsumerQueue::Import(status.take())};
+}
+
+} // namespace display
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libdisplay/display_manager_client_impl.cpp b/libs/vr/libdisplay/display_manager_client_impl.cpp
deleted file mode 100644
index 44b3c4b..0000000
--- a/libs/vr/libdisplay/display_manager_client_impl.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-#include "include/private/dvr/display_manager_client_impl.h"
-
-#include <pdx/default_transport/client_channel_factory.h>
-#include <private/dvr/buffer_hub_client.h>
-#include <private/dvr/display_rpc.h>
-#include <utils/Log.h>
-
-using android::pdx::LocalChannelHandle;
-using android::pdx::Transaction;
-
-namespace android {
-namespace dvr {
-
-DisplayManagerClient::DisplayManagerClient()
- : BASE(pdx::default_transport::ClientChannelFactory::Create(
- DisplayManagerRPC::kClientPath)) {}
-
-DisplayManagerClient::~DisplayManagerClient() {}
-
-int DisplayManagerClient::GetSurfaceList(
- std::vector<DisplaySurfaceInfo>* surface_list) {
- auto status = InvokeRemoteMethod<DisplayManagerRPC::GetSurfaceList>();
- if (!status) {
- ALOGE(
- "DisplayManagerClient::GetSurfaceList: Failed to get surface info: %s",
- status.GetErrorMessage().c_str());
- return -status.error();
- }
-
- *surface_list = status.take();
- return 0;
-}
-
-std::unique_ptr<IonBuffer> DisplayManagerClient::SetupNamedBuffer(
- const std::string& name, size_t size, uint64_t producer_usage,
- uint64_t consumer_usage) {
- auto status = InvokeRemoteMethod<DisplayManagerRPC::SetupNamedBuffer>(
- name, size, producer_usage, consumer_usage);
- if (!status) {
- ALOGE(
- "DisplayManagerClient::SetupNamedBuffer: Failed to create the named "
- "buffer: name=%s, error=%s",
- name.c_str(), status.GetErrorMessage().c_str());
- return {};
- }
-
- auto ion_buffer = std::make_unique<IonBuffer>();
- status.take().Import(ion_buffer.get());
- return ion_buffer;
-}
-
-} // namespace dvr
-} // namespace android
diff --git a/libs/vr/libdisplay/display_protocol.cpp b/libs/vr/libdisplay/display_protocol.cpp
new file mode 100644
index 0000000..773f9a5
--- /dev/null
+++ b/libs/vr/libdisplay/display_protocol.cpp
@@ -0,0 +1,13 @@
+#include "include/private/dvr/display_protocol.h"
+
+namespace android {
+namespace dvr {
+namespace display {
+
+constexpr char DisplayProtocol::kClientPath[];
+constexpr char DisplayManagerProtocol::kClientPath[];
+constexpr char VSyncProtocol::kClientPath[];
+
+} // namespace display
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libdisplay/display_rpc.cpp b/libs/vr/libdisplay/display_rpc.cpp
deleted file mode 100644
index f5693bd..0000000
--- a/libs/vr/libdisplay/display_rpc.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "include/private/dvr/display_rpc.h"
-
-namespace android {
-namespace dvr {
-
-constexpr char DisplayRPC::kClientPath[];
-constexpr char DisplayManagerRPC::kClientPath[];
-constexpr char DisplayScreenshotRPC::kClientPath[];
-constexpr char DisplayVSyncRPC::kClientPath[];
-
-} // namespace dvr
-} // namespace android
diff --git a/libs/vr/libdisplay/graphics.cpp b/libs/vr/libdisplay/graphics.cpp
index 2abdf8e..f0e37f8 100644
--- a/libs/vr/libdisplay/graphics.cpp
+++ b/libs/vr/libdisplay/graphics.cpp
@@ -13,20 +13,19 @@
#endif
#include <vulkan/vulkan.h>
+#include <dvr/dvr_display_types.h>
#include <pdx/file_handle.h>
#include <private/dvr/clock_ns.h>
#include <private/dvr/debug.h>
-#include <private/dvr/display_types.h>
#include <private/dvr/frame_history.h>
#include <private/dvr/gl_fenced_flush.h>
#include <private/dvr/graphics/vr_gl_extensions.h>
#include <private/dvr/graphics_private.h>
#include <private/dvr/late_latch.h>
#include <private/dvr/native_buffer_queue.h>
-#include <private/dvr/sensor_constants.h>
-#include <private/dvr/video_mesh_surface_client.h>
-#include <private/dvr/vsync_client.h>
#include <private/dvr/platform_defines.h>
+#include <private/dvr/sensor_constants.h>
+#include <private/dvr/vsync_client.h>
#include <android/native_window.h>
@@ -35,21 +34,30 @@
#define EGL_CONTEXT_MINOR_VERSION 0x30FB
#endif
+using android::pdx::ErrorStatus;
using android::pdx::LocalHandle;
using android::pdx::LocalChannelHandle;
+using android::pdx::Status;
-using android::dvr::DisplaySurfaceAttributeEnum;
-using android::dvr::DisplaySurfaceAttributeValue;
+using android::dvr::display::DisplayClient;
+using android::dvr::display::Metrics;
+using android::dvr::display::NativeBufferQueue;
+using android::dvr::display::Surface;
+using android::dvr::display::SurfaceAttribute;
+using android::dvr::display::SurfaceAttributes;
+using android::dvr::display::SurfaceAttributeValue;
+using android::dvr::VSyncClient;
namespace {
// TODO(urbanus): revisit once we have per-platform usage config in place.
-constexpr int kDefaultDisplaySurfaceUsage =
- GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE |
- GRALLOC_USAGE_QCOM_FRAMEBUFFER_COMPRESSION;
-constexpr int kDefaultDisplaySurfaceFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+constexpr uint64_t kDefaultDisplaySurfaceUsage =
+ GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET |
+ GRALLOC1_PRODUCER_USAGE_PRIVATE_1 | GRALLOC1_CONSUMER_USAGE_CLIENT_TARGET |
+ GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;
+constexpr uint32_t kDefaultDisplaySurfaceFormat = HAL_PIXEL_FORMAT_RGBA_8888;
// TODO(alexst): revisit this count when HW encode is available for casting.
-constexpr int kDefaultBufferCount = 4;
+constexpr size_t kDefaultBufferCount = 4;
// Use with dvrBeginRenderFrame to disable EDS for the current frame.
constexpr float32x4_t DVR_POSE_NO_EDS = {10.0f, 0.0f, 0.0f, 0.0f};
@@ -279,51 +287,119 @@
return 0;
}
-} // anonymous namespace
+// Utility structure to hold info related to creating a surface.
+struct SurfaceResult {
+ std::shared_ptr<Surface> surface;
+ Metrics metrics;
+ uint32_t width;
+ uint32_t height;
+ uint32_t format;
+ uint64_t usage;
+ size_t capacity;
+ int geometry;
+ bool direct_surface;
+};
-// TODO(hendrikw): When we remove the calls to this in native_window.cpp, move
-// this back into the anonymous namespace
-std::shared_ptr<android::dvr::DisplaySurfaceClient> CreateDisplaySurfaceClient(
- struct DvrSurfaceParameter* parameters,
- /*out*/ android::dvr::SystemDisplayMetrics* metrics) {
- auto client = android::dvr::DisplayClient::Create();
- if (!client) {
- ALOGE("Failed to create display client!");
- return nullptr;
+Status<std::tuple<std::shared_ptr<android::dvr::ProducerQueue>,
+ std::shared_ptr<android::dvr::BufferProducer>,
+ volatile DisplaySurfaceMetadata*>>
+CreateMetadataBuffer(const std::shared_ptr<Surface>& surface,
+ bool direct_surface) {
+ std::shared_ptr<android::dvr::ProducerQueue> queue;
+ std::shared_ptr<android::dvr::BufferProducer> buffer;
+
+ if (!direct_surface) {
+ auto queue_status = surface->CreateQueue(
+ sizeof(DisplaySurfaceMetadata), 1, HAL_PIXEL_FORMAT_BLOB,
+ GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET |
+ GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN |
+ GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER,
+ 1);
+ if (!queue_status) {
+ ALOGE("CreateMetadataBuffer: Failed to create queue: %s",
+ queue_status.GetErrorMessage().c_str());
+ return queue_status.error_status();
+ }
+
+ queue = queue_status.take();
+ LocalHandle fence;
+ size_t slot;
+ auto buffer_status = queue->Dequeue(-1, &slot, &fence);
+ if (!buffer_status) {
+ ALOGE("CreateMetadataBuffer: Failed to dequeue buffer: %s",
+ buffer_status.GetErrorMessage().c_str());
+ return buffer_status.error_status();
+ }
+ buffer = buffer_status.take();
+ } else {
+ buffer = android::dvr::BufferProducer::CreateUncachedBlob(
+ sizeof(DisplaySurfaceMetadata));
+ if (!buffer) {
+ ALOGE("CreateMetadataBuffer: Failed to create stand-in buffer!");
+ return ErrorStatus(ENOMEM);
+ }
}
- const int ret = client->GetDisplayMetrics(metrics);
+ void* address = nullptr;
+ int ret =
+ buffer->GetBlobReadWritePointer(sizeof(DisplaySurfaceMetadata), &address);
+
if (ret < 0) {
- ALOGE("Failed to get display metrics: %s", strerror(-ret));
- return nullptr;
+ ALOGE("CreateMetadataBuffer: Failed to map buffer: %s", strerror(-ret));
+ return ErrorStatus(-ret);
+ }
+
+ // Post the buffer so that the compositor can retrieve it from the consumer
+ // queue.
+ ret = buffer->Post<void>(LocalHandle{});
+ if (ret < 0) {
+ ALOGE("CreateMetadataBuffer: Failed to post buffer: %s", strerror(-ret));
+ return ErrorStatus(-ret);
+ }
+
+ ALOGD_IF(TRACE, "CreateMetadataBuffer: queue_id=%d buffer_id=%d address=%p",
+ queue ? queue->id() : -1, buffer->id(), address);
+ return {{std::move(queue), std::move(buffer),
+ static_cast<DisplaySurfaceMetadata*>(address)}};
+}
+
+} // anonymous namespace
+
+Status<SurfaceResult> CreateSurface(struct DvrSurfaceParameter* parameters) {
+ int error;
+ auto client = DisplayClient::Create(&error);
+ if (!client) {
+ ALOGE("CreateApplicationSurface: Failed to create display client!");
+ return ErrorStatus(error);
+ }
+
+ auto metrics_status = client->GetDisplayMetrics();
+ if (!metrics_status) {
+ ALOGE("CreateApplicationSurface: Failed to get display metrics: %s",
+ metrics_status.GetErrorMessage().c_str());
+ return metrics_status.error_status();
}
// Parameters that may be modified by the parameters array. Some of these are
// here for future expansion.
- int request_width = -1;
- int request_height = -1;
- int request_flags = 0;
+
+ uint32_t request_width = metrics_status.get().display_width;
+ uint32_t request_height = metrics_status.get().display_width;
+ uint32_t request_format = kDefaultDisplaySurfaceFormat;
+ uint64_t request_usage = kDefaultDisplaySurfaceUsage;
+ size_t request_capacity = kDefaultBufferCount;
+ int request_geometry = DVR_SURFACE_GEOMETRY_SINGLE;
bool disable_distortion = false;
bool disable_stabilization = false;
bool disable_cac = false;
- bool request_visible = true;
+ bool request_visible = false;
bool vertical_flip = false;
+ bool direct_surface = false;
int request_z_order = 0;
- bool request_exclude_from_blur = false;
- bool request_blur_behind = true;
- int request_format = kDefaultDisplaySurfaceFormat;
- int request_usage = kDefaultDisplaySurfaceUsage;
- int geometry_type = DVR_SURFACE_GEOMETRY_SINGLE;
// Handle parameter inputs.
for (auto p = parameters; p && p->key != DVR_SURFACE_PARAMETER_NONE; ++p) {
switch (p->key) {
- case DVR_SURFACE_PARAMETER_WIDTH_IN:
- request_width = p->value;
- break;
- case DVR_SURFACE_PARAMETER_HEIGHT_IN:
- request_height = p->value;
- break;
case DVR_SURFACE_PARAMETER_DISABLE_DISTORTION_IN:
disable_distortion = !!p->value;
break;
@@ -339,20 +415,23 @@
case DVR_SURFACE_PARAMETER_Z_ORDER_IN:
request_z_order = p->value;
break;
- case DVR_SURFACE_PARAMETER_EXCLUDE_FROM_BLUR_IN:
- request_exclude_from_blur = !!p->value;
- break;
- case DVR_SURFACE_PARAMETER_BLUR_BEHIND_IN:
- request_blur_behind = !!p->value;
- break;
case DVR_SURFACE_PARAMETER_VERTICAL_FLIP_IN:
vertical_flip = !!p->value;
break;
- case DVR_SURFACE_PARAMETER_GEOMETRY_IN:
- geometry_type = p->value;
+ case DVR_SURFACE_PARAMETER_DIRECT_IN:
+ direct_surface = !!p->value;
+ break;
+ case DVR_SURFACE_PARAMETER_WIDTH_IN:
+ request_width = p->value;
+ break;
+ case DVR_SURFACE_PARAMETER_HEIGHT_IN:
+ request_height = p->value;
break;
case DVR_SURFACE_PARAMETER_FORMAT_IN:
- request_format = DvrToHalSurfaceFormat(p->value);
+ request_format = p->value;
+ break;
+ case DVR_SURFACE_PARAMETER_GEOMETRY_IN:
+ request_geometry = p->value;
break;
case DVR_SURFACE_PARAMETER_ENABLE_LATE_LATCH_IN:
case DVR_SURFACE_PARAMETER_CREATE_GL_CONTEXT_IN:
@@ -376,113 +455,90 @@
case DVR_SURFACE_PARAMETER_VK_SWAPCHAIN_IMAGE_FORMAT_OUT:
break;
default:
- ALOGE("Invalid display surface parameter: key=%d value=%" PRId64,
- p->key, p->value);
- return nullptr;
+ ALOGE(
+ "CreateSurface: Invalid display surface parameter: key=%d "
+ "value=%" PRId64,
+ p->key, p->value);
+ return ErrorStatus(EINVAL);
}
}
- request_flags |= disable_distortion
- ? DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION
- : 0;
- request_flags |=
- disable_stabilization ? DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_EDS : 0;
- request_flags |=
- disable_cac ? DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_CAC : 0;
- request_flags |= vertical_flip ? DVR_DISPLAY_SURFACE_FLAGS_VERTICAL_FLIP : 0;
- request_flags |= (geometry_type == DVR_SURFACE_GEOMETRY_SEPARATE_2)
- ? DVR_DISPLAY_SURFACE_FLAGS_GEOMETRY_SEPARATE_2
- : 0;
+ // TODO(eieio): Setup a "surface flags" attribute based on the surface
+ // parameters gathered above.
+ SurfaceAttributes surface_attributes;
- if (request_width == -1) {
- request_width = disable_distortion ? metrics->display_native_width
- : metrics->distorted_width;
- if (!disable_distortion &&
- geometry_type == DVR_SURFACE_GEOMETRY_SEPARATE_2) {
- // The metrics always return the single wide buffer resolution.
- // When split between eyes, we need to halve the width of the surface.
- request_width /= 2;
- }
- }
- if (request_height == -1) {
- request_height = disable_distortion ? metrics->display_native_height
- : metrics->distorted_height;
+ surface_attributes[SurfaceAttribute::Direct] = direct_surface;
+ surface_attributes[SurfaceAttribute::Visible] = request_visible;
+ surface_attributes[SurfaceAttribute::ZOrder] = request_z_order;
+
+ auto surface_status = Surface::CreateSurface(surface_attributes);
+ if (!surface_status) {
+ ALOGE("CreateSurface: Failed to create surface: %s",
+ surface_status.GetErrorMessage().c_str());
+ return surface_status.error_status();
}
- std::shared_ptr<android::dvr::DisplaySurfaceClient> surface =
- client->CreateDisplaySurface(request_width, request_height,
- request_format, request_usage,
- request_flags);
- surface->SetAttributes(
- {{DisplaySurfaceAttributeEnum::Visible,
- DisplaySurfaceAttributeValue{request_visible}},
- {DisplaySurfaceAttributeEnum::ZOrder,
- DisplaySurfaceAttributeValue{request_z_order}},
- {DisplaySurfaceAttributeEnum::ExcludeFromBlur,
- DisplaySurfaceAttributeValue{request_exclude_from_blur}},
- {DisplaySurfaceAttributeEnum::BlurBehind,
- DisplaySurfaceAttributeValue{request_blur_behind}}});
+ return {{surface_status.take(), metrics_status.get(), request_width,
+ request_height, request_format, request_usage, request_capacity,
+ request_geometry, direct_surface}};
+}
+
+// TODO(hendrikw): When we remove the calls to this in native_window.cpp, move
+// this back into the anonymous namespace
+Status<SurfaceResult> CreateApplicationSurface(
+ struct DvrSurfaceParameter* parameters) {
+ auto surface_status = CreateSurface(parameters);
+ if (!surface_status)
+ return surface_status;
// Handle parameter output requests down here so we can return surface info.
for (auto p = parameters; p && p->key != DVR_SURFACE_PARAMETER_NONE; ++p) {
switch (p->key) {
case DVR_SURFACE_PARAMETER_DISPLAY_WIDTH_OUT:
- *static_cast<int32_t*>(p->value_out) = metrics->display_native_width;
+ *static_cast<int32_t*>(p->value_out) =
+ surface_status.get().metrics.display_width;
break;
case DVR_SURFACE_PARAMETER_DISPLAY_HEIGHT_OUT:
- *static_cast<int32_t*>(p->value_out) = metrics->display_native_height;
- break;
- case DVR_SURFACE_PARAMETER_SURFACE_WIDTH_OUT:
- *static_cast<int32_t*>(p->value_out) = surface->width();
- break;
- case DVR_SURFACE_PARAMETER_SURFACE_HEIGHT_OUT:
- *static_cast<int32_t*>(p->value_out) = surface->height();
- break;
- case DVR_SURFACE_PARAMETER_INTER_LENS_METERS_OUT:
- *static_cast<float*>(p->value_out) = metrics->inter_lens_distance_m;
- break;
- case DVR_SURFACE_PARAMETER_LEFT_FOV_LRBT_OUT:
- for (int i = 0; i < 4; ++i) {
- float* float_values_out = static_cast<float*>(p->value_out);
- float_values_out[i] = metrics->left_fov_lrbt[i];
- }
- break;
- case DVR_SURFACE_PARAMETER_RIGHT_FOV_LRBT_OUT:
- for (int i = 0; i < 4; ++i) {
- float* float_values_out = static_cast<float*>(p->value_out);
- float_values_out[i] = metrics->right_fov_lrbt[i];
- }
+ *static_cast<int32_t*>(p->value_out) =
+ surface_status.get().metrics.display_height;
break;
case DVR_SURFACE_PARAMETER_VSYNC_PERIOD_OUT:
- *static_cast<uint64_t*>(p->value_out) = metrics->vsync_period_ns;
+ *static_cast<uint64_t*>(p->value_out) =
+ surface_status.get().metrics.vsync_period_ns;
break;
+ case DVR_SURFACE_PARAMETER_SURFACE_WIDTH_OUT:
+ *static_cast<uint32_t*>(p->value_out) = surface_status.get().width;
+ break;
+ case DVR_SURFACE_PARAMETER_SURFACE_HEIGHT_OUT:
+ *static_cast<uint32_t*>(p->value_out) = surface_status.get().height;
+ break;
+
default:
break;
}
}
- return surface;
+ return surface_status;
}
-extern "C" int dvrGetNativeDisplayDimensions(int* native_width,
- int* native_height) {
+extern "C" int dvrGetNativeDisplayDimensions(int* display_width,
+ int* display_height) {
int error = 0;
- auto client = android::dvr::DisplayClient::Create(&error);
+ auto client = DisplayClient::Create(&error);
if (!client) {
- ALOGE("Failed to create display client!");
- return error;
+ ALOGE("dvrGetNativeDisplayDimensions: Failed to create display client!");
+ return -error;
}
- android::dvr::SystemDisplayMetrics metrics;
- const int ret = client->GetDisplayMetrics(&metrics);
-
- if (ret != 0) {
- ALOGE("Failed to get display metrics!");
- return ret;
+ auto metrics_status = client->GetDisplayMetrics();
+ if (!metrics_status) {
+ ALOGE("dvrGetNativeDisplayDimensions: Failed to get display metrics: %s",
+ metrics_status.GetErrorMessage().c_str());
+ return -metrics_status.error();
}
- *native_width = static_cast<int>(metrics.display_native_width);
- *native_height = static_cast<int>(metrics.display_native_height);
+ *display_width = static_cast<int>(metrics_status.get().display_width);
+ *display_height = static_cast<int>(metrics_status.get().display_height);
return 0;
}
@@ -524,9 +580,12 @@
} vk;
// Display surface, metrics, and buffer management members.
- std::shared_ptr<android::dvr::DisplaySurfaceClient> display_surface;
- android::dvr::SystemDisplayMetrics display_metrics;
- std::unique_ptr<android::dvr::NativeBufferQueue> buffer_queue;
+ std::shared_ptr<Surface> display_surface;
+ uint32_t width;
+ uint32_t height;
+ uint32_t format;
+ Metrics display_metrics;
+ std::unique_ptr<NativeBufferQueue> buffer_queue;
android::dvr::NativeBufferProducer* current_buffer;
bool buffer_already_posted;
@@ -536,16 +595,17 @@
android::dvr::FrameHistory frame_history;
+ // Metadata queue and buffer.
+ // TODO(eieio): Remove the queue once one-off buffers are supported as a
+ // surface primitive element.
+ std::shared_ptr<android::dvr::ProducerQueue> metadata_queue;
+ std::shared_ptr<android::dvr::BufferProducer> metadata_buffer;
// Mapped surface metadata (ie: for pose delivery with presented frames).
- volatile android::dvr::DisplaySurfaceMetadata* surface_metadata;
+ volatile DisplaySurfaceMetadata* surface_metadata;
// LateLatch support.
std::unique_ptr<android::dvr::LateLatch> late_latch;
- // Video mesh support.
- std::vector<std::shared_ptr<android::dvr::VideoMeshSurfaceClient>>
- video_mesh_surfaces;
-
private:
// ANativeWindow function implementations
std::mutex lock_;
@@ -616,7 +676,7 @@
int dvrGraphicsContextCreate(struct DvrSurfaceParameter* parameters,
DvrGraphicsContext** return_graphics_context) {
- std::unique_ptr<DvrGraphicsContext> context(new DvrGraphicsContext);
+ auto context = std::make_unique<DvrGraphicsContext>();
// See whether we're using GL or Vulkan
for (auto p = parameters; p && p->key != DVR_SURFACE_PARAMETER_NONE; ++p) {
@@ -681,46 +741,66 @@
return -EINVAL;
}
- context->display_surface =
- CreateDisplaySurfaceClient(parameters, &context->display_metrics);
- if (!context->display_surface) {
- ALOGE("Error: failed to create display surface client");
- return -ECOMM;
+ auto surface_status = CreateApplicationSurface(parameters);
+ if (!surface_status) {
+ ALOGE("dvrGraphicsContextCreate: Failed to create surface: %s",
+ surface_status.GetErrorMessage().c_str());
+ return -surface_status.error();
}
- context->buffer_queue.reset(new android::dvr::NativeBufferQueue(
- context->gl.egl_display, context->display_surface, kDefaultBufferCount));
+ auto surface_result = surface_status.take();
+
+ context->display_surface = surface_result.surface;
+ context->display_metrics = surface_result.metrics;
+ context->width = surface_result.width;
+ context->height = surface_result.height;
+ context->format = surface_result.format;
+
+ // Create an empty queue. NativeBufferQueue allocates the buffers for this
+ // queue.
+ auto queue_status = context->display_surface->CreateQueue();
+ if (!queue_status) {
+ ALOGE("dvrGraphicsContextCreate: Failed to create queue: %s",
+ queue_status.GetErrorMessage().c_str());
+ return -queue_status.error();
+ }
+
+ context->buffer_queue.reset(new NativeBufferQueue(
+ context->gl.egl_display, queue_status.take(), surface_result.width,
+ surface_result.height, surface_result.format, surface_result.usage,
+ surface_result.capacity));
+
+ // Create the metadata buffer.
+ auto metadata_status = CreateMetadataBuffer(context->display_surface,
+ surface_result.direct_surface);
+ if (!metadata_status) {
+ ALOGE("dvrGraphicsContextCreate: Failed to create metadata buffer: %s",
+ metadata_status.GetErrorMessage().c_str());
+ return -metadata_status.error();
+ }
+ std::tie(context->metadata_queue, context->metadata_buffer,
+ context->surface_metadata) = metadata_status.take();
// The way the call sequence works we need 1 more than the buffer queue
// capacity to store data for all pending frames
- context->frame_history.Reset(context->buffer_queue->GetQueueCapacity() + 1);
+ context->frame_history.Reset(context->buffer_queue->capacity() + 1);
- context->vsync_client = android::dvr::VSyncClient::Create();
+ context->vsync_client = VSyncClient::Create();
if (!context->vsync_client) {
- ALOGE("Error: failed to create vsync client");
+ ALOGE("dvrGraphicsContextCreate: failed to create vsync client");
return -ECOMM;
}
context->timerfd.Reset(timerfd_create(CLOCK_MONOTONIC, 0));
if (!context->timerfd) {
- ALOGE("Error: timerfd_create failed because: %s", strerror(errno));
+ ALOGE("dvrGraphicsContextCreate: timerfd_create failed because: %s",
+ strerror(errno));
return -EPERM;
}
- context->surface_metadata = context->display_surface->GetMetadataBufferPtr();
- if (!context->surface_metadata) {
- ALOGE("Error: surface metadata allocation failed");
- return -ENOMEM;
- }
-
- ALOGI("buffer: %d x %d\n", context->display_surface->width(),
- context->display_surface->height());
-
if (context->graphics_api == DVR_GRAPHICS_API_GLES) {
- context->gl.texture_count = (context->display_surface->flags() &
- DVR_DISPLAY_SURFACE_FLAGS_GEOMETRY_SEPARATE_2)
- ? 2
- : 1;
+ context->gl.texture_count =
+ (surface_result.geometry == DVR_SURFACE_GEOMETRY_SEPARATE_2) ? 2 : 1;
// Create the GL textures.
glGenTextures(context->gl.texture_count, context->gl.texture_id);
@@ -761,14 +841,9 @@
// Initialize late latch.
if (is_late_latch) {
- LocalHandle fd;
- int ret = context->display_surface->GetMetadataBufferFd(&fd);
- if (ret == 0) {
- context->late_latch.reset(
- new android::dvr::LateLatch(true, std::move(fd)));
- } else {
- ALOGE("Error: failed to get surface metadata buffer fd for late latch");
- }
+ LocalHandle fd = context->metadata_buffer->GetBlobFd();
+ context->late_latch.reset(
+ new android::dvr::LateLatch(true, std::move(fd)));
}
} else if (context->graphics_api == DVR_GRAPHICS_API_VULKAN) {
VkResult result = VK_SUCCESS;
@@ -968,7 +1043,7 @@
std::lock_guard<std::mutex> autolock(self->lock_);
if (!self->current_buffer) {
- self->current_buffer = self->buffer_queue.get()->Dequeue();
+ self->current_buffer = self->buffer_queue->Dequeue();
}
ATRACE_ASYNC_BEGIN("BufferDraw", self->current_buffer->buffer()->id());
*fence_fd = self->current_buffer->ClaimReleaseFence().Release();
@@ -1035,7 +1110,7 @@
}
}
if (do_enqueue) {
- self->buffer_queue.get()->Enqueue(native_buffer);
+ self->buffer_queue->Enqueue(native_buffer);
}
if (fence_fd >= 0)
close(fence_fd);
@@ -1053,13 +1128,13 @@
switch (what) {
case NATIVE_WINDOW_WIDTH:
- *value = self->display_surface->width();
+ *value = self->width;
return android::NO_ERROR;
case NATIVE_WINDOW_HEIGHT:
- *value = self->display_surface->height();
+ *value = self->height;
return android::NO_ERROR;
case NATIVE_WINDOW_FORMAT:
- *value = self->display_surface->format();
+ *value = self->format;
return android::NO_ERROR;
case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
*value = 1;
@@ -1071,10 +1146,10 @@
*value = 1;
return android::NO_ERROR;
case NATIVE_WINDOW_DEFAULT_WIDTH:
- *value = self->display_surface->width();
+ *value = self->width;
return android::NO_ERROR;
case NATIVE_WINDOW_DEFAULT_HEIGHT:
- *value = self->display_surface->height();
+ *value = self->height;
return android::NO_ERROR;
case NATIVE_WINDOW_TRANSFORM_HINT:
*value = 0;
@@ -1201,8 +1276,7 @@
// we don't touch it here.
float32x4_t is_late_latch = DVR_POSE_LATE_LATCH;
if (render_pose_orientation[0] != is_late_latch[0]) {
- volatile android::dvr::DisplaySurfaceMetadata* data =
- graphics_context->surface_metadata;
+ volatile DisplaySurfaceMetadata* data = graphics_context->surface_metadata;
uint32_t buffer_index =
graphics_context->current_buffer->surface_buffer_index();
ALOGE_IF(TRACE, "write pose index %d %f %f", buffer_index,
@@ -1249,6 +1323,7 @@
CHECK_GL();
return 0;
}
+
int dvrBeginRenderFrameEdsVk(DvrGraphicsContext* graphics_context,
float32x4_t render_pose_orientation,
float32x4_t render_pose_translation,
@@ -1426,7 +1501,7 @@
auto buffer = graphics_context->current_buffer->buffer().get();
ATRACE_ASYNC_BEGIN("BufferPost", buffer->id());
- int result = buffer->Post<uint64_t>(LocalHandle(), 0);
+ int result = buffer->Post<void>(LocalHandle());
if (result < 0)
ALOGE("Buffer post failed: %d (%s)", result, strerror(-result));
}
@@ -1457,7 +1532,7 @@
ATRACE_ASYNC_END("BufferDraw", buffer->id());
if (!graphics_context->buffer_already_posted) {
ATRACE_ASYNC_BEGIN("BufferPost", buffer->id());
- int result = buffer->Post<uint64_t>(fence_fd, 0);
+ int result = buffer->Post<void>(fence_fd);
if (result < 0)
ALOGE("Buffer post failed: %d (%s)", result, strerror(-result));
}
@@ -1520,7 +1595,7 @@
extern "C" int dvrGraphicsSurfaceGetVisible(
DvrGraphicsContext* graphics_context) {
- return graphics_context->display_surface->visible() ? 1 : 0;
+ return !!graphics_context->display_surface->visible();
}
extern "C" void dvrGraphicsSurfaceSetZOrder(
@@ -1532,45 +1607,3 @@
DvrGraphicsContext* graphics_context) {
return graphics_context->display_surface->z_order();
}
-
-extern "C" DvrVideoMeshSurface* dvrGraphicsVideoMeshSurfaceCreate(
- DvrGraphicsContext* graphics_context) {
- auto display_surface = graphics_context->display_surface;
- // A DisplaySurface must be created prior to the creation of a
- // VideoMeshSurface.
- LOG_ALWAYS_FATAL_IF(display_surface == nullptr);
-
- LocalChannelHandle surface_handle = display_surface->CreateVideoMeshSurface();
- if (!surface_handle.valid()) {
- return nullptr;
- }
-
- std::unique_ptr<DvrVideoMeshSurface> surface(new DvrVideoMeshSurface);
- surface->client =
- android::dvr::VideoMeshSurfaceClient::Import(std::move(surface_handle));
-
- // TODO(jwcai) The next line is not needed...
- auto producer_queue = surface->client->GetProducerQueue();
- return surface.release();
-}
-
-extern "C" void dvrGraphicsVideoMeshSurfaceDestroy(
- DvrVideoMeshSurface* surface) {
- delete surface;
-}
-
-extern "C" void dvrGraphicsVideoMeshSurfacePresent(
- DvrGraphicsContext* graphics_context, DvrVideoMeshSurface* surface,
- const int eye, const float* transform) {
- volatile android::dvr::VideoMeshSurfaceMetadata* metadata =
- surface->client->GetMetadataBufferPtr();
-
- const uint32_t graphics_buffer_index =
- graphics_context->current_buffer->surface_buffer_index();
-
- for (int i = 0; i < 4; ++i) {
- metadata->transform[graphics_buffer_index][eye].val[i] = {
- transform[i + 0], transform[i + 4], transform[i + 8], transform[i + 12],
- };
- }
-}
diff --git a/libs/vr/libdisplay/include/dvr/dvr_display_types.h b/libs/vr/libdisplay/include/dvr/dvr_display_types.h
new file mode 100644
index 0000000..25364d8
--- /dev/null
+++ b/libs/vr/libdisplay/include/dvr/dvr_display_types.h
@@ -0,0 +1,65 @@
+#ifndef ANDROID_DVR_DISPLAY_TYPES_H_
+#define ANDROID_DVR_DISPLAY_TYPES_H_
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+// Define types used in pose buffer fields. These types have atomicity
+// guarantees that are useful in lock-free shared memory ring buffers.
+#ifdef __ARM_NEON
+#include <arm_neon.h>
+#else
+#ifndef __FLOAT32X4T_86
+#define __FLOAT32X4T_86
+typedef float float32x4_t __attribute__((__vector_size__(16)));
+typedef struct float32x4x4_t { float32x4_t val[4]; };
+#endif
+#endif
+
+// VrFlinger display manager surface state snapshots per surface flags
+// indicating what changed since the last snapshot.
+enum {
+ // No changes.
+ DVR_SURFACE_UPDATE_FLAGS_NONE = 0,
+ // This surface is new.
+ DVR_SURFACE_UPDATE_FLAGS_NEW_SURFACE = (1 << 0),
+ // Buffer queues added/removed.
+ DVR_SURFACE_UPDATE_FLAGS_BUFFERS_CHANGED = (1 << 1),
+ // Visibility/z-order changed.
+ DVR_SURFACE_UPDATE_FLAGS_VISIBILITY_CHANGED = (1 << 2),
+ // Generic attributes changed.
+ DVR_SURFACE_UPDATE_FLAGS_ATTRIBUTES_CHANGED = (1 << 3),
+};
+
+// Surface attribute keys. VrFlinger defines keys in the negative integer space.
+// The compositor is free to use keys in the positive integer space for
+// implementation-defined purposes.
+enum {
+ // DIRECT: bool
+ // Determines whether a direct surface is created (compositor output) or an
+ // application surface. Defaults to false (application surface). May only be
+ // set to true by a process with either UID=root or UID validated with
+ // IsTrustedUid() (VrCore).
+ DVR_SURFACE_ATTRIBUTE_DIRECT = -3,
+ // Z_ORDER: int32_t
+ // Interpreted by VrFlinger only on direct surfaces to order the corresponding
+ // hardware layers. More positive values render on top of more negative
+ // values.
+ DVR_SURFACE_ATTRIBUTE_Z_ORDER = -2,
+ // VISIBLE: bool
+ // Interpreted by VrFlinger only on direct surfaces to determine whether a
+ // surface is assigned to a hardware layer or ignored.
+ DVR_SURFACE_ATTRIBUTE_VISIBLE = -1,
+ // INVALID
+ // Invalid key. No attributes should have this key.
+ DVR_SURFACE_ATTRIBUTE_INVALID = 0,
+ // FIRST_USER_KEY
+ // VrFlinger ingores any keys with this value or greater, passing them to the
+ // compositor through surface state query results.
+ DVR_SURFACE_ATTRIBUTE_FIRST_USER_KEY = 1,
+};
+
+__END_DECLS
+
+#endif // ANDROID_DVR_DISPLAY_TYPES_H_
diff --git a/libs/vr/libdisplay/include/dvr/graphics.h b/libs/vr/libdisplay/include/dvr/graphics.h
index ac8b27f..c83a698 100644
--- a/libs/vr/libdisplay/include/dvr/graphics.h
+++ b/libs/vr/libdisplay/include/dvr/graphics.h
@@ -9,7 +9,7 @@
#else
#ifndef __FLOAT32X4T_86
#define __FLOAT32X4T_86
-typedef float float32x4_t __attribute__ ((__vector_size__ (16)));
+typedef float float32x4_t __attribute__((__vector_size__(16)));
typedef struct float32x4x4_t { float32x4_t val[4]; };
#endif
#endif
@@ -112,6 +112,10 @@
// VK_SWAPCHAIN_IMAGE_FORMAT: In Vulkan mode, the VkFormat of the swapchain
// images will be returned here.
DVR_SURFACE_PARAMETER_VK_SWAPCHAIN_IMAGE_FORMAT_OUT,
+ // DIRECT: Whether the surface goes directly to the display or to the
+ // compositor. Default is 0 (compositor). Only processes with either uid=root
+ // (test tools) or uid validated by IsTrustedUid() may set this to 1.
+ DVR_SURFACE_PARAMETER_DIRECT_IN,
};
enum {
@@ -439,8 +443,7 @@
// Present a VideoMeshSurface with the current video mesh transfromation matrix.
void dvrGraphicsVideoMeshSurfacePresent(DvrGraphicsContext* graphics_context,
DvrVideoMeshSurface* surface,
- const int eye,
- const float* transform);
+ const int eye, const float* transform);
__END_DECLS
diff --git a/libs/vr/libdisplay/include/private/dvr/display_client.h b/libs/vr/libdisplay/include/private/dvr/display_client.h
index fec2ea5..668532d 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_client.h
@@ -6,112 +6,73 @@
#include <pdx/file_handle.h>
#include <private/dvr/buffer_hub_client.h>
#include <private/dvr/buffer_hub_queue_client.h>
-#include <private/dvr/display_rpc.h>
+#include <private/dvr/display_protocol.h>
namespace android {
namespace dvr {
+namespace display {
-struct LateLatchOutput;
-
-// Abstract base class for all surface types maintained in DVR's display
-// service.
-// TODO(jwcai) Explain more, surface is a channel...
-class SurfaceClient : public pdx::Client {
+class Surface : public pdx::ClientBase<Surface> {
public:
- using LocalChannelHandle = pdx::LocalChannelHandle;
- SurfaceType type() const { return type_; }
+ // Utility named constructor. This can be removed once ClientBase::Create is
+ // refactored to return Status<T> types.
+ static pdx::Status<std::unique_ptr<Surface>> CreateSurface(
+ const SurfaceAttributes& attributes) {
+ int error;
+ pdx::Status<std::unique_ptr<Surface>> status;
+ if (auto surface = Create(attributes, &error))
+ status.SetValue(std::move(surface));
+ else
+ status.SetError(error);
+ return status;
+ }
- // Get the shared memory metadata buffer fd for this display surface. If it is
- // not yet allocated, this will allocate it.
- int GetMetadataBufferFd(pdx::LocalHandle* out_fd);
-
- // Allocate the single metadata buffer for providing metadata associated with
- // posted buffers for this surface. This can be used to provide rendered poses
- // for EDS, for example. The buffer format is defined by the struct
- // DisplaySurfaceMetadata.
- // The first call to this method will allocate the buffer in via IPC to the
- // display surface.
- std::shared_ptr<BufferProducer> GetMetadataBuffer();
-
- protected:
- SurfaceClient(LocalChannelHandle channel_handle, SurfaceType type);
- SurfaceClient(const std::string& endpoint_path, SurfaceType type);
-
- private:
- SurfaceType type_;
- std::shared_ptr<BufferProducer> metadata_buffer_;
-};
-
-// DisplaySurfaceClient represents the client interface to a displayd display
-// surface.
-class DisplaySurfaceClient
- : public pdx::ClientBase<DisplaySurfaceClient, SurfaceClient> {
- public:
- using LocalHandle = pdx::LocalHandle;
-
- int width() const { return width_; }
- int height() const { return height_; }
- int format() const { return format_; }
- int usage() const { return usage_; }
- int flags() const { return flags_; }
+ int surface_id() const { return surface_id_; }
int z_order() const { return z_order_; }
bool visible() const { return visible_; }
- void SetVisible(bool visible);
- void SetZOrder(int z_order);
- void SetExcludeFromBlur(bool exclude_from_blur);
- void SetBlurBehind(bool blur_behind);
- void SetAttributes(const DisplaySurfaceAttributes& attributes);
+ pdx::Status<void> SetVisible(bool visible);
+ pdx::Status<void> SetZOrder(int z_order);
+ pdx::Status<void> SetAttributes(const SurfaceAttributes& attributes);
- // Get the producer end of the buffer queue that transports graphics buffer
- // from the application side to the compositor side.
- std::shared_ptr<ProducerQueue> GetProducerQueue();
+ // Creates an empty queue.
+ pdx::Status<std::unique_ptr<ProducerQueue>> CreateQueue();
- // Get the shared memory metadata buffer for this display surface. If it is
- // not yet allocated, this will allocate it.
- volatile DisplaySurfaceMetadata* GetMetadataBufferPtr();
-
- // Create a VideoMeshSurface that is attached to the display sruface.
- LocalChannelHandle CreateVideoMeshSurface();
+ // Creates a queue and populates it with |capacity| buffers of the specified
+ // parameters.
+ pdx::Status<std::unique_ptr<ProducerQueue>> CreateQueue(uint32_t width,
+ uint32_t height,
+ uint32_t format,
+ uint64_t usage,
+ size_t capacity);
private:
friend BASE;
- DisplaySurfaceClient(int width, int height, int format, int usage, int flags);
+ int surface_id_ = -1;
+ int z_order_ = 0;
+ bool visible_ = false;
- int width_;
- int height_;
- int format_;
- int usage_;
- int flags_;
- int z_order_;
- bool visible_;
- bool exclude_from_blur_;
- bool blur_behind_;
- DisplaySurfaceMetadata* mapped_metadata_buffer_;
+ // TODO(eieio,avakulenko): Remove error param once pdx::ClientBase::Create()
+ // returns Status<T>.
+ explicit Surface(const SurfaceAttributes& attributes, int* error = nullptr);
+ explicit Surface(pdx::LocalChannelHandle channel_handle,
+ int* error = nullptr);
- // TODO(jwcai) Add support for multiple queues.
- std::shared_ptr<ProducerQueue> producer_queue_;
-
- DisplaySurfaceClient(const DisplaySurfaceClient&) = delete;
- void operator=(const DisplaySurfaceClient&) = delete;
+ Surface(const Surface&) = delete;
+ void operator=(const Surface&) = delete;
};
class DisplayClient : public pdx::ClientBase<DisplayClient> {
public:
- int GetDisplayMetrics(SystemDisplayMetrics* metrics);
- pdx::Status<void> SetViewerParams(const ViewerParams& viewer_params);
-
- // Pull the latest eds pose data from the display service renderer
- int GetLastFrameEdsTransform(LateLatchOutput* ll_out);
-
- std::unique_ptr<DisplaySurfaceClient> CreateDisplaySurface(
- int width, int height, int format, int usage, int flags);
-
- std::unique_ptr<IonBuffer> GetNamedBuffer(const std::string& name);
+ pdx::Status<Metrics> GetDisplayMetrics();
+ pdx::Status<std::unique_ptr<IonBuffer>> GetNamedBuffer(
+ const std::string& name);
+ pdx::Status<std::unique_ptr<Surface>> CreateSurface(
+ const SurfaceAttributes& attributes);
// Temporary query for current VR status. Will be removed later.
- bool IsVrAppRunning();
+ pdx::Status<bool> IsVrAppRunning();
private:
friend BASE;
@@ -122,6 +83,7 @@
void operator=(const DisplayClient&) = delete;
};
+} // namespace display
} // namespace dvr
} // namespace android
diff --git a/libs/vr/libdisplay/include/private/dvr/display_manager_client.h b/libs/vr/libdisplay/include/private/dvr/display_manager_client.h
new file mode 100644
index 0000000..fea8415
--- /dev/null
+++ b/libs/vr/libdisplay/include/private/dvr/display_manager_client.h
@@ -0,0 +1,51 @@
+#ifndef ANDROID_DVR_DISPLAY_MANAGER_CLIENT_H_
+#define ANDROID_DVR_DISPLAY_MANAGER_CLIENT_H_
+
+#include <string>
+#include <vector>
+
+#include <pdx/client.h>
+#include <pdx/status.h>
+#include <private/dvr/display_protocol.h>
+
+namespace android {
+namespace dvr {
+
+class IonBuffer;
+class ConsumerQueue;
+
+namespace display {
+
+class DisplayManagerClient : public pdx::ClientBase<DisplayManagerClient> {
+ public:
+ ~DisplayManagerClient() override;
+
+ pdx::Status<std::vector<SurfaceState>> GetSurfaceState();
+ pdx::Status<std::unique_ptr<IonBuffer>> SetupNamedBuffer(
+ const std::string& name, size_t size, uint64_t usage);
+ pdx::Status<std::unique_ptr<ConsumerQueue>> GetSurfaceQueue(int surface_id,
+ int queue_id);
+
+ using Client::event_fd;
+
+ pdx::Status<int> GetEventMask(int events) {
+ if (auto* client_channel = GetChannel())
+ return client_channel->GetEventMask(events);
+ else
+ return pdx::ErrorStatus(EINVAL);
+ }
+
+ private:
+ friend BASE;
+
+ DisplayManagerClient();
+
+ DisplayManagerClient(const DisplayManagerClient&) = delete;
+ void operator=(const DisplayManagerClient&) = delete;
+};
+
+} // namespace display
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_DISPLAY_MANAGER_CLIENT_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h b/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h
deleted file mode 100644
index b0a7d13..0000000
--- a/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef ANDROID_DVR_DISPLAY_MANAGER_CLIENT_IMPL_H_
-#define ANDROID_DVR_DISPLAY_MANAGER_CLIENT_IMPL_H_
-
-#include <vector>
-
-#include <pdx/client.h>
-#include <private/dvr/display_rpc.h>
-
-namespace android {
-namespace dvr {
-
-class BufferProducer;
-
-class DisplayManagerClient : public pdx::ClientBase<DisplayManagerClient> {
- public:
- ~DisplayManagerClient() override;
-
- int GetSurfaceList(std::vector<DisplaySurfaceInfo>* surface_list);
-
- std::unique_ptr<IonBuffer> SetupNamedBuffer(const std::string& name,
- size_t size,
- uint64_t producer_usage,
- uint64_t consumer_usage);
-
- using Client::event_fd;
- using Client::GetChannel;
-
- private:
- friend BASE;
-
- DisplayManagerClient();
-
- DisplayManagerClient(const DisplayManagerClient&) = delete;
- void operator=(const DisplayManagerClient&) = delete;
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_DISPLAY_MANAGER_CLIENT_IMPL_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/display_protocol.h b/libs/vr/libdisplay/include/private/dvr/display_protocol.h
new file mode 100644
index 0000000..f34d61f
--- /dev/null
+++ b/libs/vr/libdisplay/include/private/dvr/display_protocol.h
@@ -0,0 +1,283 @@
+#ifndef ANDROID_DVR_DISPLAY_PROTOCOL_H_
+#define ANDROID_DVR_DISPLAY_PROTOCOL_H_
+
+#include <sys/types.h>
+
+#include <array>
+#include <map>
+
+#include <dvr/dvr_display_types.h>
+
+#include <pdx/rpc/remote_method.h>
+#include <pdx/rpc/serializable.h>
+#include <pdx/rpc/variant.h>
+#include <private/dvr/bufferhub_rpc.h>
+
+// RPC protocol definitions for DVR display services (VrFlinger).
+
+namespace android {
+namespace dvr {
+namespace display {
+
+// Native display metrics.
+struct Metrics {
+ // Basic display properties.
+ uint32_t display_width;
+ uint32_t display_height;
+ uint32_t display_x_dpi;
+ uint32_t display_y_dpi;
+ uint32_t vsync_period_ns;
+
+ // HMD metrics.
+ // TODO(eieio): Determine how these fields should be populated. On phones
+ // these values are determined at runtime by VrCore based on which headset the
+ // phone is in. On dedicated hardware this needs to come from somewhere else.
+ // Perhaps these should be moved to a separate structure that is returned by a
+ // separate runtime call.
+ uint32_t distorted_width;
+ uint32_t distorted_height;
+ uint32_t hmd_ipd_mm;
+ float inter_lens_distance_m;
+ std::array<float, 4> left_fov_lrbt;
+ std::array<float, 4> right_fov_lrbt;
+
+ private:
+ PDX_SERIALIZABLE_MEMBERS(Metrics, display_width, display_height,
+ display_x_dpi, display_y_dpi, vsync_period_ns,
+ distorted_width, distorted_height, hmd_ipd_mm,
+ inter_lens_distance_m, left_fov_lrbt,
+ right_fov_lrbt);
+};
+
+// Serializable base type for enum structs. Enum structs are easier to use than
+// enum classes, especially for bitmasks. This base type provides common
+// utilities for flags types.
+template <typename Integer>
+class Flags {
+ public:
+ using Base = Flags<Integer>;
+ using Type = Integer;
+
+ Flags(const Integer& value) : value_{value} {}
+ Flags(const Flags&) = default;
+ Flags& operator=(const Flags&) = default;
+
+ Integer value() const { return value_; }
+ operator Integer() const { return value_; }
+
+ bool IsSet(Integer bits) const { return (value_ & bits) == bits; }
+ bool IsClear(Integer bits) const { return (value_ & bits) == 0; }
+
+ void Set(Integer bits) { value_ |= bits; }
+ void Clear(Integer bits) { value_ &= ~bits; }
+
+ Integer operator|(Integer bits) const { return value_ | bits; }
+ Integer operator&(Integer bits) const { return value_ & bits; }
+
+ Flags& operator|=(Integer bits) {
+ value_ |= bits;
+ return *this;
+ }
+ Flags& operator&=(Integer bits) {
+ value_ &= bits;
+ return *this;
+ }
+
+ private:
+ Integer value_;
+
+ PDX_SERIALIZABLE_MEMBERS(Flags<Integer>, value_);
+};
+
+// Flags indicating what changed since last update.
+struct SurfaceUpdateFlags : public Flags<uint32_t> {
+ enum : Type {
+ None = DVR_SURFACE_UPDATE_FLAGS_NONE,
+ NewSurface = DVR_SURFACE_UPDATE_FLAGS_NEW_SURFACE,
+ BuffersChanged = DVR_SURFACE_UPDATE_FLAGS_BUFFERS_CHANGED,
+ VisibilityChanged = DVR_SURFACE_UPDATE_FLAGS_VISIBILITY_CHANGED,
+ AttributesChanged = DVR_SURFACE_UPDATE_FLAGS_ATTRIBUTES_CHANGED,
+ };
+
+ SurfaceUpdateFlags() : Base{None} {}
+ using Base::Base;
+};
+
+// Surface attribute key/value types.
+using SurfaceAttributeKey = int32_t;
+using SurfaceAttributeValue =
+ pdx::rpc::Variant<int32_t, int64_t, bool, float, std::array<float, 2>,
+ std::array<float, 3>, std::array<float, 4>,
+ std::array<float, 8>, std::array<float, 16>>;
+
+// Defined surface attribute keys.
+struct SurfaceAttribute : public Flags<SurfaceAttributeKey> {
+ enum : Type {
+ // Keys in the negative integer space are interpreted by VrFlinger for
+ // direct surfaces.
+ Direct = DVR_SURFACE_ATTRIBUTE_DIRECT,
+ ZOrder = DVR_SURFACE_ATTRIBUTE_Z_ORDER,
+ Visible = DVR_SURFACE_ATTRIBUTE_VISIBLE,
+
+ // Invalid key. May be used to terminate C style lists in public API code.
+ Invalid = DVR_SURFACE_ATTRIBUTE_INVALID,
+
+ // Positive keys are interpreted by the compositor only.
+ FirstUserKey = DVR_SURFACE_ATTRIBUTE_FIRST_USER_KEY,
+ };
+
+ SurfaceAttribute() : Base{Invalid} {}
+ using Base::Base;
+};
+
+// Collection of surface attribute key/value pairs.
+using SurfaceAttributes = std::map<SurfaceAttributeKey, SurfaceAttributeValue>;
+
+struct SurfaceState {
+ int32_t surface_id;
+ int32_t process_id;
+ int32_t user_id;
+
+ SurfaceAttributes surface_attributes;
+ SurfaceUpdateFlags update_flags;
+ std::vector<int32_t> queue_ids;
+
+ // Convenience accessors.
+ bool GetVisible() const {
+ bool bool_value = false;
+ GetAttribute(SurfaceAttribute::Visible, &bool_value,
+ ValidTypes<int32_t, int64_t, bool, float>{});
+ return bool_value;
+ }
+
+ int GetZOrder() const {
+ int int_value = 0;
+ GetAttribute(SurfaceAttribute::ZOrder, &int_value,
+ ValidTypes<int32_t, int64_t, float>{});
+ return int_value;
+ }
+
+ private:
+ template <typename... Types>
+ struct ValidTypes {};
+
+ template <typename ReturnType, typename... Types>
+ bool GetAttribute(SurfaceAttributeKey key, ReturnType* out_value,
+ ValidTypes<Types...>) const {
+ auto search = surface_attributes.find(key);
+ if (search != surface_attributes.end())
+ return pdx::rpc::IfAnyOf<Types...>::Get(&search->second, out_value);
+ else
+ return false;
+ }
+
+ PDX_SERIALIZABLE_MEMBERS(SurfaceState, surface_id, process_id,
+ surface_attributes, update_flags, queue_ids);
+};
+
+struct SurfaceInfo {
+ int surface_id;
+ bool visible;
+ int z_order;
+
+ private:
+ PDX_SERIALIZABLE_MEMBERS(SurfaceInfo, surface_id, visible, z_order);
+};
+
+struct DisplayProtocol {
+ // Service path.
+ static constexpr char kClientPath[] = "system/vr/display/client";
+
+ // Op codes.
+ enum {
+ kOpGetMetrics = 0,
+ kOpGetNamedBuffer,
+ kOpIsVrAppRunning,
+ kOpCreateSurface,
+ kOpGetSurfaceInfo,
+ kOpCreateQueue,
+ kOpSetAttributes,
+ };
+
+ // Aliases.
+ using LocalChannelHandle = pdx::LocalChannelHandle;
+ using Void = pdx::rpc::Void;
+
+ // Methods.
+ PDX_REMOTE_METHOD(GetMetrics, kOpGetMetrics, Metrics(Void));
+ PDX_REMOTE_METHOD(GetNamedBuffer, kOpGetNamedBuffer,
+ LocalNativeBufferHandle(std::string name));
+ PDX_REMOTE_METHOD(IsVrAppRunning, kOpIsVrAppRunning, bool(Void));
+ PDX_REMOTE_METHOD(CreateSurface, kOpCreateSurface,
+ SurfaceInfo(const SurfaceAttributes& attributes));
+ PDX_REMOTE_METHOD(GetSurfaceInfo, kOpGetSurfaceInfo, SurfaceInfo(Void));
+ PDX_REMOTE_METHOD(CreateQueue, kOpCreateQueue,
+ LocalChannelHandle(size_t meta_size_bytes));
+ PDX_REMOTE_METHOD(SetAttributes, kOpSetAttributes,
+ void(const SurfaceAttributes& attributes));
+};
+
+struct DisplayManagerProtocol {
+ // Service path.
+ static constexpr char kClientPath[] = "system/vr/display/manager";
+
+ // Op codes.
+ enum {
+ kOpGetSurfaceState = 0,
+ kOpGetSurfaceQueue,
+ kOpSetupNamedBuffer,
+ };
+
+ // Aliases.
+ using LocalChannelHandle = pdx::LocalChannelHandle;
+ using Void = pdx::rpc::Void;
+
+ // Methods.
+ PDX_REMOTE_METHOD(GetSurfaceState, kOpGetSurfaceState,
+ std::vector<SurfaceState>(Void));
+ PDX_REMOTE_METHOD(GetSurfaceQueue, kOpGetSurfaceQueue,
+ LocalChannelHandle(int surface_id, int queue_id));
+ PDX_REMOTE_METHOD(SetupNamedBuffer, kOpSetupNamedBuffer,
+ LocalNativeBufferHandle(const std::string& name,
+ size_t size, uint64_t usage));
+};
+
+struct VSyncSchedInfo {
+ int64_t vsync_period_ns;
+ int64_t timestamp_ns;
+ uint32_t next_vsync_count;
+
+ private:
+ PDX_SERIALIZABLE_MEMBERS(VSyncSchedInfo, vsync_period_ns, timestamp_ns,
+ next_vsync_count);
+};
+
+struct VSyncProtocol {
+ // Service path.
+ static constexpr char kClientPath[] = "system/vr/display/vsync";
+
+ // Op codes.
+ enum {
+ kOpWait = 0,
+ kOpAck,
+ kOpGetLastTimestamp,
+ kOpGetSchedInfo,
+ kOpAcknowledge,
+ };
+
+ // Aliases.
+ using Void = pdx::rpc::Void;
+ using Timestamp = int64_t;
+
+ // Methods.
+ PDX_REMOTE_METHOD(Wait, kOpWait, Timestamp(Void));
+ PDX_REMOTE_METHOD(GetLastTimestamp, kOpGetLastTimestamp, Timestamp(Void));
+ PDX_REMOTE_METHOD(GetSchedInfo, kOpGetSchedInfo, VSyncSchedInfo(Void));
+ PDX_REMOTE_METHOD(Acknowledge, kOpAcknowledge, void(Void));
+};
+
+} // namespace display
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_DISPLAY_PROTOCOL_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/display_rpc.h b/libs/vr/libdisplay/include/private/dvr/display_rpc.h
deleted file mode 100644
index 778032f..0000000
--- a/libs/vr/libdisplay/include/private/dvr/display_rpc.h
+++ /dev/null
@@ -1,343 +0,0 @@
-#ifndef ANDROID_DVR_DISPLAY_RPC_H_
-#define ANDROID_DVR_DISPLAY_RPC_H_
-
-#include <sys/types.h>
-
-#include <array>
-#include <map>
-
-#include <pdx/rpc/remote_method.h>
-#include <pdx/rpc/serializable.h>
-#include <pdx/rpc/variant.h>
-#include <private/dvr/bufferhub_rpc.h>
-#include <private/dvr/display_types.h>
-
-namespace android {
-namespace dvr {
-
-struct SystemDisplayMetrics {
- uint32_t display_native_width;
- uint32_t display_native_height;
- uint32_t display_x_dpi;
- uint32_t display_y_dpi;
- uint32_t distorted_width;
- uint32_t distorted_height;
- uint32_t vsync_period_ns;
- uint32_t hmd_ipd_mm;
- float inter_lens_distance_m;
- std::array<float, 4> left_fov_lrbt;
- std::array<float, 4> right_fov_lrbt;
-
- private:
- PDX_SERIALIZABLE_MEMBERS(SystemDisplayMetrics, display_native_width,
- display_native_height, display_x_dpi, display_y_dpi,
- distorted_width, distorted_height, vsync_period_ns,
- hmd_ipd_mm, inter_lens_distance_m, left_fov_lrbt,
- right_fov_lrbt);
-};
-
-using SurfaceType = uint32_t;
-struct SurfaceTypeEnum {
- enum : SurfaceType {
- Normal = DVR_SURFACE_TYPE_NORMAL,
- VideoMesh = DVR_SURFACE_TYPE_VIDEO_MESH,
- Overlay = DVR_SURFACE_TYPE_OVERLAY,
- };
-};
-
-using DisplaySurfaceFlags = uint32_t;
-enum class DisplaySurfaceFlagsEnum : DisplaySurfaceFlags {
- DisableSystemEds = DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_EDS,
- DisableSystemDistortion = DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION,
- VerticalFlip = DVR_DISPLAY_SURFACE_FLAGS_VERTICAL_FLIP,
- SeparateGeometry = DVR_DISPLAY_SURFACE_FLAGS_GEOMETRY_SEPARATE_2,
- DisableSystemCac = DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_CAC,
-};
-
-using DisplaySurfaceInfoFlags = uint32_t;
-enum class DisplaySurfaceInfoFlagsEnum : DisplaySurfaceInfoFlags {
- BuffersChanged = DVR_DISPLAY_SURFACE_ITEM_FLAGS_BUFFERS_CHANGED,
-};
-
-using DisplaySurfaceAttributeValue =
- pdx::rpc::Variant<int32_t, int64_t, bool, float, std::array<float, 2>,
- std::array<float, 3>, std::array<float, 4>,
- std::array<float, 16>>;
-using DisplaySurfaceAttribute = uint32_t;
-struct DisplaySurfaceAttributeEnum {
- enum : DisplaySurfaceAttribute {
- ZOrder = DVR_DISPLAY_SURFACE_ATTRIBUTE_Z_ORDER,
- Visible = DVR_DISPLAY_SURFACE_ATTRIBUTE_VISIBLE,
- // Manager only.
- Blur = DVR_DISPLAY_SURFACE_ATTRIBUTE_BLUR,
- // Client only.
- ExcludeFromBlur = DVR_DISPLAY_SURFACE_ATTRIBUTE_EXCLUDE_FROM_BLUR,
- BlurBehind = DVR_DISPLAY_SURFACE_ATTRIBUTE_BLUR_BEHIND,
- };
-
- static std::string ToString(DisplaySurfaceAttribute attribute) {
- switch (attribute) {
- case ZOrder:
- return "z-order";
- case Visible:
- return "visible";
- case Blur:
- return "blur";
- case ExcludeFromBlur:
- return "exclude-from-blur";
- case BlurBehind:
- return "blur-behind";
- default:
- return "unknown";
- }
- }
-};
-
-using DisplaySurfaceAttributes =
- std::map<DisplaySurfaceAttribute, DisplaySurfaceAttributeValue>;
-
-struct DisplaySurfaceInfo {
- int surface_id;
- int process_id;
- SurfaceType type;
- DisplaySurfaceFlags flags;
- DisplaySurfaceInfoFlags info_flags;
- DisplaySurfaceAttributes client_attributes;
- DisplaySurfaceAttributes manager_attributes;
-
- // Convenience accessors.
- bool IsClientVisible() const {
- const auto* variant =
- FindClientAttribute(DisplaySurfaceAttributeEnum::Visible);
- bool bool_value;
- if (variant && pdx::rpc::IfAnyOf<int32_t, int64_t, bool, float>::Get(
- variant, &bool_value))
- return bool_value;
- else
- return false;
- }
-
- int ClientZOrder() const {
- const auto* variant =
- FindClientAttribute(DisplaySurfaceAttributeEnum::ZOrder);
- int int_value;
- if (variant &&
- pdx::rpc::IfAnyOf<int32_t, int64_t, float>::Get(variant, &int_value))
- return int_value;
- else
- return 0;
- }
-
- private:
- const DisplaySurfaceAttributeValue* FindClientAttribute(
- DisplaySurfaceAttribute key) const {
- auto search = client_attributes.find(key);
- return (search != client_attributes.end()) ? &search->second : nullptr;
- }
-
- PDX_SERIALIZABLE_MEMBERS(DisplaySurfaceInfo, surface_id, process_id, type,
- flags, info_flags, client_attributes,
- manager_attributes);
-};
-
-struct AlignmentMarker {
- public:
- float horizontal;
- float vertical;
-
- PDX_SERIALIZABLE_MEMBERS(AlignmentMarker, horizontal, vertical);
-};
-
-struct DaydreamInternalParams {
- public:
- int32_t version;
- std::vector<AlignmentMarker> alignment_markers;
-
- PDX_SERIALIZABLE_MEMBERS(DaydreamInternalParams, version, alignment_markers);
-};
-
-struct ViewerParams {
- public:
- // TODO(hendrikw): Do we need viewer_vendor_name and viewer_model_name?
- float screen_to_lens_distance;
- float inter_lens_distance;
- float screen_center_to_lens_distance;
- std::vector<float> left_eye_field_of_view_angles;
-
- enum VerticalAlignmentType : int32_t {
- BOTTOM = 0, // phone rests against a fixed bottom tray
- CENTER = 1, // phone screen assumed to be centered w.r.t. lenses
- TOP = 2 // phone rests against a fixed top tray
- };
-
- enum EyeOrientation : int32_t {
- kCCW0Degrees = 0,
- kCCW90Degrees = 1,
- kCCW180Degrees = 2,
- kCCW270Degrees = 3,
- kCCW0DegreesMirrored = 4,
- kCCW90DegreesMirrored = 5,
- kCCW180DegreesMirrored = 6,
- kCCW270DegreesMirrored = 7
- };
-
- VerticalAlignmentType vertical_alignment;
- std::vector<EyeOrientation> eye_orientations;
-
- float tray_to_lens_distance;
-
- std::vector<float> distortion_coefficients_r;
- std::vector<float> distortion_coefficients_g;
- std::vector<float> distortion_coefficients_b;
-
- DaydreamInternalParams daydream_internal;
-
- PDX_SERIALIZABLE_MEMBERS(ViewerParams, screen_to_lens_distance,
- inter_lens_distance, screen_center_to_lens_distance,
- left_eye_field_of_view_angles, vertical_alignment,
- eye_orientations, tray_to_lens_distance,
- distortion_coefficients_r, distortion_coefficients_g,
- distortion_coefficients_b, daydream_internal);
-};
-
-struct DisplayRPC {
- // Service path.
- static constexpr char kClientPath[] = "system/vr/display/client";
-
- // Op codes.
- enum {
- kOpGetMetrics = 0,
- kOpGetEdsCapture,
- kOpCreateSurface,
- kOpCreateBufferQueue,
- kOpSetAttributes,
- kOpGetMetadataBuffer,
- kOpCreateVideoMeshSurface,
- kOpVideoMeshSurfaceCreateProducerQueue,
- kOpSetViewerParams,
- kOpGetNamedBuffer,
- kOpIsVrAppRunning,
- };
-
- // Aliases.
- using ByteBuffer = pdx::rpc::BufferWrapper<std::vector<uint8_t>>;
- using LocalChannelHandle = pdx::LocalChannelHandle;
- using Void = pdx::rpc::Void;
-
- // Methods.
- PDX_REMOTE_METHOD(GetMetrics, kOpGetMetrics, SystemDisplayMetrics(Void));
- PDX_REMOTE_METHOD(GetEdsCapture, kOpGetEdsCapture, ByteBuffer(Void));
- PDX_REMOTE_METHOD(CreateSurface, kOpCreateSurface,
- int(int width, int height, int format, int usage,
- DisplaySurfaceFlags flags));
- PDX_REMOTE_METHOD(CreateBufferQueue, kOpCreateBufferQueue,
- LocalChannelHandle(Void));
- PDX_REMOTE_METHOD(SetAttributes, kOpSetAttributes,
- int(const DisplaySurfaceAttributes& attributes));
- PDX_REMOTE_METHOD(GetMetadataBuffer, kOpGetMetadataBuffer,
- LocalChannelHandle(Void));
- // VideoMeshSurface methods
- PDX_REMOTE_METHOD(CreateVideoMeshSurface, kOpCreateVideoMeshSurface,
- LocalChannelHandle(Void));
- PDX_REMOTE_METHOD(VideoMeshSurfaceCreateProducerQueue,
- kOpVideoMeshSurfaceCreateProducerQueue,
- LocalChannelHandle(Void));
- PDX_REMOTE_METHOD(SetViewerParams, kOpSetViewerParams,
- void(const ViewerParams& viewer_params));
- PDX_REMOTE_METHOD(GetNamedBuffer, kOpGetNamedBuffer,
- LocalNativeBufferHandle(const std::string& name));
- PDX_REMOTE_METHOD(IsVrAppRunning, kOpIsVrAppRunning, int(Void));
-};
-
-struct DisplayManagerRPC {
- // Service path.
- static constexpr char kClientPath[] = "system/vr/display/manager";
-
- // Op codes.
- enum {
- kOpGetSurfaceList = 0,
- kOpUpdateSurfaces,
- kOpSetupNamedBuffer,
- };
-
- // Aliases.
- using LocalChannelHandle = pdx::LocalChannelHandle;
- using Void = pdx::rpc::Void;
-
- // Methods.
- PDX_REMOTE_METHOD(GetSurfaceList, kOpGetSurfaceList,
- std::vector<DisplaySurfaceInfo>(Void));
- PDX_REMOTE_METHOD(
- UpdateSurfaces, kOpUpdateSurfaces,
- int(const std::map<int, DisplaySurfaceAttributes>& updates));
- PDX_REMOTE_METHOD(SetupNamedBuffer, kOpSetupNamedBuffer,
- LocalNativeBufferHandle(const std::string& name,
- size_t size,
- uint64_t producer_usage,
- uint64_t consumer_usage));
-};
-
-struct ScreenshotData {
- int width;
- int height;
- std::vector<uint8_t> buffer;
-
- private:
- PDX_SERIALIZABLE_MEMBERS(ScreenshotData, width, height, buffer);
-};
-
-struct DisplayScreenshotRPC {
- // Service path.
- static constexpr char kClientPath[] = "system/vr/display/screenshot";
-
- // Op codes.
- enum {
- kOpGetFormat = 0,
- kOpTakeScreenshot,
- };
-
- using Void = pdx::rpc::Void;
-
- PDX_REMOTE_METHOD(GetFormat, kOpGetFormat, int(Void));
- PDX_REMOTE_METHOD(TakeScreenshot, kOpTakeScreenshot,
- ScreenshotData(int layer_index));
-};
-
-struct VSyncSchedInfo {
- int64_t vsync_period_ns;
- int64_t timestamp_ns;
- uint32_t next_vsync_count;
-
- private:
- PDX_SERIALIZABLE_MEMBERS(VSyncSchedInfo, vsync_period_ns, timestamp_ns,
- next_vsync_count);
-};
-
-struct DisplayVSyncRPC {
- // Service path.
- static constexpr char kClientPath[] = "system/vr/display/vsync";
-
- // Op codes.
- enum {
- kOpWait = 0,
- kOpAck,
- kOpGetLastTimestamp,
- kOpGetSchedInfo,
- kOpAcknowledge,
- };
-
- // Aliases.
- using Void = pdx::rpc::Void;
- using Timestamp = int64_t;
-
- // Methods.
- PDX_REMOTE_METHOD(Wait, kOpWait, Timestamp(Void));
- PDX_REMOTE_METHOD(GetLastTimestamp, kOpGetLastTimestamp, Timestamp(Void));
- PDX_REMOTE_METHOD(GetSchedInfo, kOpGetSchedInfo, VSyncSchedInfo(Void));
- PDX_REMOTE_METHOD(Acknowledge, kOpAcknowledge, int(Void));
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_DISPLAY_RPC_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/display_types.h b/libs/vr/libdisplay/include/private/dvr/display_types.h
deleted file mode 100644
index 2bd02bd..0000000
--- a/libs/vr/libdisplay/include/private/dvr/display_types.h
+++ /dev/null
@@ -1,83 +0,0 @@
-#ifndef ANDROID_DVR_DISPLAY_TYPES_H_
-#define ANDROID_DVR_DISPLAY_TYPES_H_
-
-#ifdef __ARM_NEON
-#include <arm_neon.h>
-#else
-#ifndef __FLOAT32X4T_86
-#define __FLOAT32X4T_86
-typedef float float32x4_t __attribute__ ((__vector_size__ (16)));
-typedef struct float32x4x4_t { float32x4_t val[4]; };
-#endif
-#endif
-
-#include <cutils/native_handle.h>
-
-// DVR display-related data types.
-
-enum dvr_display_surface_type {
- // Normal display surface meant to be used by applications' GL context to
- // render into.
- DVR_SURFACE_TYPE_NORMAL = 0,
-
- // VideoMeshSurface is used to composite video frames into the 3D world.
- DVR_SURFACE_TYPE_VIDEO_MESH,
-
- // System overlay surface type. This is not currently in use.
- DVR_SURFACE_TYPE_OVERLAY,
-};
-
-enum dvr_display_surface_flags {
- DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_EDS = (1 << 0),
- DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION = (1 << 1),
- DVR_DISPLAY_SURFACE_FLAGS_VERTICAL_FLIP = (1 << 2),
- DVR_DISPLAY_SURFACE_FLAGS_GEOMETRY_SEPARATE_2 = (1 << 3),
- DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_CAC = (1 << 4),
-};
-
-enum dvr_display_surface_item_flags {
- DVR_DISPLAY_SURFACE_ITEM_FLAGS_BUFFERS_CHANGED = (1 << 0),
-};
-
-enum dvr_display_surface_attribute {
- DVR_DISPLAY_SURFACE_ATTRIBUTE_Z_ORDER = (1<<0),
- DVR_DISPLAY_SURFACE_ATTRIBUTE_VISIBLE = (1<<1),
- DVR_DISPLAY_SURFACE_ATTRIBUTE_BLUR = (1<<2),
- DVR_DISPLAY_SURFACE_ATTRIBUTE_EXCLUDE_FROM_BLUR = (1<<3),
- DVR_DISPLAY_SURFACE_ATTRIBUTE_BLUR_BEHIND = (1<<4),
-};
-
-// Maximum number of buffers for a surface. Each buffer represents a single
-// frame and may actually be a buffer array if multiview rendering is in use.
-// Define so that it can be used in shader code.
-#define kSurfaceBufferMaxCount 4
-
-// Maximum number of views per surface. Each eye is a view, for example.
-#define kSurfaceViewMaxCount 4
-
-namespace android {
-namespace dvr {
-
-struct __attribute__((packed, aligned(16))) DisplaySurfaceMetadata {
- // Array of orientations and translations corresponding with surface buffers.
- // The index is associated with each allocated buffer by DisplaySurface and
- // communicated to clients.
- // The maximum number of buffers is hard coded here as 4 so that we can bind
- // this data structure in GPU shaders.
- float32x4_t orientation[kSurfaceBufferMaxCount];
- float32x4_t translation[kSurfaceBufferMaxCount];
-};
-
-struct __attribute__((packed, aligned(16))) VideoMeshSurfaceMetadata {
- // Array of transform matrices corresponding with surface buffers.
- // Note that The index is associated with each allocated buffer by
- // DisplaySurface instead of VideoMeshSurface due to the fact that the
- // metadata here is interpreted as video mesh's transformation in each
- // application's rendering frame.
- float32x4x4_t transform[4][2];
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_DISPLAY_TYPES_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/graphics_private.h b/libs/vr/libdisplay/include/private/dvr/graphics_private.h
index 57c99da..a08b0df 100644
--- a/libs/vr/libdisplay/include/private/dvr/graphics_private.h
+++ b/libs/vr/libdisplay/include/private/dvr/graphics_private.h
@@ -17,6 +17,19 @@
__BEGIN_DECLS
+#define kSurfaceBufferMaxCount 4
+#define kSurfaceViewMaxCount 4
+
+struct __attribute__((packed, aligned(16))) DisplaySurfaceMetadata {
+ // Array of orientations and translations corresponding with surface buffers.
+ // The index is associated with each allocated buffer by DisplaySurface and
+ // communicated to clients.
+ // The maximum number of buffers is hard coded here as 4 so that we can bind
+ // this data structure in GPU shaders.
+ float32x4_t orientation[kSurfaceBufferMaxCount];
+ float32x4_t translation[kSurfaceBufferMaxCount];
+};
+
// Sets the pose used by the system for EDS. If dvrBeginRenderFrameEds() or
// dvrBeginRenderFrameLateLatch() are called instead of dvrBeginRenderFrame()
// it's not necessary to call this function. If this function is used, the call
diff --git a/libs/vr/libdisplay/include/private/dvr/late_latch.h b/libs/vr/libdisplay/include/private/dvr/late_latch.h
index b7c5e4f..c91d15c 100644
--- a/libs/vr/libdisplay/include/private/dvr/late_latch.h
+++ b/libs/vr/libdisplay/include/private/dvr/late_latch.h
@@ -5,11 +5,12 @@
#include <thread>
#include <vector>
+#include <dvr/dvr_display_types.h>
#include <dvr/pose_client.h>
#include <pdx/file_handle.h>
-#include <private/dvr/display_types.h>
#include <private/dvr/graphics/shader_program.h>
#include <private/dvr/graphics/vr_gl_extensions.h>
+#include <private/dvr/graphics_private.h>
#include <private/dvr/types.h>
struct DvrPose;
diff --git a/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h b/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h
index 4b1fa98..a260f17 100644
--- a/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h
+++ b/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h
@@ -13,30 +13,43 @@
namespace android {
namespace dvr {
+namespace display {
// A wrapper over dvr::ProducerQueue that caches EGLImage.
class NativeBufferQueue {
public:
- // Create a queue with the given number of free buffers.
NativeBufferQueue(EGLDisplay display,
- const std::shared_ptr<DisplaySurfaceClient>& surface,
- size_t capacity);
+ const std::shared_ptr<ProducerQueue>& producer_queue,
+ uint32_t width, uint32_t height, uint32_t format,
+ uint64_t usage, size_t capacity);
- size_t GetQueueCapacity() const { return producer_queue_->capacity(); }
+ uint32_t width() const { return width_; }
+ uint32_t height() const { return height_; }
+ uint32_t format() const { return format_; }
+ uint64_t usage() const { return usage_; }
+ size_t capacity() const { return producer_queue_->capacity(); }
// Dequeue a buffer from the free queue, blocking until one is available.
NativeBufferProducer* Dequeue();
// An noop here to keep Vulkan path in GraphicsContext happy.
// TODO(jwcai, cort) Move Vulkan path into GVR/Google3.
- void Enqueue(NativeBufferProducer* buffer) {}
+ void Enqueue(NativeBufferProducer* /*buffer*/) {}
private:
EGLDisplay display_;
+ uint32_t width_;
+ uint32_t height_;
+ uint32_t format_;
+ uint64_t usage_;
std::shared_ptr<ProducerQueue> producer_queue_;
std::vector<sp<NativeBufferProducer>> buffers_;
+
+ NativeBufferQueue(const NativeBufferQueue&) = delete;
+ void operator=(const NativeBufferQueue&) = delete;
};
+} // namespace display
} // namespace dvr
} // namespace android
diff --git a/libs/vr/libdisplay/include/private/dvr/screenshot_client.h b/libs/vr/libdisplay/include/private/dvr/screenshot_client.h
deleted file mode 100644
index b6fc859..0000000
--- a/libs/vr/libdisplay/include/private/dvr/screenshot_client.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef ANDROID_DVR_SCREENSHOT_CLIENT_H_
-#define ANDROID_DVR_SCREENSHOT_CLIENT_H_
-
-#include <memory>
-#include <vector>
-
-#include <pdx/client.h>
-#include <private/dvr/display_rpc.h>
-#include <system/graphics.h>
-
-namespace android {
-namespace dvr {
-
-// Represents a connection to the screenshot service, which allows capturing an
-// upcoming frame as it is being rendered to the display.
-class ScreenshotClient : public pdx::ClientBase<ScreenshotClient> {
- public:
- int format() const { return format_; }
-
- // Attempts to take a screenshot. If successful, sets *data to the contents
- // of the screenshot and returns zero. Otherwise, returns a negative error
- // code.
- // |index| is used to match the requested buffer with various buffer layers.
- int Take(std::vector<uint8_t>* data, int index, int* return_width,
- int* return_height);
-
- private:
- friend BASE;
-
- ScreenshotClient();
-
- // Layout information for screenshots.
- int format_;
-
- ScreenshotClient(const ScreenshotClient&) = delete;
- void operator=(const ScreenshotClient&) = delete;
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_SCREENSHOT_CLIENT_H_
diff --git a/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h b/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h
deleted file mode 100644
index 3a7f125..0000000
--- a/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef ANDROID_DVR_VIDEO_MESH_SURFACE_CLIENT_H_
-#define ANDROID_DVR_VIDEO_MESH_SURFACE_CLIENT_H_
-
-#include <private/dvr/buffer_hub_queue_client.h>
-#include <private/dvr/display_client.h>
-
-namespace android {
-namespace dvr {
-
-class VideoMeshSurfaceClient
- : pdx::ClientBase<VideoMeshSurfaceClient, SurfaceClient> {
- public:
- using LocalChannelHandle = pdx::LocalChannelHandle;
-
- // This call assumes ownership of |handle|.
- static std::unique_ptr<VideoMeshSurfaceClient> Import(
- LocalChannelHandle handle);
-
- std::shared_ptr<ProducerQueue> GetProducerQueue();
-
- // Get the shared memory metadata buffer for this video mesh surface. If it is
- // not yet allocated, this will allocate it.
- volatile VideoMeshSurfaceMetadata* GetMetadataBufferPtr();
-
- private:
- friend BASE;
-
- std::shared_ptr<ProducerQueue> producer_queue_;
- VideoMeshSurfaceMetadata* mapped_metadata_buffer_;
-
- explicit VideoMeshSurfaceClient(LocalChannelHandle handle);
-};
-
-} // namespace dvr
-} // namespace android
-
-struct DvrVideoMeshSurface {
- std::shared_ptr<android::dvr::VideoMeshSurfaceClient> client;
-};
-
-#endif // ANDROID_DVR_VIDEO_MESH_SURFACE_CLIENT_H_
diff --git a/libs/vr/libdisplay/native_buffer_queue.cpp b/libs/vr/libdisplay/native_buffer_queue.cpp
index d516d63..762db32 100644
--- a/libs/vr/libdisplay/native_buffer_queue.cpp
+++ b/libs/vr/libdisplay/native_buffer_queue.cpp
@@ -7,58 +7,59 @@
#include <array>
-#include <private/dvr/display_types.h>
+#include <dvr/dvr_display_types.h>
namespace android {
namespace dvr {
+namespace display {
NativeBufferQueue::NativeBufferQueue(
- EGLDisplay display, const std::shared_ptr<DisplaySurfaceClient>& surface,
+ EGLDisplay display, const std::shared_ptr<ProducerQueue>& producer_queue,
+ uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
size_t capacity)
- : display_(display), buffers_(capacity) {
- std::shared_ptr<ProducerQueue> queue = surface->GetProducerQueue();
-
+ : display_(display),
+ width_(width),
+ height_(height),
+ format_(format),
+ usage_(usage),
+ producer_queue_(producer_queue),
+ buffers_(capacity) {
for (size_t i = 0; i < capacity; i++) {
size_t slot;
// TODO(jwcai) Should change to use BufferViewPort's spec to config.
- int ret =
- queue->AllocateBuffer(surface->width(), surface->height(),
- surface->format(), surface->usage(), 1, &slot);
+ const int ret = producer_queue_->AllocateBuffer(width_, height_, format_,
+ usage_, 1, &slot);
if (ret < 0) {
ALOGE(
- "NativeBufferQueue::NativeBufferQueue: Failed to allocate buffer, "
- "error=%d",
- ret);
+ "NativeBufferQueue::NativeBufferQueue: Failed to allocate buffer: %s",
+ strerror(-ret));
return;
}
- ALOGD_IF(TRACE,
- "NativeBufferQueue::NativeBufferQueue: New buffer allocated at "
- "slot=%zu",
- slot);
+ ALOGD_IF(TRACE, "NativeBufferQueue::NativeBufferQueue: slot=%zu", slot);
}
-
- producer_queue_ = std::move(queue);
}
NativeBufferProducer* NativeBufferQueue::Dequeue() {
ATRACE_NAME("NativeBufferQueue::Dequeue");
-
- // This never times out.
size_t slot;
pdx::LocalHandle fence;
- std::shared_ptr<BufferProducer> buffer =
- producer_queue_->Dequeue(-1, &slot, &fence);
-
- if (buffers_[slot] == nullptr) {
- buffers_[slot] = new NativeBufferProducer(buffer, display_, slot);
+ auto buffer_status = producer_queue_->Dequeue(-1, &slot, &fence);
+ if (!buffer_status) {
+ ALOGE("NativeBufferQueue::Dequeue: Failed to dequeue buffer: %s",
+ buffer_status.GetErrorMessage().c_str());
+ return nullptr;
}
- ALOGD_IF(TRACE,
- "NativeBufferQueue::Dequeue: dequeue buffer at slot=%zu, buffer=%p",
- slot, buffers_[slot].get());
+ if (buffers_[slot] == nullptr)
+ buffers_[slot] =
+ new NativeBufferProducer(buffer_status.take(), display_, slot);
+
+ ALOGD_IF(TRACE, "NativeBufferQueue::Dequeue: slot=%zu buffer=%p", slot,
+ buffers_[slot].get());
return buffers_[slot].get();
}
+} // namespace display
} // namespace dvr
} // namespace android
diff --git a/libs/vr/libdisplay/screenshot_client.cpp b/libs/vr/libdisplay/screenshot_client.cpp
deleted file mode 100644
index 3ad0c68..0000000
--- a/libs/vr/libdisplay/screenshot_client.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-#include "include/private/dvr/screenshot_client.h"
-
-#include <log/log.h>
-
-#include <mutex>
-
-#include <pdx/default_transport/client_channel_factory.h>
-#include <private/dvr/display_rpc.h>
-
-using android::pdx::Transaction;
-using android::pdx::rpc::ClientPayload;
-using android::pdx::rpc::MessageBuffer;
-using android::pdx::rpc::ReplyBuffer;
-
-namespace android {
-namespace dvr {
-
-namespace {
-// Maximum supported pixels for screenshot capture. If the actual target buffer
-// is more than this, an error will be reported.
-constexpr int kMaxScreenshotPixels = 6000 * 4000;
-} // namespace
-
-int ScreenshotClient::Take(std::vector<uint8_t>* out_image, int index,
- int* return_width, int* return_height) {
- if (format_ != HAL_PIXEL_FORMAT_RGB_888) {
- ALOGE("ScreenshotClient::Take: Unsupported layout format: format=%d",
- format_);
- return -ENOSYS;
- }
-
- // TODO(eieio): Make a cleaner way to ensure enough capacity for send or
- // receive buffers. This method assumes TLS buffers that will maintain
- // capacity across calls within the same thread.
- MessageBuffer<ReplyBuffer>::Reserve(kMaxScreenshotPixels * 3);
- auto status = InvokeRemoteMethod<DisplayScreenshotRPC::TakeScreenshot>(index);
- if (!status) {
- ALOGE("ScreenshotClient::Take: Failed to take screenshot: %s",
- status.GetErrorMessage().c_str());
- return -status.error();
- }
-
- *return_width = status.get().width;
- *return_height = status.get().height;
- *out_image = std::move(status.take().buffer);
- return 0;
-}
-
-ScreenshotClient::ScreenshotClient()
- : BASE(pdx::default_transport::ClientChannelFactory::Create(
- DisplayScreenshotRPC::kClientPath)) {
- auto status = InvokeRemoteMethod<DisplayScreenshotRPC::GetFormat>();
- if (!status) {
- ALOGE(
- "ScreenshotClient::ScreenshotClient: Failed to retrieve screenshot "
- "layout: %s",
- status.GetErrorMessage().c_str());
-
- Close(status.error());
- } else {
- format_ = status.get();
- }
-}
-
-} // namespace dvr
-} // namespace android
diff --git a/libs/vr/libdisplay/tests/graphics_app_tests.cpp b/libs/vr/libdisplay/tests/graphics_app_tests.cpp
index f51dd8a..c592ba9 100644
--- a/libs/vr/libdisplay/tests/graphics_app_tests.cpp
+++ b/libs/vr/libdisplay/tests/graphics_app_tests.cpp
@@ -57,6 +57,8 @@
dvrGraphicsContextCreate(surface_params, &context);
EXPECT_NE(nullptr, context);
+ dvrGraphicsSurfaceSetVisible(context, 1);
+
DvrFrameSchedule schedule;
int wait_result = dvrGraphicsWaitNextFrame(context, 0, &schedule);
EXPECT_EQ(wait_result, 0);
@@ -64,10 +66,10 @@
dvrBeginRenderFrame(context);
- // Check range of vsync period from 70fps to 100fps.
+ // Check range of vsync period from 60fps to 100fps.
// TODO(jbates) Once we have stable hardware, clamp this range down further.
- EXPECT_LT(vsync_period, 1000000000ul / 70ul);
- EXPECT_GT(vsync_period, 1000000000ul / 100ul);
+ EXPECT_LE(vsync_period, 1000000000ul / 60ul);
+ EXPECT_GE(vsync_period, 1000000000ul / 100ul);
dvrPresent(context);
dvrGraphicsContextDestroy(context);
@@ -103,15 +105,3 @@
dvrGraphicsContextDestroy(context);
}
-TEST(GraphicsAppTests, CreateVideoMeshSurface) {
- DvrSurfaceParameter surface_params[] = {DVR_SURFACE_PARAMETER_LIST_END};
- DvrGraphicsContext* context = nullptr;
- int result = dvrGraphicsContextCreate(surface_params, &context);
- EXPECT_NE(nullptr, context);
- EXPECT_EQ(result, 0);
-
- DvrVideoMeshSurface* surface = dvrGraphicsVideoMeshSurfaceCreate(context);
- EXPECT_NE(nullptr, surface);
-
- dvrGraphicsVideoMeshSurfaceDestroy(surface);
-}
diff --git a/libs/vr/libdisplay/video_mesh_surface_client.cpp b/libs/vr/libdisplay/video_mesh_surface_client.cpp
deleted file mode 100644
index a2307e5..0000000
--- a/libs/vr/libdisplay/video_mesh_surface_client.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-#include "include/private/dvr/video_mesh_surface_client.h"
-
-using android::pdx::LocalChannelHandle;
-
-namespace android {
-namespace dvr {
-
-/* static */
-std::unique_ptr<VideoMeshSurfaceClient> VideoMeshSurfaceClient::Import(
- LocalChannelHandle handle) {
- return VideoMeshSurfaceClient::Create(std::move(handle));
-}
-
-VideoMeshSurfaceClient::VideoMeshSurfaceClient(LocalChannelHandle handle)
- : BASE(std::move(handle), SurfaceTypeEnum::VideoMesh),
- mapped_metadata_buffer_(nullptr) {
- // TODO(jwcai) import more data if needed.
-}
-
-std::shared_ptr<ProducerQueue> VideoMeshSurfaceClient::GetProducerQueue() {
- if (producer_queue_ == nullptr) {
- // Create producer queue through DisplayRPC
- auto status =
- InvokeRemoteMethod<DisplayRPC::VideoMeshSurfaceCreateProducerQueue>();
- if (!status) {
- ALOGE(
- "VideoMeshSurfaceClient::GetProducerQueue: failed to create producer "
- "queue: %s",
- status.GetErrorMessage().c_str());
- return nullptr;
- }
-
- producer_queue_ = ProducerQueue::Import(status.take());
- }
- return producer_queue_;
-}
-
-volatile VideoMeshSurfaceMetadata*
-VideoMeshSurfaceClient::GetMetadataBufferPtr() {
- if (!mapped_metadata_buffer_) {
- if (auto buffer_producer = GetMetadataBuffer()) {
- void* addr = nullptr;
- const int ret = buffer_producer->GetBlobReadWritePointer(
- sizeof(VideoMeshSurfaceMetadata), &addr);
- if (ret < 0) {
- ALOGE(
- "VideoMeshSurfaceClient::GetMetadataBufferPtr: Failed to map "
- "surface metadata: %s",
- strerror(-ret));
- return nullptr;
- }
- mapped_metadata_buffer_ = static_cast<VideoMeshSurfaceMetadata*>(addr);
- }
- }
-
- return mapped_metadata_buffer_;
-}
-
-} // namespace dvr
-} // namespace android
diff --git a/libs/vr/libdisplay/vsync_client.cpp b/libs/vr/libdisplay/vsync_client.cpp
index c928a08..bc6cf6c 100644
--- a/libs/vr/libdisplay/vsync_client.cpp
+++ b/libs/vr/libdisplay/vsync_client.cpp
@@ -3,8 +3,9 @@
#include <log/log.h>
#include <pdx/default_transport/client_channel_factory.h>
-#include <private/dvr/display_rpc.h>
+#include <private/dvr/display_protocol.h>
+using android::dvr::display::VSyncProtocol;
using android::pdx::Transaction;
namespace android {
@@ -12,15 +13,15 @@
VSyncClient::VSyncClient(long timeout_ms)
: BASE(pdx::default_transport::ClientChannelFactory::Create(
- DisplayVSyncRPC::kClientPath),
+ VSyncProtocol::kClientPath),
timeout_ms) {}
VSyncClient::VSyncClient()
: BASE(pdx::default_transport::ClientChannelFactory::Create(
- DisplayVSyncRPC::kClientPath)) {}
+ VSyncProtocol::kClientPath)) {}
int VSyncClient::Wait(int64_t* timestamp_ns) {
- auto status = InvokeRemoteMethod<DisplayVSyncRPC::Wait>();
+ auto status = InvokeRemoteMethod<VSyncProtocol::Wait>();
if (!status) {
ALOGE("VSyncClient::Wait: Failed to wait for vsync: %s",
status.GetErrorMessage().c_str());
@@ -36,7 +37,7 @@
int VSyncClient::GetFd() { return event_fd(); }
int VSyncClient::GetLastTimestamp(int64_t* timestamp_ns) {
- auto status = InvokeRemoteMethod<DisplayVSyncRPC::GetLastTimestamp>();
+ auto status = InvokeRemoteMethod<VSyncProtocol::GetLastTimestamp>();
if (!status) {
ALOGE("VSyncClient::GetLastTimestamp: Failed to get vsync timestamp: %s",
status.GetErrorMessage().c_str());
@@ -51,7 +52,7 @@
if (!vsync_period_ns || !timestamp_ns || !next_vsync_count)
return -EINVAL;
- auto status = InvokeRemoteMethod<DisplayVSyncRPC::GetSchedInfo>();
+ auto status = InvokeRemoteMethod<VSyncProtocol::GetSchedInfo>();
if (!status) {
ALOGE("VSyncClient::GetSchedInfo:: Failed to get warp timestamp: %s",
status.GetErrorMessage().c_str());
@@ -65,7 +66,7 @@
}
int VSyncClient::Acknowledge() {
- auto status = InvokeRemoteMethod<DisplayVSyncRPC::Acknowledge>();
+ auto status = InvokeRemoteMethod<VSyncProtocol::Acknowledge>();
ALOGE_IF(!status, "VSuncClient::Acknowledge: Failed to ack vsync because: %s",
status.GetErrorMessage().c_str());
return ReturnStatusOrError(status);
diff --git a/libs/vr/libdvr/Android.mk b/libs/vr/libdvr/Android.mk
index aa4513e..2375b5a 100644
--- a/libs/vr/libdvr/Android.mk
+++ b/libs/vr/libdvr/Android.mk
@@ -20,6 +20,7 @@
LOCAL_CFLAGS += \
-fvisibility=hidden \
+ -DLOG_TAG=\"libdvr\" \
-D DVR_EXPORT='__attribute__ ((visibility ("default")))'
LOCAL_C_INCLUDES := \
@@ -29,13 +30,13 @@
$(LOCAL_PATH)/include \
LOCAL_SRC_FILES := \
- display_manager_client.cpp \
dvr_api.cpp \
dvr_buffer.cpp \
dvr_buffer_queue.cpp \
+ dvr_display_manager.cpp \
dvr_hardware_composer_client.cpp \
dvr_surface.cpp \
- vsync_client_api.cpp \
+ dvr_vsync.cpp \
LOCAL_STATIC_LIBRARIES := \
libbufferhub \
diff --git a/libs/vr/libdvr/display_manager_client.cpp b/libs/vr/libdvr/display_manager_client.cpp
deleted file mode 100644
index e469e3e..0000000
--- a/libs/vr/libdvr/display_manager_client.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-#include "include/dvr/display_manager_client.h"
-
-#include <dvr/dvr_buffer.h>
-#include <grallocusage/GrallocUsageConversion.h>
-#include <private/android/AHardwareBufferHelpers.h>
-#include <private/dvr/buffer_hub_client.h>
-#include <private/dvr/display_manager_client_impl.h>
-
-using android::dvr::DisplaySurfaceAttributeEnum;
-
-extern "C" {
-
-struct DvrDisplayManagerClient {
- DvrDisplayManagerClient()
- : client(android::dvr::DisplayManagerClient::Create()) {}
- ~DvrDisplayManagerClient() {}
-
- std::unique_ptr<android::dvr::DisplayManagerClient> client;
-};
-
-struct DvrDisplayManagerClientSurfaceList {
- DvrDisplayManagerClientSurfaceList(
- std::vector<android::dvr::DisplaySurfaceInfo> surface_list)
- : list(std::move(surface_list)) {}
- ~DvrDisplayManagerClientSurfaceList() {}
-
- std::vector<android::dvr::DisplaySurfaceInfo> list;
-};
-
-struct DvrDisplayManagerClientSurfaceBuffers {
- DvrDisplayManagerClientSurfaceBuffers(
- std::vector<std::unique_ptr<android::dvr::BufferConsumer>> buffer_list)
- : list(std::move(buffer_list)) {}
- ~DvrDisplayManagerClientSurfaceBuffers() {}
-
- std::vector<std::unique_ptr<android::dvr::BufferConsumer>> list;
-};
-
-DvrDisplayManagerClient* dvrDisplayManagerClientCreate() {
- return new DvrDisplayManagerClient();
-}
-
-void dvrDisplayManagerClientDestroy(DvrDisplayManagerClient* client) {
- delete client;
-}
-
-DvrBuffer* dvrDisplayManagerSetupNamedBuffer(DvrDisplayManagerClient* client,
- const char* name, size_t size,
- uint64_t hardware_buffer_usage,
- uint64_t unused) {
- uint64_t producer_usage = 0;
- uint64_t consumer_usage = 0;
-
- // Note: AHardwareBuffer no longer uses usage0/usage1
- uint64_t gralloc_usage =
- android::AHardwareBuffer_convertToGrallocUsageBits(hardware_buffer_usage);
-
- // Note: split producer/consumer usage is deprecated, grallocV2 uses single
- // 64-bits usage
- // And, currently, 64-bits gralloc usage flags can safely be truncated to
- // 32-bits
- android_convertGralloc0To1Usage((uint32_t)gralloc_usage, &producer_usage,
- &consumer_usage);
-
- auto ion_buffer = client->client->SetupNamedBuffer(name, size, producer_usage,
- consumer_usage);
- if (ion_buffer) {
- return CreateDvrBufferFromIonBuffer(std::move(ion_buffer));
- }
- return nullptr;
-}
-
-int dvrDisplayManagerClientGetEventFd(DvrDisplayManagerClient* client) {
- return client->client->event_fd();
-}
-
-int dvrDisplayManagerClientTranslateEpollEventMask(
- DvrDisplayManagerClient* client, int in_events, int* out_events) {
- auto result = client->client->GetChannel()->GetEventMask(in_events);
-
- if (!result) {
- return -EIO;
- }
-
- *out_events = result.get();
-
- return 0;
-}
-
-int dvrDisplayManagerClientGetSurfaceList(
- DvrDisplayManagerClient* client,
- DvrDisplayManagerClientSurfaceList** surface_list) {
- std::vector<android::dvr::DisplaySurfaceInfo> list;
- int ret = client->client->GetSurfaceList(&list);
- if (ret < 0)
- return ret;
-
- *surface_list = new DvrDisplayManagerClientSurfaceList(std::move(list));
- return ret;
-}
-
-void dvrDisplayManagerClientSurfaceListDestroy(
- DvrDisplayManagerClientSurfaceList* surface_list) {
- delete surface_list;
-}
-
-size_t dvrDisplayManagerClientSurfaceListGetSize(
- DvrDisplayManagerClientSurfaceList* surface_list) {
- return surface_list->list.size();
-}
-
-int dvrDisplayManagerClientSurfaceListGetSurfaceId(
- DvrDisplayManagerClientSurfaceList* surface_list, size_t index) {
- return surface_list->list[index].surface_id;
-}
-
-int dvrDisplayManagerClientSurfaceListGetClientZOrder(
- DvrDisplayManagerClientSurfaceList* surface_list, size_t index) {
- return surface_list->list[index].ClientZOrder();
-}
-
-bool dvrDisplayManagerClientSurfaceListGetClientIsVisible(
- DvrDisplayManagerClientSurfaceList* surface_list, size_t index) {
- return surface_list->list[index].IsClientVisible();
-}
-
-int dvrDisplayManagerClientGetSurfaceBuffers(
- DvrDisplayManagerClient* /* client */, int /* surface_id */,
- DvrDisplayManagerClientSurfaceBuffers** /* surface_buffers */) {
- // TODO(jwcai, hendrikw) Remove this after we replacing
- // dvrDisplayManagerClientGetSurfaceBuffers is dvr_api.
- return -1;
-}
-
-void dvrDisplayManagerClientSurfaceBuffersDestroy(
- DvrDisplayManagerClientSurfaceBuffers* surface_buffers) {
- delete surface_buffers;
-}
-
-size_t dvrDisplayManagerClientSurfaceBuffersGetSize(
- DvrDisplayManagerClientSurfaceBuffers* surface_buffers) {
- return surface_buffers->list.size();
-}
-
-int dvrDisplayManagerClientSurfaceBuffersGetFd(
- DvrDisplayManagerClientSurfaceBuffers* surface_buffers, size_t index) {
- return surface_buffers->list[index]->event_fd();
-}
-
-} // extern "C"
diff --git a/libs/vr/libdvr/dvr_api.cpp b/libs/vr/libdvr/dvr_api.cpp
index c4634b1..4d7e1a6 100644
--- a/libs/vr/libdvr/dvr_api.cpp
+++ b/libs/vr/libdvr/dvr_api.cpp
@@ -1,13 +1,14 @@
#include "include/dvr/dvr_api.h"
#include <errno.h>
+#include <utils/Log.h>
// Headers from libdvr
-#include <dvr/display_manager_client.h>
#include <dvr/dvr_buffer.h>
#include <dvr/dvr_buffer_queue.h>
+#include <dvr/dvr_display_manager.h>
#include <dvr/dvr_surface.h>
-#include <dvr/vsync_client_api.h>
+#include <dvr/dvr_vsync.h>
// Headers not yet moved into libdvr.
// TODO(jwcai) Move these once their callers are moved into Google3.
@@ -18,134 +19,28 @@
extern "C" {
DVR_EXPORT int dvrGetApi(void* api, size_t struct_size, int version) {
+ ALOGI("dvrGetApi: api=%p struct_size=%zu version=%d", api, struct_size,
+ version);
if (version == 1) {
if (struct_size != sizeof(DvrApi_v1)) {
+ ALOGE("dvrGetApi: Size mismatch: expected %zu; actual %zu",
+ sizeof(DvrApi_v1), struct_size);
return -EINVAL;
}
DvrApi_v1* dvr_api = static_cast<DvrApi_v1*>(api);
- // display_manager_client.h
- dvr_api->display_manager_client_create = dvrDisplayManagerClientCreate;
- dvr_api->display_manager_client_destroy = dvrDisplayManagerClientDestroy;
- dvr_api->display_manager_client_get_surface_list =
- dvrDisplayManagerClientGetSurfaceList;
- dvr_api->display_manager_client_surface_list_destroy =
- dvrDisplayManagerClientSurfaceListDestroy;
- dvr_api->display_manager_setup_named_buffer =
- dvrDisplayManagerSetupNamedBuffer;
- dvr_api->display_manager_client_surface_list_get_size =
- dvrDisplayManagerClientSurfaceListGetSize;
- dvr_api->display_manager_client_surface_list_get_surface_id =
- dvrDisplayManagerClientSurfaceListGetSurfaceId;
- dvr_api->display_manager_client_get_surface_buffer_list =
- dvrDisplayManagerClientGetSurfaceBuffers;
- dvr_api->display_manager_client_surface_buffer_list_destroy =
- dvrDisplayManagerClientSurfaceBuffersDestroy;
- dvr_api->display_manager_client_surface_buffer_list_get_size =
- dvrDisplayManagerClientSurfaceBuffersGetSize;
- dvr_api->display_manager_client_surface_buffer_list_get_fd =
- dvrDisplayManagerClientSurfaceBuffersGetFd;
+// Defines an API entry for V1 (no version suffix).
+#define DVR_V1_API_ENTRY(name) dvr_api->name = dvr##name
- // dvr_buffer.h
- dvr_api->write_buffer_destroy = dvrWriteBufferDestroy;
- dvr_api->write_buffer_get_ahardwarebuffer =
- dvrWriteBufferGetAHardwareBuffer;
- dvr_api->write_buffer_post = dvrWriteBufferPost;
- dvr_api->write_buffer_gain = dvrWriteBufferGain;
- dvr_api->write_buffer_gain_async = dvrWriteBufferGainAsync;
- dvr_api->write_buffer_get_native_handle = dvrWriteBufferGetNativeHandle;
+#include "include/dvr/dvr_api_entries.h"
- dvr_api->read_buffer_destroy = dvrReadBufferDestroy;
- dvr_api->read_buffer_get_ahardwarebuffer = dvrReadBufferGetAHardwareBuffer;
- dvr_api->read_buffer_acquire = dvrReadBufferAcquire;
- dvr_api->read_buffer_release = dvrReadBufferRelease;
- dvr_api->read_buffer_release_async = dvrReadBufferReleaseAsync;
- dvr_api->read_buffer_get_native_handle = dvrReadBufferGetNativeHandle;
-
- dvr_api->buffer_destroy = dvrBufferDestroy;
- dvr_api->buffer_get_ahardwarebuffer = dvrBufferGetAHardwareBuffer;
- dvr_api->buffer_get_native_handle = dvrBufferGetNativeHandle;
-
- // dvr_buffer_queue.h
- dvr_api->write_buffer_queue_destroy = dvrWriteBufferQueueDestroy;
- dvr_api->write_buffer_queue_get_capacity = dvrWriteBufferQueueGetCapacity;
- dvr_api->write_buffer_queue_get_external_surface =
- dvrWriteBufferQueueGetExternalSurface;
- dvr_api->write_buffer_queue_create_read_queue =
- dvrWriteBufferQueueCreateReadQueue;
- dvr_api->write_buffer_queue_dequeue = dvrWriteBufferQueueDequeue;
- dvr_api->read_buffer_queue_destroy = dvrReadBufferQueueDestroy;
- dvr_api->read_buffer_queue_get_capacity = dvrReadBufferQueueGetCapacity;
- dvr_api->read_buffer_queue_create_read_queue =
- dvrReadBufferQueueCreateReadQueue;
- dvr_api->read_buffer_queue_dequeue = dvrReadBufferQueueDequeue;
-
- // dvr_surface.h
- dvr_api->get_named_buffer = dvrGetNamedBuffer;
- dvr_api->surface_create = dvrSurfaceCreate;
- dvr_api->surface_get_write_buffer_queue = dvrSurfaceGetWriteBufferQueue;
-
- // vsync_client_api.h
- dvr_api->vsync_client_create = dvr_vsync_client_create;
- dvr_api->vsync_client_destroy = dvr_vsync_client_destroy;
- dvr_api->vsync_client_get_sched_info = dvr_vsync_client_get_sched_info;
-
- // pose_client.h
- dvr_api->pose_client_create = dvrPoseCreate;
- dvr_api->pose_client_destroy = dvrPoseDestroy;
- dvr_api->pose_get = dvrPoseGet;
- dvr_api->pose_get_vsync_count = dvrPoseGetVsyncCount;
- dvr_api->pose_get_controller = dvrPoseGetController;
-
- // virtual_touchpad_client.h
- dvr_api->virtual_touchpad_create = dvrVirtualTouchpadCreate;
- dvr_api->virtual_touchpad_destroy = dvrVirtualTouchpadDestroy;
- dvr_api->virtual_touchpad_attach = dvrVirtualTouchpadAttach;
- dvr_api->virtual_touchpad_detach = dvrVirtualTouchpadDetach;
- dvr_api->virtual_touchpad_touch = dvrVirtualTouchpadTouch;
- dvr_api->virtual_touchpad_button_state = dvrVirtualTouchpadButtonState;
-
- // dvr_hardware_composer_client.h
- dvr_api->hwc_client_create = dvrHwcClientCreate;
- dvr_api->hwc_client_destroy = dvrHwcClientDestroy;
- dvr_api->hwc_frame_destroy = dvrHwcFrameDestroy;
- dvr_api->hwc_frame_get_display_id = dvrHwcFrameGetDisplayId;
- dvr_api->hwc_frame_get_display_width = dvrHwcFrameGetDisplayWidth;
- dvr_api->hwc_frame_get_display_height = dvrHwcFrameGetDisplayHeight;
- dvr_api->hwc_frame_get_display_removed = dvrHwcFrameGetDisplayRemoved;
- dvr_api->hwc_frame_get_active_config = dvrHwcFrameGetActiveConfig;
- dvr_api->hwc_frame_get_color_mode = dvrHwcFrameGetColorMode;
- dvr_api->hwc_frame_get_color_transform = dvrHwcFrameGetColorTransform;
- dvr_api->hwc_frame_get_power_mode = dvrHwcFrameGetPowerMode;
- dvr_api->hwc_frame_get_vsync_enabled = dvrHwcFrameGetVsyncEnabled;
- dvr_api->hwc_frame_get_layer_count = dvrHwcFrameGetLayerCount;
- dvr_api->hwc_frame_get_layer_id = dvrHwcFrameGetLayerId;
- dvr_api->hwc_frame_get_layer_buffer = dvrHwcFrameGetLayerBuffer;
- dvr_api->hwc_frame_get_layer_fence = dvrHwcFrameGetLayerFence;
- dvr_api->hwc_frame_get_layer_display_frame =
- dvrHwcFrameGetLayerDisplayFrame;
- dvr_api->hwc_frame_get_layer_crop = dvrHwcFrameGetLayerCrop;
- dvr_api->hwc_frame_get_layer_blend_mode = dvrHwcFrameGetLayerBlendMode;
- dvr_api->hwc_frame_get_layer_alpha = dvrHwcFrameGetLayerAlpha;
- dvr_api->hwc_frame_get_layer_type = dvrHwcFrameGetLayerType;
- dvr_api->hwc_frame_get_layer_application_id =
- dvrHwcFrameGetLayerApplicationId;
- dvr_api->hwc_frame_get_layer_z_order = dvrHwcFrameGetLayerZOrder;
- dvr_api->hwc_frame_get_layer_cursor = dvrHwcFrameGetLayerCursor;
- dvr_api->hwc_frame_get_layer_transform = dvrHwcFrameGetLayerTransform;
- dvr_api->hwc_frame_get_layer_dataspace = dvrHwcFrameGetLayerDataspace;
- dvr_api->hwc_frame_get_layer_color = dvrHwcFrameGetLayerColor;
- dvr_api->hwc_frame_get_layer_num_visible_regions =
- dvrHwcFrameGetLayerNumVisibleRegions;
- dvr_api->hwc_frame_get_layer_visible_region =
- dvrHwcFrameGetLayerVisibleRegion;
- dvr_api->hwc_frame_get_layer_num_damaged_regions =
- dvrHwcFrameGetLayerNumDamagedRegions;
- dvr_api->hwc_frame_get_layer_damaged_region =
- dvrHwcFrameGetLayerDamagedRegion;
+// Undefine macro definitions to play nice with Google3 style rules.
+#undef DVR_V1_API_ENTRY
return 0;
}
+
+ ALOGE("dvrGetApi: Unknown API version=%d", version);
return -EINVAL;
}
diff --git a/libs/vr/libdvr/dvr_buffer.cpp b/libs/vr/libdvr/dvr_buffer.cpp
index 28820e7..82469b8 100644
--- a/libs/vr/libdvr/dvr_buffer.cpp
+++ b/libs/vr/libdvr/dvr_buffer.cpp
@@ -4,37 +4,13 @@
#include <private/dvr/buffer_hub_client.h>
#include <ui/GraphicBuffer.h>
+#include "dvr_internal.h"
+
using namespace android;
-struct DvrWriteBuffer {
- std::shared_ptr<dvr::BufferProducer> write_buffer;
-};
-
-struct DvrReadBuffer {
- std::shared_ptr<dvr::BufferConsumer> read_buffer;
-};
-
-struct DvrBuffer {
- std::shared_ptr<dvr::IonBuffer> buffer;
-};
-
namespace android {
namespace dvr {
-DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
- const std::shared_ptr<dvr::BufferProducer>& buffer_producer) {
- if (!buffer_producer)
- return nullptr;
- return new DvrWriteBuffer{std::move(buffer_producer)};
-}
-
-DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
- const std::shared_ptr<dvr::BufferConsumer>& buffer_consumer) {
- if (!buffer_consumer)
- return nullptr;
- return new DvrReadBuffer{std::move(buffer_consumer)};
-}
-
DvrBuffer* CreateDvrBufferFromIonBuffer(
const std::shared_ptr<IonBuffer>& ion_buffer) {
if (!ion_buffer)
@@ -47,14 +23,6 @@
namespace {
-void InitializeGraphicBuffer(const dvr::BufferHubBuffer* buffer,
- sp<GraphicBuffer>* graphic_buffer) {
- *graphic_buffer = sp<GraphicBuffer>(new GraphicBuffer(
- buffer->width(), buffer->height(), buffer->format(), 1, /* layer count */
- buffer->usage(), buffer->stride(), buffer->native_handle(),
- false /* keep ownership */));
-}
-
int ConvertToAHardwareBuffer(GraphicBuffer* graphic_buffer,
AHardwareBuffer** hardware_buffer) {
if (!hardware_buffer || !graphic_buffer) {
@@ -69,28 +37,57 @@
extern "C" {
+void dvrWriteBufferCreateEmpty(DvrWriteBuffer** write_buffer) {
+ if (write_buffer)
+ *write_buffer = new DvrWriteBuffer;
+}
+
void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer) {
delete write_buffer;
}
+int dvrWriteBufferIsValid(DvrWriteBuffer* write_buffer) {
+ return write_buffer && write_buffer->write_buffer;
+}
+
+int dvrWriteBufferClear(DvrWriteBuffer* write_buffer) {
+ if (!write_buffer)
+ return -EINVAL;
+
+ write_buffer->write_buffer = nullptr;
+ return 0;
+}
+
int dvrWriteBufferGetId(DvrWriteBuffer* write_buffer) {
+ if (!write_buffer || !write_buffer->write_buffer)
+ return -EINVAL;
+
return write_buffer->write_buffer->id();
}
int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* write_buffer,
AHardwareBuffer** hardware_buffer) {
+ if (!write_buffer || !write_buffer->write_buffer)
+ return -EINVAL;
+
return ConvertToAHardwareBuffer(
write_buffer->write_buffer->buffer()->buffer().get(), hardware_buffer);
}
int dvrWriteBufferPost(DvrWriteBuffer* write_buffer, int ready_fence_fd,
const void* meta, size_t meta_size_bytes) {
+ if (!write_buffer || !write_buffer->write_buffer)
+ return -EINVAL;
+
pdx::LocalHandle fence(ready_fence_fd);
int result = write_buffer->write_buffer->Post(fence, meta, meta_size_bytes);
return result;
}
int dvrWriteBufferGain(DvrWriteBuffer* write_buffer, int* release_fence_fd) {
+ if (!write_buffer || !write_buffer->write_buffer || !release_fence_fd)
+ return -EINVAL;
+
pdx::LocalHandle release_fence;
int result = write_buffer->write_buffer->Gain(&release_fence);
*release_fence_fd = release_fence.Release();
@@ -98,23 +95,52 @@
}
int dvrWriteBufferGainAsync(DvrWriteBuffer* write_buffer) {
+ if (!write_buffer || !write_buffer->write_buffer)
+ return -EINVAL;
+
return write_buffer->write_buffer->GainAsync();
}
+void dvrReadBufferCreateEmpty(DvrReadBuffer** read_buffer) {
+ if (read_buffer)
+ *read_buffer = new DvrReadBuffer;
+}
+
void dvrReadBufferDestroy(DvrReadBuffer* read_buffer) { delete read_buffer; }
+int dvrReadBufferIsValid(DvrReadBuffer* read_buffer) {
+ return read_buffer && read_buffer->read_buffer;
+}
+
+int dvrReadBufferClear(DvrReadBuffer* read_buffer) {
+ if (!read_buffer)
+ return -EINVAL;
+
+ read_buffer->read_buffer = nullptr;
+ return 0;
+}
+
int dvrReadBufferGetId(DvrReadBuffer* read_buffer) {
+ if (!read_buffer || !read_buffer->read_buffer)
+ return -EINVAL;
+
return read_buffer->read_buffer->id();
}
int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* read_buffer,
AHardwareBuffer** hardware_buffer) {
+ if (!read_buffer || !read_buffer->read_buffer)
+ return -EINVAL;
+
return ConvertToAHardwareBuffer(
read_buffer->read_buffer->buffer()->buffer().get(), hardware_buffer);
}
int dvrReadBufferAcquire(DvrReadBuffer* read_buffer, int* ready_fence_fd,
void* meta, size_t meta_size_bytes) {
+ if (!read_buffer || !read_buffer->read_buffer)
+ return -EINVAL;
+
pdx::LocalHandle ready_fence;
int result =
read_buffer->read_buffer->Acquire(&ready_fence, meta, meta_size_bytes);
@@ -123,12 +149,18 @@
}
int dvrReadBufferRelease(DvrReadBuffer* read_buffer, int release_fence_fd) {
+ if (!read_buffer || !read_buffer->read_buffer)
+ return -EINVAL;
+
pdx::LocalHandle fence(release_fence_fd);
int result = read_buffer->read_buffer->Release(fence);
return result;
}
int dvrReadBufferReleaseAsync(DvrReadBuffer* read_buffer) {
+ if (!read_buffer || !read_buffer->read_buffer)
+ return -EINVAL;
+
return read_buffer->read_buffer->ReleaseAsync();
}
@@ -136,21 +168,34 @@
int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer,
AHardwareBuffer** hardware_buffer) {
+ if (!buffer || !buffer->buffer || !hardware_buffer) {
+ return -EINVAL;
+ }
+
return ConvertToAHardwareBuffer(buffer->buffer->buffer().get(),
hardware_buffer);
}
const struct native_handle* dvrWriteBufferGetNativeHandle(
DvrWriteBuffer* write_buffer) {
+ if (!write_buffer || !write_buffer->write_buffer)
+ return nullptr;
+
return write_buffer->write_buffer->native_handle();
}
const struct native_handle* dvrReadBufferGetNativeHandle(
DvrReadBuffer* read_buffer) {
+ if (!read_buffer || !read_buffer->read_buffer)
+ return nullptr;
+
return read_buffer->read_buffer->native_handle();
}
const struct native_handle* dvrBufferGetNativeHandle(DvrBuffer* buffer) {
+ if (!buffer || !buffer->buffer)
+ return nullptr;
+
return buffer->buffer->handle();
}
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index 50c94cb..95c0e26 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -6,45 +6,77 @@
#include <private/dvr/buffer_hub_queue_client.h>
#include <private/dvr/buffer_hub_queue_producer.h>
+#include "dvr_internal.h"
+
#define CHECK_PARAM(param) \
LOG_ALWAYS_FATAL_IF(param == nullptr, "%s: " #param "cannot be NULL.", \
__FUNCTION__)
using namespace android;
+namespace android {
+namespace dvr {
+
+DvrWriteBufferQueue* CreateDvrWriteBufferQueueFromProducerQueue(
+ const std::shared_ptr<dvr::ProducerQueue>& producer_queue) {
+ return new DvrWriteBufferQueue{std::move(producer_queue)};
+}
+
+DvrReadBufferQueue* CreateDvrReadBufferQueueFromConsumerQueue(
+ const std::shared_ptr<dvr::ConsumerQueue>& consumer_queue) {
+ return new DvrReadBufferQueue{std::move(consumer_queue)};
+}
+
+dvr::ProducerQueue* GetProducerQueueFromDvrWriteBufferQueue(
+ DvrWriteBufferQueue* write_queue) {
+ return write_queue->producer_queue.get();
+}
+
+} // namespace dvr
+} // namespace android
+
extern "C" {
void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue) {
- if (write_queue != nullptr && write_queue->native_window_ != nullptr) {
- ANativeWindow_release(write_queue->native_window_);
- }
+ if (write_queue != nullptr && write_queue->native_window != nullptr)
+ ANativeWindow_release(write_queue->native_window);
+
delete write_queue;
}
-size_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue) {
- CHECK_PARAM(write_queue);
- return write_queue->producer_queue_->capacity();
+ssize_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue) {
+ if (!write_queue || !write_queue->producer_queue)
+ return -EINVAL;
+
+ return write_queue->producer_queue->capacity();
+}
+
+int dvrWriteBufferQueueGetId(DvrWriteBufferQueue* write_queue) {
+ if (!write_queue)
+ return -EINVAL;
+
+ return write_queue->producer_queue->id();
}
int dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
ANativeWindow** out_window) {
- CHECK_PARAM(write_queue);
- CHECK_PARAM(out_window);
+ if (!write_queue || !out_window)
+ return -EINVAL;
- if (write_queue->producer_queue_->metadata_size() !=
+ if (write_queue->producer_queue->metadata_size() !=
sizeof(DvrNativeBufferMetadata)) {
ALOGE(
- "The size of buffer metadata (%u) of the write queue does not match of "
- "size of DvrNativeBufferMetadata (%u).",
- write_queue->producer_queue_->metadata_size(),
+ "The size of buffer metadata (%zu) of the write queue does not match "
+ "of size of DvrNativeBufferMetadata (%zu).",
+ write_queue->producer_queue->metadata_size(),
sizeof(DvrNativeBufferMetadata));
return -EINVAL;
}
- // Lazy creation of |native_window_|.
- if (write_queue->native_window_ == nullptr) {
+ // Lazy creation of |native_window|.
+ if (write_queue->native_window == nullptr) {
std::shared_ptr<dvr::BufferHubQueueCore> core =
- dvr::BufferHubQueueCore::Create(write_queue->producer_queue_);
+ dvr::BufferHubQueueCore::Create(write_queue->producer_queue);
if (core == nullptr) {
ALOGE(
"dvrWriteBufferQueueGetExternalSurface: Failed to create native "
@@ -54,24 +86,23 @@
sp<IGraphicBufferProducer> gbp = new dvr::BufferHubQueueProducer(core);
sp<Surface> surface = new Surface(gbp, true);
- write_queue->native_window_ = static_cast<ANativeWindow*>(surface.get());
- ANativeWindow_acquire(write_queue->native_window_);
+ write_queue->native_window = static_cast<ANativeWindow*>(surface.get());
+ ANativeWindow_acquire(write_queue->native_window);
}
- *out_window = write_queue->native_window_;
+ *out_window = write_queue->native_window;
return 0;
}
int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
DvrReadBufferQueue** out_read_queue) {
- CHECK_PARAM(write_queue);
- CHECK_PARAM(write_queue->producer_queue_);
- CHECK_PARAM(out_read_queue);
+ if (!write_queue || !write_queue->producer_queue || !out_read_queue)
+ return -EINVAL;
auto read_queue = std::make_unique<DvrReadBufferQueue>();
- read_queue->consumer_queue_ =
- write_queue->producer_queue_->CreateConsumerQueue();
- if (read_queue->consumer_queue_ == nullptr) {
+ read_queue->consumer_queue =
+ write_queue->producer_queue->CreateConsumerQueue();
+ if (read_queue->consumer_queue == nullptr) {
ALOGE(
"dvrWriteBufferQueueCreateReadQueue: Failed to create consumer queue "
"from DvrWriteBufferQueue[%p].",
@@ -84,23 +115,25 @@
}
int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout,
- DvrWriteBuffer** out_buffer,
- int* out_fence_fd) {
- CHECK_PARAM(write_queue);
- CHECK_PARAM(write_queue->producer_queue_);
- CHECK_PARAM(out_buffer);
- CHECK_PARAM(out_fence_fd);
+ DvrWriteBuffer* write_buffer,
+ int* out_fence_fd) {
+ if (!write_queue || !write_queue->producer_queue || !write_buffer ||
+ !out_fence_fd) {
+ return -EINVAL;
+ }
size_t slot;
pdx::LocalHandle release_fence;
- std::shared_ptr<dvr::BufferProducer> buffer =
- write_queue->producer_queue_->Dequeue(timeout, &slot, &release_fence);
- if (buffer == nullptr) {
- ALOGE("dvrWriteBufferQueueDequeue: Failed to dequeue buffer.");
- return -ENOMEM;
+ auto buffer_status =
+ write_queue->producer_queue->Dequeue(timeout, &slot, &release_fence);
+ if (!buffer_status) {
+ ALOGE_IF(buffer_status.error() != ETIMEDOUT,
+ "dvrWriteBufferQueueDequeue: Failed to dequeue buffer: %s",
+ buffer_status.GetErrorMessage().c_str());
+ return -buffer_status.error();
}
- *out_buffer = CreateDvrWriteBufferFromBufferProducer(buffer);
+ write_buffer->write_buffer = buffer_status.take();
*out_fence_fd = release_fence.Release();
return 0;
}
@@ -110,22 +143,29 @@
delete read_queue;
}
-size_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue) {
- CHECK_PARAM(read_queue);
+ssize_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue) {
+ if (!read_queue)
+ return -EINVAL;
- return read_queue->consumer_queue_->capacity();
+ return read_queue->consumer_queue->capacity();
+}
+
+int dvrReadBufferQueueGetId(DvrReadBufferQueue* read_queue) {
+ if (!read_queue)
+ return -EINVAL;
+
+ return read_queue->consumer_queue->id();
}
int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue,
DvrReadBufferQueue** out_read_queue) {
- CHECK_PARAM(read_queue);
- CHECK_PARAM(read_queue->consumer_queue_);
- CHECK_PARAM(out_read_queue);
+ if (!read_queue || !read_queue->consumer_queue || !out_read_queue)
+ return -EINVAL;
auto new_read_queue = std::make_unique<DvrReadBufferQueue>();
- new_read_queue->consumer_queue_ =
- read_queue->consumer_queue_->CreateConsumerQueue();
- if (new_read_queue->consumer_queue_ == nullptr) {
+ new_read_queue->consumer_queue =
+ read_queue->consumer_queue->CreateConsumerQueue();
+ if (new_read_queue->consumer_queue == nullptr) {
ALOGE(
"dvrReadBufferQueueCreateReadQueue: Failed to create consumer queue "
"from DvrReadBufferQueue[%p].",
@@ -138,34 +178,33 @@
}
int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout,
- DvrReadBuffer** out_buffer, int* out_fence_fd,
+ DvrReadBuffer* read_buffer, int* out_fence_fd,
void* out_meta, size_t meta_size_bytes) {
- CHECK_PARAM(read_queue);
- CHECK_PARAM(read_queue->consumer_queue_);
- CHECK_PARAM(out_buffer);
- CHECK_PARAM(out_fence_fd);
- CHECK_PARAM(out_meta);
+ if (!read_queue || !read_queue->consumer_queue || !read_buffer ||
+ !out_fence_fd || !out_meta) {
+ return -EINVAL;
+ }
- if (meta_size_bytes != read_queue->consumer_queue_->metadata_size()) {
+ if (meta_size_bytes != read_queue->consumer_queue->metadata_size()) {
ALOGE(
"dvrReadBufferQueueDequeue: Invalid metadata size, expected (%zu), "
"but actual (%zu).",
- read_queue->consumer_queue_->metadata_size(), meta_size_bytes);
+ read_queue->consumer_queue->metadata_size(), meta_size_bytes);
return -EINVAL;
}
size_t slot;
pdx::LocalHandle acquire_fence;
- std::shared_ptr<dvr::BufferConsumer> buffer =
- read_queue->consumer_queue_->Dequeue(timeout, &slot, out_meta,
- meta_size_bytes, &acquire_fence);
-
- if (buffer == nullptr) {
- ALOGE("dvrReadBufferQueueGainBuffer: Failed to dequeue buffer.");
- return -ENOMEM;
+ auto buffer_status = read_queue->consumer_queue->Dequeue(
+ timeout, &slot, out_meta, meta_size_bytes, &acquire_fence);
+ if (!buffer_status) {
+ ALOGE_IF(buffer_status.error() != ETIMEDOUT,
+ "dvrReadBufferQueueDequeue: Failed to dequeue buffer: %s",
+ buffer_status.GetErrorMessage().c_str());
+ return -buffer_status.error();
}
- *out_buffer = CreateDvrReadBufferFromBufferConsumer(buffer);
+ read_buffer->read_buffer = buffer_status.take();
*out_fence_fd = acquire_fence.Release();
return 0;
}
diff --git a/libs/vr/libdvr/dvr_display_manager.cpp b/libs/vr/libdvr/dvr_display_manager.cpp
new file mode 100644
index 0000000..87636ec
--- /dev/null
+++ b/libs/vr/libdvr/dvr_display_manager.cpp
@@ -0,0 +1,304 @@
+#include "include/dvr/dvr_display_manager.h"
+
+#include <dvr/dvr_buffer.h>
+#include <pdx/rpc/variant.h>
+#include <private/android/AHardwareBufferHelpers.h>
+#include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/buffer_hub_queue_client.h>
+#include <private/dvr/display_manager_client.h>
+
+#include "dvr_internal.h"
+
+using android::AHardwareBuffer_convertToGrallocUsageBits;
+using android::dvr::BufferConsumer;
+using android::dvr::display::DisplayManagerClient;
+using android::dvr::display::SurfaceAttributes;
+using android::dvr::display::SurfaceAttribute;
+using android::dvr::display::SurfaceState;
+using android::dvr::CreateDvrReadBufferQueueFromConsumerQueue;
+using android::pdx::rpc::EmptyVariant;
+
+namespace {
+
+// Extracts type and value from the attribute Variant and writes them into the
+// respective fields of DvrSurfaceAttribute.
+struct AttributeVisitor {
+ DvrSurfaceAttribute* attribute;
+
+ void operator()(int32_t value) {
+ attribute->value.int32_value = value;
+ attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT32;
+ }
+ void operator()(int64_t value) {
+ attribute->value.int64_value = value;
+ attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT64;
+ }
+ void operator()(bool value) {
+ attribute->value.bool_value = value;
+ attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL;
+ }
+ void operator()(float value) {
+ attribute->value.float_value = value;
+ attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT;
+ }
+ void operator()(const std::array<float, 2>& value) {
+ std::copy(value.cbegin(), value.cend(), attribute->value.float2_value);
+ attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2;
+ }
+ void operator()(const std::array<float, 3>& value) {
+ std::copy(value.cbegin(), value.cend(), attribute->value.float3_value);
+ attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3;
+ }
+ void operator()(const std::array<float, 4>& value) {
+ std::copy(value.cbegin(), value.cend(), attribute->value.float4_value);
+ attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4;
+ }
+ void operator()(const std::array<float, 8>& value) {
+ std::copy(value.cbegin(), value.cend(), attribute->value.float8_value);
+ attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8;
+ }
+ void operator()(const std::array<float, 16>& value) {
+ std::copy(value.cbegin(), value.cend(), attribute->value.float16_value);
+ attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16;
+ }
+ void operator()(EmptyVariant) {
+ attribute->value.type = DVR_SURFACE_ATTRIBUTE_TYPE_NONE;
+ }
+};
+
+size_t ConvertSurfaceAttributes(const SurfaceAttributes& surface_attributes,
+ DvrSurfaceAttribute* attributes,
+ size_t max_count) {
+ size_t count = 0;
+ for (const auto& attribute : surface_attributes) {
+ if (count >= max_count)
+ break;
+
+ // Copy the key and extract the Variant value using a visitor.
+ attributes[count].key = attribute.first;
+ attribute.second.Visit(AttributeVisitor{&attributes[count]});
+ count++;
+ }
+
+ return count;
+}
+
+} // anonymous namespace
+
+extern "C" {
+
+struct DvrDisplayManager {
+ std::unique_ptr<DisplayManagerClient> client;
+};
+
+struct DvrSurfaceState {
+ std::vector<SurfaceState> state;
+};
+
+int dvrDisplayManagerCreate(DvrDisplayManager** client_out) {
+ if (!client_out)
+ return -EINVAL;
+
+ auto client = DisplayManagerClient::Create();
+ if (!client) {
+ ALOGE("dvrDisplayManagerCreate: Failed to create display manager client!");
+ return -EIO;
+ }
+
+ *client_out = new DvrDisplayManager{std::move(client)};
+ return 0;
+}
+
+void dvrDisplayManagerDestroy(DvrDisplayManager* client) { delete client; }
+
+int dvrDisplayManagerSetupNamedBuffer(DvrDisplayManager* client,
+ const char* name, size_t size,
+ uint64_t usage, DvrBuffer** buffer_out) {
+ if (!client || !name || !buffer_out)
+ return -EINVAL;
+
+ uint64_t gralloc_usage = AHardwareBuffer_convertToGrallocUsageBits(usage);
+
+ auto buffer_status =
+ client->client->SetupNamedBuffer(name, size, gralloc_usage);
+ if (!buffer_status) {
+ ALOGE("dvrDisplayManagerSetupPoseBuffer: Failed to setup named buffer: %s",
+ buffer_status.GetErrorMessage().c_str());
+ return -buffer_status.error();
+ }
+
+ *buffer_out = CreateDvrBufferFromIonBuffer(buffer_status.take());
+ return 0;
+}
+
+int dvrDisplayManagerGetEventFd(DvrDisplayManager* client) {
+ if (!client)
+ return -EINVAL;
+
+ return client->client->event_fd();
+}
+
+int dvrDisplayManagerTranslateEpollEventMask(DvrDisplayManager* client,
+ int in_events, int* out_events) {
+ if (!client || !out_events)
+ return -EINVAL;
+
+ auto status = client->client->GetEventMask(in_events);
+ if (!status)
+ return -status.error();
+
+ *out_events = status.get();
+ return 0;
+}
+
+int dvrDisplayManagerGetSurfaceState(DvrDisplayManager* client,
+ DvrSurfaceState* state) {
+ if (!client || !state)
+ return -EINVAL;
+
+ auto status = client->client->GetSurfaceState();
+ if (!status)
+ return -status.error();
+
+ state->state = status.take();
+ return 0;
+}
+
+int dvrDisplayManagerGetReadBufferQueue(DvrDisplayManager* client,
+ int surface_id, int queue_id,
+ DvrReadBufferQueue** queue_out) {
+ if (!client || !queue_out)
+ return -EINVAL;
+
+ auto status = client->client->GetSurfaceQueue(surface_id, queue_id);
+ if (!status) {
+ ALOGE("dvrDisplayManagerGetReadBufferQueue: Failed to get queue: %s",
+ status.GetErrorMessage().c_str());
+ return -status.error();
+ }
+
+ *queue_out = CreateDvrReadBufferQueueFromConsumerQueue(status.take());
+ return 0;
+}
+
+int dvrSurfaceStateCreate(DvrSurfaceState** surface_state_out) {
+ if (!surface_state_out)
+ return -EINVAL;
+
+ *surface_state_out = new DvrSurfaceState{};
+ return 0;
+}
+
+void dvrSurfaceStateDestroy(DvrSurfaceState* surface_state) {
+ delete surface_state;
+}
+
+int dvrSurfaceStateGetSurfaceCount(DvrSurfaceState* surface_state,
+ size_t* count_out) {
+ if (!surface_state)
+ return -EINVAL;
+
+ *count_out = surface_state->state.size();
+ return 0;
+}
+
+int dvrSurfaceStateGetUpdateFlags(DvrSurfaceState* surface_state,
+ size_t surface_index,
+ DvrSurfaceUpdateFlags* flags_out) {
+ if (!surface_state || surface_index >= surface_state->state.size())
+ return -EINVAL;
+
+ *flags_out = surface_state->state[surface_index].update_flags;
+ return 0;
+}
+
+int dvrSurfaceStateGetSurfaceId(DvrSurfaceState* surface_state,
+ size_t surface_index, int* surface_id_out) {
+ if (!surface_state || surface_index >= surface_state->state.size())
+ return -EINVAL;
+
+ *surface_id_out = surface_state->state[surface_index].surface_id;
+ return 0;
+}
+
+int dvrSurfaceStateGetProcessId(DvrSurfaceState* surface_state,
+ size_t surface_index, int* process_id_out) {
+ if (!surface_state || surface_index >= surface_state->state.size())
+ return -EINVAL;
+
+ *process_id_out = surface_state->state[surface_index].process_id;
+ return 0;
+}
+
+int dvrSurfaceStateGetQueueCount(DvrSurfaceState* surface_state,
+ size_t surface_index, size_t* count_out) {
+ if (!surface_state || surface_index >= surface_state->state.size())
+ return -EINVAL;
+
+ *count_out = surface_state->state[surface_index].queue_ids.size();
+ return 0;
+}
+
+ssize_t dvrSurfaceStateGetQueueIds(DvrSurfaceState* surface_state,
+ size_t surface_index, int* queue_ids,
+ size_t max_count) {
+ if (!surface_state || surface_index >= surface_state->state.size())
+ return -EINVAL;
+
+ size_t i;
+ const auto& state = surface_state->state[surface_index];
+ for (i = 0; i < std::min(max_count, state.queue_ids.size()); i++) {
+ queue_ids[i] = state.queue_ids[i];
+ }
+
+ return i;
+}
+
+int dvrSurfaceStateGetZOrder(DvrSurfaceState* surface_state,
+ size_t surface_index, int* z_order_out) {
+ if (!surface_state || surface_index >= surface_state->state.size() ||
+ !z_order_out) {
+ return -EINVAL;
+ }
+
+ *z_order_out = surface_state->state[surface_index].GetZOrder();
+ return 0;
+}
+
+int dvrSurfaceStateGetVisible(DvrSurfaceState* surface_state,
+ size_t surface_index, bool* visible_out) {
+ if (!surface_state || surface_index >= surface_state->state.size() ||
+ !visible_out) {
+ return -EINVAL;
+ }
+
+ *visible_out = surface_state->state[surface_index].GetVisible();
+ return 0;
+}
+
+int dvrSurfaceStateGetAttributeCount(DvrSurfaceState* surface_state,
+ size_t surface_index, size_t* count_out) {
+ if (!surface_state || surface_index >= surface_state->state.size() ||
+ !count_out) {
+ return -EINVAL;
+ }
+
+ *count_out = surface_state->state[surface_index].surface_attributes.size();
+ return 0;
+}
+
+ssize_t dvrSurfaceStateGetAttributes(DvrSurfaceState* surface_state,
+ size_t surface_index,
+ DvrSurfaceAttribute* attributes,
+ size_t max_count) {
+ if (!surface_state || surface_index >= surface_state->state.size() ||
+ !attributes) {
+ return -EINVAL;
+ }
+
+ return ConvertSurfaceAttributes(
+ surface_state->state[surface_index].surface_attributes, attributes,
+ max_count);
+}
+
+} // extern "C"
diff --git a/libs/vr/libdvr/dvr_internal.h b/libs/vr/libdvr/dvr_internal.h
new file mode 100644
index 0000000..89bef09
--- /dev/null
+++ b/libs/vr/libdvr/dvr_internal.h
@@ -0,0 +1,70 @@
+#ifndef ANDROID_DVR_INTERNAL_H_
+#define ANDROID_DVR_INTERNAL_H_
+
+#include <sys/cdefs.h>
+
+#include <memory>
+
+extern "C" {
+
+typedef struct DvrBuffer DvrBuffer;
+typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct DvrWriteBuffer DvrWriteBuffer;
+typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
+typedef struct DvrReadBufferQueue DvrReadBufferQueue;
+
+} // extern "C"
+
+namespace android {
+namespace dvr {
+
+class BufferProducer;
+class BufferConsumer;
+class ConsumerQueue;
+class IonBuffer;
+class ProducerQueue;
+
+DvrBuffer* CreateDvrBufferFromIonBuffer(
+ const std::shared_ptr<IonBuffer>& ion_buffer);
+
+DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
+ const std::shared_ptr<BufferConsumer>& buffer_consumer);
+DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
+ const std::shared_ptr<BufferProducer>& buffer_producer);
+
+DvrReadBufferQueue* CreateDvrReadBufferQueueFromConsumerQueue(
+ const std::shared_ptr<ConsumerQueue>& consumer_queue);
+DvrWriteBufferQueue* CreateDvrWriteBufferQueueFromProducerQueue(
+ const std::shared_ptr<ProducerQueue>& producer_queue);
+ProducerQueue* GetProducerQueueFromDvrWriteBufferQueue(
+ DvrWriteBufferQueue* write_queue);
+
+} // namespace dvr
+} // namespace android
+
+extern "C" {
+
+struct DvrWriteBuffer {
+ std::shared_ptr<android::dvr::BufferProducer> write_buffer;
+};
+
+struct DvrReadBuffer {
+ std::shared_ptr<android::dvr::BufferConsumer> read_buffer;
+};
+
+struct DvrBuffer {
+ std::shared_ptr<android::dvr::IonBuffer> buffer;
+};
+
+struct DvrWriteBufferQueue {
+ std::shared_ptr<android::dvr::ProducerQueue> producer_queue;
+ ANativeWindow* native_window{nullptr};
+};
+
+struct DvrReadBufferQueue {
+ std::shared_ptr<android::dvr::ConsumerQueue> consumer_queue;
+};
+
+} // extern "C"
+
+#endif // ANDROID_DVR_INTERNAL_H_
diff --git a/libs/vr/libdvr/dvr_surface.cpp b/libs/vr/libdvr/dvr_surface.cpp
index a04ed50..b70f726 100644
--- a/libs/vr/libdvr/dvr_surface.cpp
+++ b/libs/vr/libdvr/dvr_surface.cpp
@@ -1,65 +1,162 @@
#include "include/dvr/dvr_surface.h"
+#include <inttypes.h>
+
#include <private/dvr/display_client.h>
-using namespace android;
+#include "dvr_internal.h"
-struct DvrSurface {
- std::unique_ptr<dvr::DisplaySurfaceClient> display_surface_;
-};
+using android::dvr::display::DisplayClient;
+using android::dvr::display::Surface;
+using android::dvr::display::SurfaceAttributes;
+using android::dvr::display::SurfaceAttributeValue;
+using android::dvr::CreateDvrReadBufferFromBufferConsumer;
+using android::dvr::CreateDvrWriteBufferQueueFromProducerQueue;
+
+namespace {
+
+bool ConvertSurfaceAttributes(const DvrSurfaceAttribute* attributes,
+ size_t attribute_count,
+ SurfaceAttributes* surface_attributes,
+ size_t* error_index) {
+ for (size_t i = 0; i < attribute_count; i++) {
+ SurfaceAttributeValue value;
+ switch (attributes[i].value.type) {
+ case DVR_SURFACE_ATTRIBUTE_TYPE_INT32:
+ value = attributes[i].value.int32_value;
+ break;
+ case DVR_SURFACE_ATTRIBUTE_TYPE_INT64:
+ value = attributes[i].value.int64_value;
+ break;
+ case DVR_SURFACE_ATTRIBUTE_TYPE_BOOL:
+ value = attributes[i].value.bool_value;
+ break;
+ case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT:
+ value = attributes[i].value.float_value;
+ break;
+ case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2:
+ value = attributes[i].value.float2_value;
+ break;
+ case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3:
+ value = attributes[i].value.float3_value;
+ break;
+ case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4:
+ value = attributes[i].value.float4_value;
+ break;
+ case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8:
+ value = attributes[i].value.float8_value;
+ break;
+ case DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16:
+ value = attributes[i].value.float16_value;
+ break;
+ default:
+ *error_index = i;
+ return false;
+ }
+
+ surface_attributes->emplace(attributes[i].key, value);
+ }
+
+ return true;
+}
+
+} // anonymous namespace
extern "C" {
-int dvrSurfaceCreate(int width, int height, int format, uint64_t usage0,
- uint64_t usage1, int flags, DvrSurface** out_surface) {
+struct DvrSurface {
+ std::unique_ptr<Surface> surface;
+};
+
+int dvrSurfaceCreate(const DvrSurfaceAttribute* attributes,
+ size_t attribute_count, DvrSurface** out_surface) {
if (out_surface == nullptr) {
- ALOGE("dvrSurfaceCreate: invalid inputs: out_surface=%p.", out_surface);
+ ALOGE("dvrSurfaceCreate: Invalid inputs: out_surface=%p.", out_surface);
return -EINVAL;
}
- int error;
- auto client = dvr::DisplayClient::Create(&error);
- if (!client) {
- ALOGE("Failed to create display client!");
- return error;
+ size_t error_index;
+ SurfaceAttributes surface_attributes;
+ if (!ConvertSurfaceAttributes(attributes, attribute_count,
+ &surface_attributes, &error_index)) {
+ ALOGE("dvrSurfaceCreate: Invalid surface attribute type: %" PRIu64,
+ attributes[error_index].value.type);
+ return -EINVAL;
}
- // TODO(hendrikw): When we move to gralloc1, pass both usage0 and usage1 down.
- std::unique_ptr<dvr::DisplaySurfaceClient> surface =
- client->CreateDisplaySurface(
- width, height, static_cast<int>(usage0 | usage1), format, flags);
+ auto status = Surface::CreateSurface(surface_attributes);
+ if (!status) {
+ ALOGE("dvrSurfaceCreate:: Failed to create display surface: %s",
+ status.GetErrorMessage().c_str());
+ return -status.error();
+ }
- DvrSurface* dvr_surface = new DvrSurface;
- dvr_surface->display_surface_ = std::move(surface);
- *out_surface = dvr_surface;
+ *out_surface = new DvrSurface{status.take()};
return 0;
}
-int dvrSurfaceGetWriteBufferQueue(DvrSurface* surface,
- DvrWriteBufferQueue** out_writer) {
+void dvrSurfaceDestroy(DvrSurface* surface) { delete surface; }
+
+int dvrSurfaceGetId(DvrSurface* surface) {
+ return surface->surface->surface_id();
+}
+
+int dvrSurfaceSetAttributes(DvrSurface* surface,
+ const DvrSurfaceAttribute* attributes,
+ size_t attribute_count) {
+ if (surface == nullptr || attributes == nullptr) {
+ ALOGE(
+ "dvrSurfaceSetAttributes: Invalid inputs: surface=%p attributes=%p "
+ "attribute_count=%zu",
+ surface, attributes, attribute_count);
+ return -EINVAL;
+ }
+
+ size_t error_index;
+ SurfaceAttributes surface_attributes;
+ if (!ConvertSurfaceAttributes(attributes, attribute_count,
+ &surface_attributes, &error_index)) {
+ ALOGE("dvrSurfaceSetAttributes: Invalid surface attribute type: %" PRIu64,
+ attributes[error_index].value.type);
+ return -EINVAL;
+ }
+
+ auto status = surface->surface->SetAttributes(surface_attributes);
+ if (!status) {
+ ALOGE("dvrSurfaceSetAttributes: Failed to set attributes: %s",
+ status.GetErrorMessage().c_str());
+ return -status.error();
+ }
+
+ return 0;
+}
+
+int dvrSurfaceCreateWriteBufferQueue(DvrSurface* surface, uint32_t width,
+ uint32_t height, uint32_t format,
+ uint64_t usage, size_t capacity,
+ DvrWriteBufferQueue** out_writer) {
if (surface == nullptr || out_writer == nullptr) {
ALOGE(
- "dvrSurfaceGetWriteBufferQueue: Invalid inputs: surface=%p, "
+ "dvrSurfaceCreateWriteBufferQueue: Invalid inputs: surface=%p, "
"out_writer=%p.",
surface, out_writer);
return -EINVAL;
}
- DvrWriteBufferQueue* buffer_writer = new DvrWriteBufferQueue;
- buffer_writer->producer_queue_ =
- surface->display_surface_->GetProducerQueue();
- if (buffer_writer->producer_queue_ == nullptr) {
- ALOGE(
- "dvrSurfaceGetWriteBufferQueue: Failed to get producer queue from "
- "display surface.");
- return -ENOMEM;
+
+ auto status =
+ surface->surface->CreateQueue(width, height, format, usage, capacity);
+ if (!status) {
+ ALOGE("dvrSurfaceCreateWriteBufferQueue: Failed to create queue: %s",
+ status.GetErrorMessage().c_str());
+ return -status.error();
}
- *out_writer = buffer_writer;
+ *out_writer = CreateDvrWriteBufferQueueFromProducerQueue(status.take());
return 0;
}
int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer) {
- auto client = android::dvr::DisplayClient::Create();
+ auto client = DisplayClient::Create();
if (!client) {
ALOGE("dvrGetNamedBuffer: Failed to create display client!");
return -ECOMM;
@@ -71,12 +168,13 @@
return -EINVAL;
}
- auto named_buffer = client->GetNamedBuffer(name);
- if (!named_buffer) {
- ALOGE("dvrGetNamedBuffer: Failed to find named buffer: %s.", name);
- return -EINVAL;
+ auto status = client->GetNamedBuffer(name);
+ if (!status) {
+ ALOGE("dvrGetNamedBuffer: Failed to find named buffer name=%s: %s", name,
+ status.GetErrorMessage().c_str());
+ return -status.error();
}
- *out_buffer = CreateDvrBufferFromIonBuffer(std::move(named_buffer));
+ *out_buffer = CreateDvrBufferFromIonBuffer(status.take());
return 0;
}
diff --git a/libs/vr/libdvr/dvr_vsync.cpp b/libs/vr/libdvr/dvr_vsync.cpp
new file mode 100644
index 0000000..099240e
--- /dev/null
+++ b/libs/vr/libdvr/dvr_vsync.cpp
@@ -0,0 +1,33 @@
+#include "include/dvr/dvr_vsync.h"
+
+#include <utils/Log.h>
+
+#include <private/dvr/vsync_client.h>
+
+extern "C" {
+
+struct DvrVSyncClient {
+ std::unique_ptr<android::dvr::VSyncClient> client;
+};
+
+int dvrVSyncClientCreate(DvrVSyncClient** client_out) {
+ auto client = android::dvr::VSyncClient::Create();
+ if (!client) {
+ ALOGE("dvrVSyncClientCreate: Failed to create vsync client!");
+ return -EIO;
+ }
+
+ *client_out = new DvrVSyncClient{std::move(client)};
+ return 0;
+}
+
+void dvrVSyncClientDestroy(DvrVSyncClient* client) { delete client; }
+
+int dvrVSyncClientGetSchedInfo(DvrVSyncClient* client, int64_t* vsync_period_ns,
+ int64_t* next_timestamp_ns,
+ uint32_t* next_vsync_count) {
+ return client->client->GetSchedInfo(vsync_period_ns, next_timestamp_ns,
+ next_vsync_count);
+}
+
+} // extern "C"
diff --git a/libs/vr/libdvr/include/dvr/display_manager_client.h b/libs/vr/libdvr/include/dvr/display_manager_client.h
deleted file mode 100644
index 8cd948c..0000000
--- a/libs/vr/libdvr/include/dvr/display_manager_client.h
+++ /dev/null
@@ -1,91 +0,0 @@
-#ifndef DVR_DISPLAY_MANAGER_CLIENT_H_
-#define DVR_DISPLAY_MANAGER_CLIENT_H_
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct DvrDisplayManagerClient DvrDisplayManagerClient;
-typedef struct DvrDisplayManagerClientSurfaceList
- DvrDisplayManagerClientSurfaceList;
-typedef struct DvrDisplayManagerClientSurfaceBuffers
- DvrDisplayManagerClientSurfaceBuffers;
-typedef struct DvrBuffer DvrBuffer;
-
-DvrDisplayManagerClient* dvrDisplayManagerClientCreate();
-
-void dvrDisplayManagerClientDestroy(DvrDisplayManagerClient* client);
-
-DvrBuffer* dvrDisplayManagerSetupNamedBuffer(DvrDisplayManagerClient* client,
- const char* name, size_t size,
- uint64_t usage0, uint64_t usage1);
-
-// Return an event fd for checking if there was an event on the server
-// Note that the only event which will be flagged is POLLIN. You must use
-// dvrDisplayManagerClientTranslateEpollEventMask in order to get the real
-// event flags.
-// @return the fd
-int dvrDisplayManagerClientGetEventFd(DvrDisplayManagerClient* client);
-
-// Once you have received an epoll event, you must translate it to its true
-// flags. This is a workaround for working with UDS.
-// @param in_events pass in the epoll revents that were initially returned
-// @param on success, this value will be overwritten with the true epoll values
-// @return 0 on success, non-zero otherwise
-int dvrDisplayManagerClientTranslateEpollEventMask(
- DvrDisplayManagerClient* client, int in_events, int* out_events);
-
-// If successful, populates |surface_list| with a list of application
-// surfaces the display is currently using.
-//
-// @return 0 on success. Otherwise it returns a negative error value.
-int dvrDisplayManagerClientGetSurfaceList(
- DvrDisplayManagerClient* client,
- DvrDisplayManagerClientSurfaceList** surface_list);
-
-void dvrDisplayManagerClientSurfaceListDestroy(
- DvrDisplayManagerClientSurfaceList* surface_list);
-
-// @return Returns the number of surfaces in the list.
-size_t dvrDisplayManagerClientSurfaceListGetSize(
- DvrDisplayManagerClientSurfaceList* surface_list);
-
-// @return Return a unique identifier for a client surface. The identifier can
-// be used to query for other surface properties.
-int dvrDisplayManagerClientSurfaceListGetSurfaceId(
- DvrDisplayManagerClientSurfaceList* surface_list, size_t index);
-
-// @return Returns the stacking order of the client surface at |index|.
-int dvrDisplayManagerClientSurfaceListGetClientZOrder(
- DvrDisplayManagerClientSurfaceList* surface_list, size_t index);
-
-// @return Returns true if the client surface is visible, false otherwise.
-bool dvrDisplayManagerClientSurfaceListGetClientIsVisible(
- DvrDisplayManagerClientSurfaceList* surface_list, size_t index);
-
-// TODO(jwcai, hendrikw) Remove this after we replacing
-// dvrDisplayManagerClientGetSurfaceBuffers is dvr_api.
-int dvrDisplayManagerClientGetSurfaceBuffers(
- DvrDisplayManagerClient* client, int surface_id,
- DvrDisplayManagerClientSurfaceBuffers** surface_buffers);
-
-void dvrDisplayManagerClientSurfaceBuffersDestroy(
- DvrDisplayManagerClientSurfaceBuffers* surface_buffers);
-
-// @return Returns the number of buffers.
-size_t dvrDisplayManagerClientSurfaceBuffersGetSize(
- DvrDisplayManagerClientSurfaceBuffers* surface_buffers);
-
-// @return Returns the file descriptor for the buffer consumer at |index|.
-int dvrDisplayManagerClientSurfaceBuffersGetFd(
- DvrDisplayManagerClientSurfaceBuffers* surface_buffers, size_t index);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // DVR_DISPLAY_MANAGER_CLIENT_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index 3cd401d..7124bee 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -4,137 +4,177 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
+#include <sys/cdefs.h>
+#include <unistd.h>
#include <dvr/dvr_hardware_composer_defs.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
+__BEGIN_DECLS
typedef struct ANativeWindow ANativeWindow;
typedef struct DvrPoseAsync DvrPoseAsync;
-typedef struct DvrDisplayManagerClient DvrDisplayManagerClient;
-typedef struct DvrDisplayManagerClientSurfaceList
- DvrDisplayManagerClientSurfaceList;
-typedef struct DvrDisplayManagerClientSurfaceBuffers
- DvrDisplayManagerClientSurfaceBuffers;
+typedef uint64_t DvrSurfaceUpdateFlags;
+typedef struct DvrDisplayManager DvrDisplayManager;
+typedef struct DvrSurfaceState DvrSurfaceState;
typedef struct DvrPose DvrPose;
-typedef struct dvr_vsync_client dvr_vsync_client;
+typedef struct DvrVSyncClient DvrVSyncClient;
typedef struct DvrVirtualTouchpad DvrVirtualTouchpad;
-typedef DvrDisplayManagerClient* (*DvrDisplayManagerClientCreatePtr)(void);
-typedef void (*DvrDisplayManagerClientDestroyPtr)(
- DvrDisplayManagerClient* client);
-
+typedef struct DvrBuffer DvrBuffer;
typedef struct DvrWriteBuffer DvrWriteBuffer;
typedef struct DvrReadBuffer DvrReadBuffer;
-typedef struct DvrBuffer DvrBuffer;
typedef struct AHardwareBuffer AHardwareBuffer;
-typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
typedef struct DvrReadBufferQueue DvrReadBufferQueue;
+typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
typedef struct DvrSurface DvrSurface;
+typedef uint64_t DvrSurfaceAttributeType;
+typedef int32_t DvrSurfaceAttributeKey;
+
+typedef struct DvrSurfaceAttributeValue DvrSurfaceAttributeValue;
+typedef struct DvrSurfaceAttribute DvrSurfaceAttribute;
struct native_handle;
-// display_manager_client.h
-typedef int (*DvrDisplayManagerClientGetSurfaceListPtr)(
- DvrDisplayManagerClient* client,
- DvrDisplayManagerClientSurfaceList** surface_list);
-typedef void (*DvrDisplayManagerClientSurfaceListDestroyPtr)(
- DvrDisplayManagerClientSurfaceList* surface_list);
-typedef DvrBuffer* (*DvrDisplayManagerSetupNamedBufferPtr)(
- DvrDisplayManagerClient* client, const char* name, size_t size,
- uint64_t usage0, uint64_t usage1);
-typedef size_t (*DvrDisplayManagerClientSurfaceListGetSizePtr)(
- DvrDisplayManagerClientSurfaceList* surface_list);
-typedef int (*DvrDisplayManagerClientSurfaceListGetSurfaceIdPtr)(
- DvrDisplayManagerClientSurfaceList* surface_list, size_t index);
-typedef int (*DvrDisplayManagerClientGetSurfaceBufferListPtr)(
- DvrDisplayManagerClient* client, int surface_id,
- DvrDisplayManagerClientSurfaceBuffers** surface_buffers);
-typedef void (*DvrDisplayManagerClientSurfaceBufferListDestroyPtr)(
- DvrDisplayManagerClientSurfaceBuffers* surface_buffers);
-typedef size_t (*DvrDisplayManagerClientSurfaceBufferListGetSizePtr)(
- DvrDisplayManagerClientSurfaceBuffers* surface_buffers);
-typedef int (*DvrDisplayManagerClientSurfaceBufferListGetFdPtr)(
- DvrDisplayManagerClientSurfaceBuffers* surface_buffers, size_t index);
+// dvr_display_manager.h
+typedef int (*DvrDisplayManagerCreatePtr)(DvrDisplayManager** client_out);
+typedef void (*DvrDisplayManagerDestroyPtr)(DvrDisplayManager* client);
+typedef int (*DvrDisplayManagerSetupNamedBufferPtr)(DvrDisplayManager* client,
+ const char* name,
+ size_t size, uint64_t usage,
+ DvrBuffer** buffer_out);
+typedef int (*DvrDisplayManagerGetEventFdPtr)(DvrDisplayManager* client);
+typedef int (*DvrDisplayManagerTranslateEpollEventMaskPtr)(
+ DvrDisplayManager* client, int in_events, int* out_events);
+typedef int (*DvrDisplayManagerGetSurfaceStatePtr)(
+ DvrDisplayManager* client, DvrSurfaceState* surface_state);
+typedef int (*DvrDisplayManagerGetReadBufferQueuePtr)(
+ DvrDisplayManager* client, int surface_id, int queue_id,
+ DvrReadBufferQueue** queue_out);
+typedef int (*DvrSurfaceStateCreatePtr)(DvrSurfaceState** surface_state);
+typedef void (*DvrSurfaceStateDestroyPtr)(DvrSurfaceState* surface_state);
+typedef int (*DvrSurfaceStateGetSurfaceCountPtr)(DvrSurfaceState* surface_state,
+ size_t* count_out);
+typedef int (*DvrSurfaceStateGetUpdateFlagsPtr)(
+ DvrSurfaceState* surface_state, size_t surface_index,
+ DvrSurfaceUpdateFlags* flags_out);
+typedef int (*DvrSurfaceStateGetSurfaceIdPtr)(DvrSurfaceState* surface_state,
+ size_t surface_index,
+ int* surface_id_out);
+typedef int (*DvrSurfaceStateGetProcessIdPtr)(DvrSurfaceState* surface_state,
+ size_t surface_index,
+ int* process_id_out);
+typedef int (*DvrSurfaceStateGetQueueCountPtr)(DvrSurfaceState* surface_state,
+ size_t surface_index,
+ size_t* count_out);
+typedef ssize_t (*DvrSurfaceStateGetQueueIdsPtr)(DvrSurfaceState* surface_state,
+ size_t surface_index,
+ int* queue_ids,
+ size_t max_count);
+typedef int (*DvrSurfaceStateGetZOrderPtr)(DvrSurfaceState* surface_state,
+ size_t surface_index,
+ int* z_order_out);
+typedef int (*DvrSurfaceStateGetVisiblePtr)(DvrSurfaceState* surface_state,
+ size_t surface_index,
+ bool* visible_out);
+typedef int (*DvrSurfaceStateGetAttributeCountPtr)(
+ DvrSurfaceState* surface_state, size_t surface_index, size_t* count_out);
+typedef ssize_t (*DvrSurfaceStateGetAttributesPtr)(
+ DvrSurfaceState* surface_state, size_t surface_index,
+ DvrSurfaceAttribute* attributes, size_t max_attribute_count);
// dvr_buffer.h
-typedef void (*DvrWriteBufferDestroyPtr)(DvrWriteBuffer* client);
+typedef void (*DvrWriteBufferCreateEmptyPtr)(DvrWriteBuffer** write_buffer_out);
+typedef void (*DvrWriteBufferDestroyPtr)(DvrWriteBuffer* write_buffer);
+typedef int (*DvrWriteBufferIsValidPtr)(DvrWriteBuffer* write_buffer);
+typedef int (*DvrWriteBufferClearPtr)(DvrWriteBuffer* write_buffer);
+typedef int (*DvrWriteBufferGetIdPtr)(DvrWriteBuffer* write_buffer);
typedef int (*DvrWriteBufferGetAHardwareBufferPtr)(
- DvrWriteBuffer* client, AHardwareBuffer** hardware_buffer);
-typedef int (*DvrWriteBufferPostPtr)(DvrWriteBuffer* client, int ready_fence_fd,
- const void* meta, size_t meta_size_bytes);
-typedef int (*DvrWriteBufferGainPtr)(DvrWriteBuffer* client,
+ DvrWriteBuffer* write_buffer, AHardwareBuffer** hardware_buffer);
+typedef int (*DvrWriteBufferPostPtr)(DvrWriteBuffer* write_buffer,
+ int ready_fence_fd, const void* meta,
+ size_t meta_size_bytes);
+typedef int (*DvrWriteBufferGainPtr)(DvrWriteBuffer* write_buffer,
int* release_fence_fd);
-typedef int (*DvrWriteBufferGainAsyncPtr)(DvrWriteBuffer* client);
-typedef const struct native_handle* (*DvrWriteBufferGetNativeHandle)(
+typedef int (*DvrWriteBufferGainAsyncPtr)(DvrWriteBuffer* write_buffer);
+typedef const struct native_handle* (*DvrWriteBufferGetNativeHandlePtr)(
DvrWriteBuffer* write_buffer);
-typedef void (*DvrReadBufferDestroyPtr)(DvrReadBuffer* client);
+typedef void (*DvrReadBufferCreateEmptyPtr)(DvrReadBuffer** read_buffer_out);
+typedef void (*DvrReadBufferDestroyPtr)(DvrReadBuffer* read_buffer);
+typedef int (*DvrReadBufferIsValidPtr)(DvrReadBuffer* read_buffer);
+typedef int (*DvrReadBufferClearPtr)(DvrReadBuffer* read_buffer);
+typedef int (*DvrReadBufferGetIdPtr)(DvrReadBuffer* read_buffer);
typedef int (*DvrReadBufferGetAHardwareBufferPtr)(
- DvrReadBuffer* client, AHardwareBuffer** hardware_buffer);
-typedef int (*DvrReadBufferAcquirePtr)(DvrReadBuffer* client,
+ DvrReadBuffer* read_buffer, AHardwareBuffer** hardware_buffer);
+typedef int (*DvrReadBufferAcquirePtr)(DvrReadBuffer* read_buffer,
int* ready_fence_fd, void* meta,
size_t meta_size_bytes);
-typedef int (*DvrReadBufferReleasePtr)(DvrReadBuffer* client,
+typedef int (*DvrReadBufferReleasePtr)(DvrReadBuffer* read_buffer,
int release_fence_fd);
-typedef int (*DvrReadBufferReleaseAsyncPtr)(DvrReadBuffer* client);
-typedef const struct native_handle* (*DvrReadBufferGetNativeHandle)(
+typedef int (*DvrReadBufferReleaseAsyncPtr)(DvrReadBuffer* read_buffer);
+typedef const struct native_handle* (*DvrReadBufferGetNativeHandlePtr)(
DvrReadBuffer* read_buffer);
-typedef void (*DvrBufferDestroy)(DvrBuffer* buffer);
-typedef int (*DvrBufferGetAHardwareBuffer)(DvrBuffer* buffer,
- AHardwareBuffer** hardware_buffer);
-typedef const struct native_handle* (*DvrBufferGetNativeHandle)(
+typedef void (*DvrBufferDestroyPtr)(DvrBuffer* buffer);
+typedef int (*DvrBufferGetAHardwareBufferPtr)(
+ DvrBuffer* buffer, AHardwareBuffer** hardware_buffer);
+typedef const struct native_handle* (*DvrBufferGetNativeHandlePtr)(
DvrBuffer* buffer);
// dvr_buffer_queue.h
typedef void (*DvrWriteBufferQueueDestroyPtr)(DvrWriteBufferQueue* write_queue);
-typedef size_t (*DvrWriteBufferQueueGetCapacityPtr)(
+typedef ssize_t (*DvrWriteBufferQueueGetCapacityPtr)(
DvrWriteBufferQueue* write_queue);
+typedef int (*DvrWriteBufferQueueGetIdPtr)(DvrWriteBufferQueue* write_queue);
typedef int (*DvrWriteBufferQueueGetExternalSurfacePtr)(
DvrWriteBufferQueue* write_queue, ANativeWindow** out_window);
typedef int (*DvrWriteBufferQueueCreateReadQueuePtr)(
DvrWriteBufferQueue* write_queue, DvrReadBufferQueue** out_read_queue);
typedef int (*DvrWriteBufferQueueDequeuePtr)(DvrWriteBufferQueue* write_queue,
int timeout,
- DvrWriteBuffer** out_buffer,
+ DvrWriteBuffer* out_buffer,
int* out_fence_fd);
typedef void (*DvrReadBufferQueueDestroyPtr)(DvrReadBufferQueue* read_queue);
-typedef size_t (*DvrReadBufferQueueGetCapacityPtr)(
+typedef ssize_t (*DvrReadBufferQueueGetCapacityPtr)(
DvrReadBufferQueue* read_queue);
+typedef int (*DvrReadBufferQueueGetIdPtr)(DvrReadBufferQueue* read_queue);
typedef int (*DvrReadBufferQueueCreateReadQueuePtr)(
DvrReadBufferQueue* read_queue, DvrReadBufferQueue** out_read_queue);
typedef int (*DvrReadBufferQueueDequeuePtr)(DvrReadBufferQueue* read_queue,
int timeout,
- DvrReadBuffer** out_buffer,
+ DvrReadBuffer* out_buffer,
int* out_fence_fd, void* out_meta,
size_t meta_size_bytes);
// dvr_surface.h
typedef int (*DvrGetNamedBufferPtr)(const char* name, DvrBuffer** out_buffer);
-typedef int (*DvrSurfaceCreatePtr)(int width, int height, int format,
- uint64_t usage0, uint64_t usage1, int flags,
- DvrSurface** out_surface);
-typedef int (*DvrSurfaceGetWriteBufferQueuePtr)(
- DvrSurface* surface, DvrWriteBufferQueue** out_writer);
+typedef int (*DvrSurfaceCreatePtr)(const DvrSurfaceAttribute* attributes,
+ size_t attribute_count,
+ DvrSurface** surface_out);
+typedef void (*DvrSurfaceDestroyPtr)(DvrSurface* surface);
+typedef int (*DvrSurfaceGetIdPtr)(DvrSurface* surface);
+typedef int (*DvrSurfaceSetAttributesPtr)(DvrSurface* surface,
+ const DvrSurfaceAttribute* attributes,
+ size_t attribute_count);
+typedef int (*DvrSurfaceCreateWriteBufferQueuePtr)(
+ DvrSurface* surface, uint32_t width, uint32_t height, uint32_t format,
+ uint64_t usage, size_t capacity, DvrWriteBufferQueue** queue_out);
// vsync_client_api.h
-typedef dvr_vsync_client* (*DvrVSyncClientCreatePtr)();
-typedef void (*DvrVSyncClientDestroyPtr)(dvr_vsync_client* client);
-typedef int (*DvrVSyncClientGetSchedInfoPtr)(dvr_vsync_client* client,
+typedef int (*DvrVSyncClientCreatePtr)(DvrVSyncClient** client_out);
+typedef void (*DvrVSyncClientDestroyPtr)(DvrVSyncClient* client);
+typedef int (*DvrVSyncClientGetSchedInfoPtr)(DvrVSyncClient* client,
int64_t* vsync_period_ns,
int64_t* next_timestamp_ns,
uint32_t* next_vsync_count);
// pose_client.h
-typedef DvrPose* (*DvrPoseClientCreatePtr)(void);
-typedef void (*DvrPoseClientDestroyPtr)(DvrPose* client);
+typedef DvrPose* (*DvrPoseCreatePtr)(void);
+typedef void (*DvrPoseDestroyPtr)(DvrPose* client);
typedef int (*DvrPoseGetPtr)(DvrPose* client, uint32_t vsync_count,
DvrPoseAsync* out_pose);
typedef uint32_t (*DvrPoseGetVsyncCountPtr)(DvrPose* client);
@@ -226,8 +266,8 @@
// reorder existing data members. If new fields need to be added, please take
// extra care to make sure that new data field is padded properly the size of
// the struct stays same.
-// TODO(b/37578558) Move |dvr_api.h| into a header library so that this structure
-// won't be copied between |dvr_api.h| and |buffer_hub_qeue_core.h|.
+// TODO(b/37578558) Move |dvr_api.h| into a header library so that this
+// structure won't be copied between |dvr_api.h| and |buffer_hub_qeue_core.h|.
struct DvrNativeBufferMetadata {
// Timestamp of the frame.
int64_t timestamp;
@@ -257,127 +297,18 @@
};
struct DvrApi_v1 {
- // Display manager client
- DvrDisplayManagerClientCreatePtr display_manager_client_create;
- DvrDisplayManagerClientDestroyPtr display_manager_client_destroy;
- DvrDisplayManagerClientGetSurfaceListPtr
- display_manager_client_get_surface_list;
- DvrDisplayManagerClientSurfaceListDestroyPtr
- display_manager_client_surface_list_destroy;
- DvrDisplayManagerSetupNamedBufferPtr display_manager_setup_named_buffer;
- DvrDisplayManagerClientSurfaceListGetSizePtr
- display_manager_client_surface_list_get_size;
- DvrDisplayManagerClientSurfaceListGetSurfaceIdPtr
- display_manager_client_surface_list_get_surface_id;
- DvrDisplayManagerClientGetSurfaceBufferListPtr
- display_manager_client_get_surface_buffer_list;
- DvrDisplayManagerClientSurfaceBufferListDestroyPtr
- display_manager_client_surface_buffer_list_destroy;
- DvrDisplayManagerClientSurfaceBufferListGetSizePtr
- display_manager_client_surface_buffer_list_get_size;
- DvrDisplayManagerClientSurfaceBufferListGetFdPtr
- display_manager_client_surface_buffer_list_get_fd;
+// Defines an API entry for V1 (no version suffix).
+#define DVR_V1_API_ENTRY(name) Dvr##name##Ptr name
- // Write buffer
- DvrWriteBufferDestroyPtr write_buffer_destroy;
- DvrWriteBufferGetAHardwareBufferPtr write_buffer_get_ahardwarebuffer;
- DvrWriteBufferPostPtr write_buffer_post;
- DvrWriteBufferGainPtr write_buffer_gain;
- DvrWriteBufferGainAsyncPtr write_buffer_gain_async;
- DvrWriteBufferGetNativeHandle write_buffer_get_native_handle;
+// Include file with API entries.
+#include "dvr_api_entries.h"
- // Read buffer
- DvrReadBufferDestroyPtr read_buffer_destroy;
- DvrReadBufferGetAHardwareBufferPtr read_buffer_get_ahardwarebuffer;
- DvrReadBufferAcquirePtr read_buffer_acquire;
- DvrReadBufferReleasePtr read_buffer_release;
- DvrReadBufferReleaseAsyncPtr read_buffer_release_async;
- DvrReadBufferGetNativeHandle read_buffer_get_native_handle;
-
- // Buffer
- DvrBufferDestroy buffer_destroy;
- DvrBufferGetAHardwareBuffer buffer_get_ahardwarebuffer;
- DvrBufferGetNativeHandle buffer_get_native_handle;
-
- // Write buffer queue
- DvrWriteBufferQueueDestroyPtr write_buffer_queue_destroy;
- DvrWriteBufferQueueGetCapacityPtr write_buffer_queue_get_capacity;
- DvrWriteBufferQueueGetExternalSurfacePtr
- write_buffer_queue_get_external_surface;
- DvrWriteBufferQueueCreateReadQueuePtr write_buffer_queue_create_read_queue;
- DvrWriteBufferQueueDequeuePtr write_buffer_queue_dequeue;
-
- // Read buffer queue
- DvrReadBufferQueueDestroyPtr read_buffer_queue_destroy;
- DvrReadBufferQueueGetCapacityPtr read_buffer_queue_get_capacity;
- DvrReadBufferQueueCreateReadQueuePtr read_buffer_queue_create_read_queue;
- DvrReadBufferQueueDequeuePtr read_buffer_queue_dequeue;
-
- // V-Sync client
- DvrVSyncClientCreatePtr vsync_client_create;
- DvrVSyncClientDestroyPtr vsync_client_destroy;
- DvrVSyncClientGetSchedInfoPtr vsync_client_get_sched_info;
-
- // Display surface
- DvrGetNamedBufferPtr get_named_buffer;
- DvrSurfaceCreatePtr surface_create;
- DvrSurfaceGetWriteBufferQueuePtr surface_get_write_buffer_queue;
-
- // Pose client
- DvrPoseClientCreatePtr pose_client_create;
- DvrPoseClientDestroyPtr pose_client_destroy;
- DvrPoseGetPtr pose_get;
- DvrPoseGetVsyncCountPtr pose_get_vsync_count;
- DvrPoseGetControllerPtr pose_get_controller;
-
- // Virtual touchpad client
- DvrVirtualTouchpadCreatePtr virtual_touchpad_create;
- DvrVirtualTouchpadDestroyPtr virtual_touchpad_destroy;
- DvrVirtualTouchpadAttachPtr virtual_touchpad_attach;
- DvrVirtualTouchpadDetachPtr virtual_touchpad_detach;
- DvrVirtualTouchpadTouchPtr virtual_touchpad_touch;
- DvrVirtualTouchpadButtonStatePtr virtual_touchpad_button_state;
-
- // VR HWComposer client
- DvrHwcClientCreatePtr hwc_client_create;
- DvrHwcClientDestroyPtr hwc_client_destroy;
- DvrHwcFrameDestroyPtr hwc_frame_destroy;
- DvrHwcFrameGetDisplayIdPtr hwc_frame_get_display_id;
- DvrHwcFrameGetDisplayWidthPtr hwc_frame_get_display_width;
- DvrHwcFrameGetDisplayHeightPtr hwc_frame_get_display_height;
- DvrHwcFrameGetDisplayRemovedPtr hwc_frame_get_display_removed;
- DvrHwcFrameGetActiveConfigPtr hwc_frame_get_active_config;
- DvrHwcFrameGetColorModePtr hwc_frame_get_color_mode;
- DvrHwcFrameGetColorTransformPtr hwc_frame_get_color_transform;
- DvrHwcFrameGetPowerModePtr hwc_frame_get_power_mode;
- DvrHwcFrameGetVsyncEnabledPtr hwc_frame_get_vsync_enabled;
- DvrHwcFrameGetLayerCountPtr hwc_frame_get_layer_count;
- DvrHwcFrameGetLayerIdPtr hwc_frame_get_layer_id;
- DvrHwcFrameGetLayerBufferPtr hwc_frame_get_layer_buffer;
- DvrHwcFrameGetLayerFencePtr hwc_frame_get_layer_fence;
- DvrHwcFrameGetLayerDisplayFramePtr hwc_frame_get_layer_display_frame;
- DvrHwcFrameGetLayerCropPtr hwc_frame_get_layer_crop;
- DvrHwcFrameGetLayerBlendModePtr hwc_frame_get_layer_blend_mode;
- DvrHwcFrameGetLayerAlphaPtr hwc_frame_get_layer_alpha;
- DvrHwcFrameGetLayerTypePtr hwc_frame_get_layer_type;
- DvrHwcFrameGetLayerApplicationIdPtr hwc_frame_get_layer_application_id;
- DvrHwcFrameGetLayerZOrderPtr hwc_frame_get_layer_z_order;
- DvrHwcFrameGetLayerCursorPtr hwc_frame_get_layer_cursor;
- DvrHwcFrameGetLayerTransformPtr hwc_frame_get_layer_transform;
- DvrHwcFrameGetLayerDataspacePtr hwc_frame_get_layer_dataspace;
- DvrHwcFrameGetLayerColorPtr hwc_frame_get_layer_color;
- DvrHwcFrameGetLayerNumVisibleRegionsPtr
- hwc_frame_get_layer_num_visible_regions;
- DvrHwcFrameGetLayerVisibleRegionPtr hwc_frame_get_layer_visible_region;
- DvrHwcFrameGetLayerNumDamagedRegionsPtr
- hwc_frame_get_layer_num_damaged_regions;
- DvrHwcFrameGetLayerDamagedRegionPtr hwc_frame_get_layer_damaged_region;
+// Undefine macro definitions to play nice with Google3 style rules.
+#undef DVR_V1_API_ENTRY
};
int dvrGetApi(void* api, size_t struct_size, int version);
-#ifdef __cplusplus
-} // extern "C"
-#endif
+__END_DECLS
#endif // ANDROID_DVR_API_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_api_entries.h b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
new file mode 100644
index 0000000..09568fd
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
@@ -0,0 +1,135 @@
+// dvr_api_entries.h
+//
+// Defines the DVR platform library API entries.
+//
+// Do not include this header directly.
+
+#ifndef DVR_V1_API_ENTRY
+#error Do not include this header directly.
+#endif
+
+// Display manager client
+DVR_V1_API_ENTRY(DisplayManagerCreate);
+DVR_V1_API_ENTRY(DisplayManagerDestroy);
+DVR_V1_API_ENTRY(DisplayManagerSetupNamedBuffer);
+DVR_V1_API_ENTRY(DisplayManagerGetEventFd);
+DVR_V1_API_ENTRY(DisplayManagerTranslateEpollEventMask);
+DVR_V1_API_ENTRY(DisplayManagerGetSurfaceState);
+DVR_V1_API_ENTRY(DisplayManagerGetReadBufferQueue);
+DVR_V1_API_ENTRY(SurfaceStateCreate);
+DVR_V1_API_ENTRY(SurfaceStateDestroy);
+DVR_V1_API_ENTRY(SurfaceStateGetSurfaceCount);
+DVR_V1_API_ENTRY(SurfaceStateGetUpdateFlags);
+DVR_V1_API_ENTRY(SurfaceStateGetSurfaceId);
+DVR_V1_API_ENTRY(SurfaceStateGetProcessId);
+DVR_V1_API_ENTRY(SurfaceStateGetQueueCount);
+DVR_V1_API_ENTRY(SurfaceStateGetQueueIds);
+DVR_V1_API_ENTRY(SurfaceStateGetZOrder);
+DVR_V1_API_ENTRY(SurfaceStateGetVisible);
+DVR_V1_API_ENTRY(SurfaceStateGetAttributeCount);
+DVR_V1_API_ENTRY(SurfaceStateGetAttributes);
+
+// Write buffer
+DVR_V1_API_ENTRY(WriteBufferCreateEmpty);
+DVR_V1_API_ENTRY(WriteBufferDestroy);
+DVR_V1_API_ENTRY(WriteBufferIsValid);
+DVR_V1_API_ENTRY(WriteBufferClear);
+DVR_V1_API_ENTRY(WriteBufferGetId);
+DVR_V1_API_ENTRY(WriteBufferGetAHardwareBuffer);
+DVR_V1_API_ENTRY(WriteBufferPost);
+DVR_V1_API_ENTRY(WriteBufferGain);
+DVR_V1_API_ENTRY(WriteBufferGainAsync);
+DVR_V1_API_ENTRY(WriteBufferGetNativeHandle);
+
+// Read buffer
+DVR_V1_API_ENTRY(ReadBufferCreateEmpty);
+DVR_V1_API_ENTRY(ReadBufferDestroy);
+DVR_V1_API_ENTRY(ReadBufferIsValid);
+DVR_V1_API_ENTRY(ReadBufferClear);
+DVR_V1_API_ENTRY(ReadBufferGetId);
+DVR_V1_API_ENTRY(ReadBufferGetAHardwareBuffer);
+DVR_V1_API_ENTRY(ReadBufferAcquire);
+DVR_V1_API_ENTRY(ReadBufferRelease);
+DVR_V1_API_ENTRY(ReadBufferReleaseAsync);
+DVR_V1_API_ENTRY(ReadBufferGetNativeHandle);
+
+// Buffer
+DVR_V1_API_ENTRY(BufferDestroy);
+DVR_V1_API_ENTRY(BufferGetAHardwareBuffer);
+DVR_V1_API_ENTRY(BufferGetNativeHandle);
+
+// Write buffer queue
+DVR_V1_API_ENTRY(WriteBufferQueueDestroy);
+DVR_V1_API_ENTRY(WriteBufferQueueGetCapacity);
+DVR_V1_API_ENTRY(WriteBufferQueueGetId);
+DVR_V1_API_ENTRY(WriteBufferQueueGetExternalSurface);
+DVR_V1_API_ENTRY(WriteBufferQueueCreateReadQueue);
+DVR_V1_API_ENTRY(WriteBufferQueueDequeue);
+
+// Read buffer queue
+DVR_V1_API_ENTRY(ReadBufferQueueDestroy);
+DVR_V1_API_ENTRY(ReadBufferQueueGetCapacity);
+DVR_V1_API_ENTRY(ReadBufferQueueGetId);
+DVR_V1_API_ENTRY(ReadBufferQueueCreateReadQueue);
+DVR_V1_API_ENTRY(ReadBufferQueueDequeue);
+
+// V-Sync client
+DVR_V1_API_ENTRY(VSyncClientCreate);
+DVR_V1_API_ENTRY(VSyncClientDestroy);
+DVR_V1_API_ENTRY(VSyncClientGetSchedInfo);
+
+// Display surface
+DVR_V1_API_ENTRY(SurfaceCreate);
+DVR_V1_API_ENTRY(SurfaceDestroy);
+DVR_V1_API_ENTRY(SurfaceGetId);
+DVR_V1_API_ENTRY(SurfaceSetAttributes);
+DVR_V1_API_ENTRY(SurfaceCreateWriteBufferQueue);
+DVR_V1_API_ENTRY(GetNamedBuffer);
+
+// Pose client
+DVR_V1_API_ENTRY(PoseCreate);
+DVR_V1_API_ENTRY(PoseDestroy);
+DVR_V1_API_ENTRY(PoseGet);
+DVR_V1_API_ENTRY(PoseGetVsyncCount);
+DVR_V1_API_ENTRY(PoseGetController);
+
+// Virtual touchpad client
+DVR_V1_API_ENTRY(VirtualTouchpadCreate);
+DVR_V1_API_ENTRY(VirtualTouchpadDestroy);
+DVR_V1_API_ENTRY(VirtualTouchpadAttach);
+DVR_V1_API_ENTRY(VirtualTouchpadDetach);
+DVR_V1_API_ENTRY(VirtualTouchpadTouch);
+DVR_V1_API_ENTRY(VirtualTouchpadButtonState);
+
+// VR HWComposer client
+DVR_V1_API_ENTRY(HwcClientCreate);
+DVR_V1_API_ENTRY(HwcClientDestroy);
+DVR_V1_API_ENTRY(HwcFrameDestroy);
+DVR_V1_API_ENTRY(HwcFrameGetDisplayId);
+DVR_V1_API_ENTRY(HwcFrameGetDisplayWidth);
+DVR_V1_API_ENTRY(HwcFrameGetDisplayHeight);
+DVR_V1_API_ENTRY(HwcFrameGetDisplayRemoved);
+DVR_V1_API_ENTRY(HwcFrameGetActiveConfig);
+DVR_V1_API_ENTRY(HwcFrameGetColorMode);
+DVR_V1_API_ENTRY(HwcFrameGetColorTransform);
+DVR_V1_API_ENTRY(HwcFrameGetPowerMode);
+DVR_V1_API_ENTRY(HwcFrameGetVsyncEnabled);
+DVR_V1_API_ENTRY(HwcFrameGetLayerCount);
+DVR_V1_API_ENTRY(HwcFrameGetLayerId);
+DVR_V1_API_ENTRY(HwcFrameGetLayerBuffer);
+DVR_V1_API_ENTRY(HwcFrameGetLayerFence);
+DVR_V1_API_ENTRY(HwcFrameGetLayerDisplayFrame);
+DVR_V1_API_ENTRY(HwcFrameGetLayerCrop);
+DVR_V1_API_ENTRY(HwcFrameGetLayerBlendMode);
+DVR_V1_API_ENTRY(HwcFrameGetLayerAlpha);
+DVR_V1_API_ENTRY(HwcFrameGetLayerType);
+DVR_V1_API_ENTRY(HwcFrameGetLayerApplicationId);
+DVR_V1_API_ENTRY(HwcFrameGetLayerZOrder);
+DVR_V1_API_ENTRY(HwcFrameGetLayerCursor);
+DVR_V1_API_ENTRY(HwcFrameGetLayerTransform);
+DVR_V1_API_ENTRY(HwcFrameGetLayerDataspace);
+DVR_V1_API_ENTRY(HwcFrameGetLayerColor);
+DVR_V1_API_ENTRY(HwcFrameGetLayerNumVisibleRegions);
+DVR_V1_API_ENTRY(HwcFrameGetLayerVisibleRegion);
+DVR_V1_API_ENTRY(HwcFrameGetLayerNumDamagedRegions);
+DVR_V1_API_ENTRY(HwcFrameGetLayerDamagedRegion);
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer.h b/libs/vr/libdvr/include/dvr/dvr_buffer.h
index 3e8357c..af55698 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer.h
@@ -3,11 +3,10 @@
#include <stdbool.h>
#include <stdint.h>
+#include <sys/cdefs.h>
#include <memory>
-#ifdef __cplusplus
-extern "C" {
-#endif
+__BEGIN_DECLS
typedef struct DvrWriteBuffer DvrWriteBuffer;
typedef struct DvrReadBuffer DvrReadBuffer;
@@ -15,58 +14,91 @@
typedef struct AHardwareBuffer AHardwareBuffer;
struct native_handle;
-// Write buffer
+// Creates an empty write buffer that may be filled with an acutal buffer by
+// other functions.
+void dvrWriteBufferCreateEmpty(DvrWriteBuffer** write_buffer);
+
+// Destroys the write buffer.
void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer);
+
+// Returns 1 if the given write buffer object contains a buffer, 0 otherwise.
+int dvrWriteBufferIsValid(DvrWriteBuffer* write_buffer);
+
+// Clears the contents of the buffer object. After a call to this function
+// dvrWriteBufferIsValid on the same buffer object returns 0.
+int dvrWriteBufferClear(DvrWriteBuffer* write_buffer);
+
+// Returns the global BufferHub id of this buffer.
int dvrWriteBufferGetId(DvrWriteBuffer* write_buffer);
+
+// Returns an AHardwareBuffer for the underlying buffer.
// Caller must call AHardwareBuffer_release on hardware_buffer.
int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* write_buffer,
AHardwareBuffer** hardware_buffer);
+
+// Posts the buffer, notifying any connected read buffers. Takes ownership of
+// |ready_fence_fd|.
int dvrWriteBufferPost(DvrWriteBuffer* write_buffer, int ready_fence_fd,
const void* meta, size_t meta_size_bytes);
+
+// Gains a buffer that has been released by all connected read buffers.
int dvrWriteBufferGain(DvrWriteBuffer* write_buffer, int* release_fence_fd);
int dvrWriteBufferGainAsync(DvrWriteBuffer* write_buffer);
+
+// TODO(eieio): Switch to return int and take an out parameter for the native
+// handle.
const struct native_handle* dvrWriteBufferGetNativeHandle(
DvrWriteBuffer* write_buffer);
-// Read buffer
+// Creates an empty read buffer that may be filled with and actual buffer by
+// other functions.
+void dvrReadBufferCreateEmpty(DvrReadBuffer** read_buffer);
+
+// Destroys the read buffer.
void dvrReadBufferDestroy(DvrReadBuffer* read_buffer);
+
+// Returns 1 if the given write buffer object contains a buffer, 0 otherwise.
+int dvrReadBufferIsValid(DvrReadBuffer* read_buffer);
+
+// Clears the contents of the buffer object. After a call to this function
+// dvrReadBufferIsValid on the same buffer object returns 0.
+int dvrReadBufferClear(DvrReadBuffer* read_buffer);
+
+// Returns the global BufferHub id of this buffer.
int dvrReadBufferGetId(DvrReadBuffer* read_buffer);
+
+// Returns an AHardwareBuffer for the underlying buffer.
// Caller must call AHardwareBuffer_release on hardware_buffer.
int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* read_buffer,
AHardwareBuffer** hardware_buffer);
+
+// Acquires the read buffer after it has been posted by the write buffer it is
+// connected to.
int dvrReadBufferAcquire(DvrReadBuffer* read_buffer, int* ready_fence_fd,
void* meta, size_t meta_size_bytes);
+
+// Releases the read buffer, notifying the write buffer it is connected to.
+// Takes ownership of |release_fence_fd|.
int dvrReadBufferRelease(DvrReadBuffer* read_buffer, int release_fence_fd);
int dvrReadBufferReleaseAsync(DvrReadBuffer* read_buffer);
+
+// TODO(eieio): Switch to return int and take an out parameter for the native
+// handle.
const struct native_handle* dvrReadBufferGetNativeHandle(
DvrReadBuffer* read_buffer);
-// Buffer
+// Destroys the buffer.
void dvrBufferDestroy(DvrBuffer* buffer);
+
+// Gets an AHardwareBuffer from the buffer.
// Caller must call AHardwareBuffer_release on hardware_buffer.
int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer,
AHardwareBuffer** hardware_buffer);
+
+// TODO(eieio): Switch to return int and take an out parameter for the native
+// handle.
const struct native_handle* dvrBufferGetNativeHandle(DvrBuffer* buffer);
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-namespace android {
-namespace dvr {
-
-class BufferProducer;
-class BufferConsumer;
-class IonBuffer;
-
-DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
- const std::shared_ptr<BufferProducer>& buffer_producer);
-DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
- const std::shared_ptr<BufferConsumer>& buffer_consumer);
-DvrBuffer* CreateDvrBufferFromIonBuffer(
- const std::shared_ptr<IonBuffer>& ion_buffer);
-
-} // namespace dvr
-} // namespace android
+__END_DECLS
#endif // ANDROID_DVR_BUFFER_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
index ba39513..dd669dc 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
@@ -1,11 +1,11 @@
#ifndef ANDROID_DVR_BUFFER_QUEUE_H_
#define ANDROID_DVR_BUFFER_QUEUE_H_
+#include <sys/cdefs.h>
+
#include <dvr/dvr_buffer.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
+__BEGIN_DECLS
typedef struct ANativeWindow ANativeWindow;
@@ -14,7 +14,8 @@
// WriteBufferQueue
void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue);
-size_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue);
+ssize_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue);
+int dvrWriteBufferQueueGetId(DvrWriteBufferQueue* write_queue);
// Returns ANativeWindow. Can be casted to a Java Surface using
// ANativeWindow_toSurface NDK API. Note that this method does not acquire an
@@ -26,19 +27,18 @@
int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
DvrReadBufferQueue** out_read_queue);
int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout,
- DvrWriteBuffer** out_buffer, int* out_fence_fd);
+ DvrWriteBuffer* out_buffer, int* out_fence_fd);
// ReadeBufferQueue
void dvrReadBufferQueueDestroy(DvrReadBufferQueue* read_queue);
-size_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue);
+ssize_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue);
+int dvrReadBufferQueueGetId(DvrReadBufferQueue* read_queue);
int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue,
DvrReadBufferQueue** out_read_queue);
int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout,
- DvrReadBuffer** out_buffer, int* out_fence_fd,
+ DvrReadBuffer* out_buffer, int* out_fence_fd,
void* out_meta, size_t meta_size_bytes);
-#ifdef __cplusplus
-} // extern "C"
-#endif
+__END_DECLS
#endif // ANDROID_DVR_BUFFER_QUEUE_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_deleter.h b/libs/vr/libdvr/include/dvr/dvr_deleter.h
new file mode 100644
index 0000000..943384f
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_deleter.h
@@ -0,0 +1,86 @@
+#ifndef ANDROID_DVR_DELETER_H_
+#define ANDROID_DVR_DELETER_H_
+
+#include <sys/cdefs.h>
+
+#include <memory>
+
+// Header-only C++ helper to delete opaque DVR objects.
+
+__BEGIN_DECLS
+
+// Use forward declarations to avoid dependency on other headers.
+typedef struct DvrBuffer DvrBuffer;
+typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct DvrWriteBuffer DvrWriteBuffer;
+typedef struct DvrReadBufferQueue DvrReadBufferQueue;
+typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
+typedef struct DvrDisplayManager DvrDisplayManager;
+typedef struct DvrSurfaceState DvrSurfaceState;
+typedef struct DvrSurface DvrSurface;
+typedef struct DvrHwcClient DvrHwcClient;
+typedef struct DvrHwcFrame DvrHwcFrame;
+typedef struct DvrVSyncClient DvrVSyncClient;
+
+void dvrBufferDestroy(DvrBuffer* buffer);
+void dvrReadBufferDestroy(DvrReadBuffer* read_buffer);
+void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer);
+void dvrReadBufferQueueDestroy(DvrReadBufferQueue* read_queue);
+void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue);
+void dvrDisplayManagerDestroy(DvrDisplayManager* client);
+void dvrSurfaceStateDestroy(DvrSurfaceState* surface_state);
+void dvrSurfaceDestroy(DvrSurface* surface);
+void dvrHwcClientDestroy(DvrHwcClient* client);
+void dvrHwcFrameDestroy(DvrHwcFrame* frame);
+void dvrVSyncClientDestroy(DvrVSyncClient* client);
+
+__END_DECLS
+
+// Avoid errors if this header is included in C code.
+#if defined(__cplusplus)
+
+namespace android {
+namespace dvr {
+
+// Universal DVR object deleter. May be passed to smart pointer types to handle
+// deletion of DVR API objects.
+struct DvrObjectDeleter {
+ void operator()(DvrBuffer* p) { dvrBufferDestroy(p); }
+ void operator()(DvrReadBuffer* p) { dvrReadBufferDestroy(p); }
+ void operator()(DvrWriteBuffer* p) { dvrWriteBufferDestroy(p); }
+ void operator()(DvrReadBufferQueue* p) { dvrReadBufferQueueDestroy(p); }
+ void operator()(DvrWriteBufferQueue* p) { dvrWriteBufferQueueDestroy(p); }
+ void operator()(DvrDisplayManager* p) { dvrDisplayManagerDestroy(p); }
+ void operator()(DvrSurfaceState* p) { dvrSurfaceStateDestroy(p); }
+ void operator()(DvrSurface* p) { dvrSurfaceDestroy(p); }
+ void operator()(DvrHwcClient* p) { dvrHwcClientDestroy(p); }
+ void operator()(DvrHwcFrame* p) { dvrHwcFrameDestroy(p); }
+ void operator()(DvrVSyncClient* p) { dvrVSyncClientDestroy(p); }
+};
+
+// Helper to define unique pointers for DVR object types.
+template <typename T>
+using MakeUniqueDvrPointer = std::unique_ptr<T, DvrObjectDeleter>;
+
+// Unique pointer types for DVR objects.
+using UniqueDvrBuffer = MakeUniqueDvrPointer<DvrBuffer>;
+using UniqueDvrReadBuffer = MakeUniqueDvrPointer<DvrReadBuffer>;
+using UniqueDvrWriteBuffer = MakeUniqueDvrPointer<DvrWriteBuffer>;
+using UniqueDvrReadBufferQueue = MakeUniqueDvrPointer<DvrReadBufferQueue>;
+using UniqueDvrWriteBufferQueue = MakeUniqueDvrPointer<DvrWriteBufferQueue>;
+using UniqueDvrDisplayManager = MakeUniqueDvrPointer<DvrDisplayManager>;
+using UniqueDvrSurfaceState = MakeUniqueDvrPointer<DvrSurfaceState>;
+using UniqueDvrSurface = MakeUniqueDvrPointer<DvrSurface>;
+using UniqueDvrHwcClient = MakeUniqueDvrPointer<DvrHwcClient>;
+using UniqueDvrHwcFrame = MakeUniqueDvrPointer<DvrHwcFrame>;
+using UniqueDvrVSyncClient = MakeUniqueDvrPointer<DvrVSyncClient>;
+
+// TODO(eieio): Add an adapter for std::shared_ptr that injects the deleter into
+// the relevant constructors.
+
+} // namespace dvr
+} // namespace android
+
+#endif // defined(__cplusplus)
+
+#endif // ANDROID_DVR_DELETER_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_display_manager.h b/libs/vr/libdvr/include/dvr/dvr_display_manager.h
new file mode 100644
index 0000000..d5aef8b
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_display_manager.h
@@ -0,0 +1,140 @@
+#ifndef DVR_DISPLAY_MANAGER_CLIENT_H_
+#define DVR_DISPLAY_MANAGER_CLIENT_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+#include <dvr/dvr_display_types.h>
+#include <dvr/dvr_surface.h>
+
+__BEGIN_DECLS
+
+typedef struct DvrBuffer DvrBuffer;
+typedef struct DvrDisplayManager DvrDisplayManager;
+typedef struct DvrSurfaceState DvrSurfaceState;
+typedef struct DvrReadBufferQueue DvrReadBufferQueue;
+
+typedef uint64_t DvrSurfaceUpdateFlags;
+
+// Attempts to connect to the display manager service.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrDisplayManagerCreate(DvrDisplayManager** client_out);
+
+// Destroys the display manager client object.
+void dvrDisplayManagerDestroy(DvrDisplayManager* client);
+
+// Sets up a named buffer for shared memory data transfer between display
+// clients and the display manager.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrDisplayManagerSetupNamedBuffer(DvrDisplayManager* client,
+ const char* name, size_t size,
+ uint64_t usage, DvrBuffer** buffer_out);
+
+// Returns an fd used to signal when surface updates occur. Note that depending
+// on the underlying transport, only a subset of the real event bits may be
+// supported. Use dvrDisplayManagerClientTranslateEpollEventMask to get the real
+// event flags.
+// @return the fd on success. Otherwise returns a negative error value.
+int dvrDisplayManagerGetEventFd(DvrDisplayManager* client);
+
+// @param in_events pass in the epoll revents that were initially returned by
+// poll/epoll.
+// @param on success, this value will be overwritten with the true poll/epoll
+// values.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrDisplayManagerTranslateEpollEventMask(DvrDisplayManager* client,
+ int in_events, int* out_events);
+
+// Queries the display manager service for the current state of the display
+// surfaces and stores the results in the given surface state object.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrDisplayManagerGetSurfaceState(DvrDisplayManager* client,
+ DvrSurfaceState* surface_state);
+
+// Gets a read buffer queue from the surface |surface_id| named |queue_id|. Each
+// call returns a different read buffer queue connected to the same write buffer
+// queue. Callers should cache these instead of requesting new ones when
+// possible.
+int dvrDisplayManagerGetReadBufferQueue(DvrDisplayManager* client,
+ int surface_id, int queue_id,
+ DvrReadBufferQueue** queue_out);
+
+// Creates a new surface state object. This object may be used to receive the
+// results of a surface state query. More than one state object may be created
+// to keep multiple snapshots, if desired.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateCreate(DvrSurfaceState** surface_state);
+
+// Destorys the surface state object.
+void dvrSurfaceStateDestroy(DvrSurfaceState* surface_state);
+
+// Writes the number of surfaces described in the state object into |count_out|.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateGetSurfaceCount(DvrSurfaceState* surface_state,
+ size_t* count_out);
+
+// Returns the update flags for the surface at |surface_index| in the state
+// object. The flags may be used to determine what changes, if any, occured to
+// the surface since the last state update.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateGetUpdateFlags(DvrSurfaceState* surface_state,
+ size_t surface_index,
+ DvrSurfaceUpdateFlags* flags_out);
+
+// Returns the unique identifier of surface at |surface_index| in the state
+// object. The identifier may be used to distinguish between surfaces.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateGetSurfaceId(DvrSurfaceState* surface_state,
+ size_t surface_index, int* surface_id_out);
+
+// Returns the process id of surface at |surface_index| in the state object.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateGetProcessId(DvrSurfaceState* surface_state,
+ size_t surface_index, int* process_id_out);
+
+// Writes the number of queues in the surface at |surface_index| in the state
+// object into |count_out|.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateGetQueueCount(DvrSurfaceState* surface_state,
+ size_t surface_index, size_t* count_out);
+
+// Returns up to |max_count| queue ids for the queues belonging to the surface
+// at |surface_index| in the state object.
+// @return The number of queue ids written on success. Otherwise returns a
+// negative error value.
+ssize_t dvrSurfaceStateGetQueueIds(DvrSurfaceState* surface_state,
+ size_t surface_index, int* queue_ids,
+ size_t max_count);
+
+// Writes the z-order of the surface at |surface_index| in surface state object
+// into |z_order_out|.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceStateGetZOrder(DvrSurfaceState* surface_state,
+ size_t surface_index, int* z_order_out);
+
+// Writes the visible state of the surface at |surface_index| in the surface
+// state object into |visible_out|.
+// @return 0 on success. Otherwise it returns a negative error value.
+int dvrSurfaceStateGetVisible(DvrSurfaceState* surface_state,
+ size_t surface_index, bool* visible_out);
+
+// Writes the number of attributes on the surface at |surface_index| in the
+// state object into |count_out|.
+// @return 0 on success. Otherwise it returns a negative error value.
+int dvrSurfaceStateGetAttributeCount(DvrSurfaceState* surface_state,
+ size_t surface_index, size_t* count_out);
+
+// Writes the list of attribute key/value pairs for the surface at
+// |surface_index| in the surface state object into |attributes|.
+// @return The number of attributes written on success. Otherwise returns a
+// negative error value.
+ssize_t dvrSurfaceStateGetAttributes(DvrSurfaceState* surface_state,
+ size_t surface_index,
+ DvrSurfaceAttribute* attributes,
+ size_t max_count);
+
+__END_DECLS
+
+#endif // DVR_DISPLAY_MANAGER_CLIENT_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_surface.h b/libs/vr/libdvr/include/dvr/dvr_surface.h
index e5228d6..58f2a10 100644
--- a/libs/vr/libdvr/include/dvr/dvr_surface.h
+++ b/libs/vr/libdvr/include/dvr/dvr_surface.h
@@ -1,28 +1,90 @@
#ifndef ANDROID_DVR_SURFACE_H_
#define ANDROID_DVR_SURFACE_H_
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/cdefs.h>
+
#include <dvr/dvr_buffer.h>
#include <dvr/dvr_buffer_queue.h>
+#include <dvr/dvr_display_types.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
+__BEGIN_DECLS
+typedef struct DvrBuffer DvrBuffer;
typedef struct DvrSurface DvrSurface;
-typedef struct DvrSurfaceParameter DvrSurfaceParameter;
+typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
-// Get a pointer to the global pose buffer.
+// Attribute types. The values are one-hot encoded to support singluar types or
+// masks of supported types.
+enum {
+ DVR_SURFACE_ATTRIBUTE_TYPE_NONE = 0,
+ DVR_SURFACE_ATTRIBUTE_TYPE_INT32 = (1 << 0),
+ DVR_SURFACE_ATTRIBUTE_TYPE_INT64 = (1 << 1),
+ DVR_SURFACE_ATTRIBUTE_TYPE_BOOL = (1 << 2),
+ DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT = (1 << 3),
+ DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT2 = (1 << 4),
+ DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT3 = (1 << 5),
+ DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT4 = (1 << 6),
+ DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT8 = (1 << 7),
+ DVR_SURFACE_ATTRIBUTE_TYPE_FLOAT16 = (1 << 8),
+};
+
+typedef uint64_t DvrSurfaceAttributeType;
+typedef int32_t DvrSurfaceAttributeKey;
+
+typedef struct DvrSurfaceAttributeValue {
+ DvrSurfaceAttributeType type;
+ union {
+ int32_t int32_value;
+ int64_t int64_value;
+ bool bool_value;
+ float float_value;
+ float float2_value[2];
+ float float3_value[3];
+ float float4_value[4];
+ float float8_value[8];
+ float float16_value[16];
+ };
+} DvrSurfaceAttributeValue;
+
+typedef struct DvrSurfaceAttribute {
+ DvrSurfaceAttributeKey key;
+ DvrSurfaceAttributeValue value;
+} DvrSurfaceAttribute;
+
+// Creates a new display surface with the given attributes.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceCreate(const DvrSurfaceAttribute* attributes,
+ size_t attribute_count, DvrSurface** surface_out);
+
+// Destroys the display surface.
+void dvrSurfaceDestroy(DvrSurface* surface);
+
+// Gets the DisplayService global id for this surface.
+int dvrSurfaceGetId(DvrSurface* surface);
+
+// Sets attributes on the given display surface.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceSetAttributes(DvrSurface* surface,
+ const DvrSurfaceAttribute* attributes,
+ size_t attribute_count);
+
+// Creates a new write-side buffer queue on the given surface. Direct surfaces
+// may only have one queue, the latest call replacing any prior queue. Replaced
+// queues are still referenced and should be destryoed using the queue destroy
+// API.
+// @return 0 on success. Otherwise returns a negative error value.
+int dvrSurfaceCreateWriteBufferQueue(DvrSurface* surface, uint32_t width,
+ uint32_t height, uint32_t format,
+ uint64_t usage, size_t capacity,
+ DvrWriteBufferQueue** queue_out);
+
+// Get a named buffer from the display service.
+// @return 0 on success. Otherwise returns a negative error value.
int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer);
-int dvrSurfaceCreate(int width, int height, int format, uint64_t usage0,
- uint64_t usage1, int flags, DvrSurface** out_surface);
-
-// TODO(eieio, jwcai) Change this once we have multiple buffer queue support.
-int dvrSurfaceGetWriteBufferQueue(DvrSurface* surface,
- DvrWriteBufferQueue** out_writer);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+__END_DECLS
#endif // ANDROID_DVR_SURFACE_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_vsync.h b/libs/vr/libdvr/include/dvr/dvr_vsync.h
new file mode 100644
index 0000000..1eea3d9
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_vsync.h
@@ -0,0 +1,26 @@
+#ifndef ANDROID_DVR_VSYNC_H_
+#define ANDROID_DVR_VSYNC_H_
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+typedef struct DvrVSyncClient DvrVSyncClient;
+
+// Creates a new client to the system vsync service.
+int dvrVSyncClientCreate(DvrVSyncClient** client_out);
+
+// Destroys the vsync client.
+void dvrVSyncClientDestroy(DvrVSyncClient* client);
+
+// Get the estimated timestamp of the next GPU lens warp preemption event in/
+// ns. Also returns the corresponding vsync count that the next lens warp
+// operation will target.
+int dvrVSyncClientGetSchedInfo(DvrVSyncClient* client, int64_t* vsync_period_ns,
+ int64_t* next_timestamp_ns,
+ uint32_t* next_vsync_count);
+
+__END_DECLS
+
+#endif // ANDROID_DVR_VSYNC_H_
diff --git a/libs/vr/libdvr/include/dvr/vsync_client_api.h b/libs/vr/libdvr/include/dvr/vsync_client_api.h
deleted file mode 100644
index 0ae5cd5..0000000
--- a/libs/vr/libdvr/include/dvr/vsync_client_api.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef ANDROID_DVR_VSYNC_CLIENT_API_H_
-#define ANDROID_DVR_VSYNC_CLIENT_API_H_
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// A client of the vsync service.
-//
-// The "dvr_vsync_client" structure wraps a client connection to the
-// system vsync service. It is used to synchronize application drawing
-// with the scanout of the display.
-typedef struct dvr_vsync_client dvr_vsync_client;
-
-// Creates a new client to the system vsync service.
-dvr_vsync_client* dvr_vsync_client_create();
-
-// Destroys the vsync client.
-void dvr_vsync_client_destroy(dvr_vsync_client* client);
-
-// Get the estimated timestamp of the next GPU lens warp preemption event in
-// ns. Also returns the corresponding vsync count that the next lens warp
-// operation will target. This call has the same side effect on events as
-// Acknowledge, which saves an IPC message.
-int dvr_vsync_client_get_sched_info(dvr_vsync_client* client,
- int64_t* vsync_period_ns,
- int64_t* next_timestamp_ns,
- uint32_t* next_vsync_count);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // ANDROID_DVR_VSYNC_CLIENT_API_H_
diff --git a/libs/vr/libdvr/tests/Android.mk b/libs/vr/libdvr/tests/Android.mk
index 29cdc13..d6ce99b 100644
--- a/libs/vr/libdvr/tests/Android.mk
+++ b/libs/vr/libdvr/tests/Android.mk
@@ -23,6 +23,7 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
dvr_buffer_queue-test.cpp \
+ dvr_display_manager-test.cpp \
dvr_named_buffer-test.cpp \
LOCAL_STATIC_LIBRARIES := $(static_libraries)
diff --git a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
index ea1273e..5f7f1bf 100644
--- a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
@@ -6,6 +6,8 @@
#include <base/logging.h>
#include <gtest/gtest.h>
+#include "../dvr_internal.h"
+
namespace android {
namespace dvr {
@@ -23,9 +25,9 @@
class DvrBufferQueueTest : public ::testing::Test {
protected:
void SetUp() override {
- write_queue_ = new DvrWriteBufferQueue;
- write_queue_->producer_queue_ = ProducerQueue::Create<TestMeta>(0, 0, 0, 0);
- ASSERT_NE(nullptr, write_queue_->producer_queue_);
+ write_queue_ = CreateDvrWriteBufferQueueFromProducerQueue(
+ ProducerQueue::Create<TestMeta>(0, 0, 0, 0));
+ ASSERT_NE(nullptr, write_queue_);
}
void TearDown() override {
@@ -38,9 +40,10 @@
void AllocateBuffers(size_t buffer_count) {
size_t out_slot;
for (size_t i = 0; i < buffer_count; i++) {
- int ret = write_queue_->producer_queue_->AllocateBuffer(
- kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage,
- kBufferSliceCount, &out_slot);
+ int ret =
+ GetProducerQueueFromDvrWriteBufferQueue(write_queue_)
+ ->AllocateBuffer(kBufferWidth, kBufferHeight, kBufferFormat,
+ kBufferUsage, kBufferSliceCount, &out_slot);
ASSERT_EQ(0, ret);
}
}
@@ -88,6 +91,39 @@
dvrReadBufferQueueDestroy(read_queue2);
}
+TEST_F(DvrBufferQueueTest, CreateEmptyBuffer) {
+ AllocateBuffers(3);
+
+ DvrReadBuffer* read_buffer = nullptr;
+ DvrWriteBuffer* write_buffer = nullptr;
+
+ EXPECT_FALSE(dvrReadBufferIsValid(read_buffer));
+ EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer));
+
+ dvrReadBufferCreateEmpty(&read_buffer);
+ ASSERT_NE(nullptr, read_buffer);
+
+ dvrWriteBufferCreateEmpty(&write_buffer);
+ ASSERT_NE(nullptr, write_buffer);
+
+ EXPECT_FALSE(dvrReadBufferIsValid(read_buffer));
+ EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer));
+
+ DvrReadBufferQueue* read_queue = nullptr;
+
+ ASSERT_EQ(0, dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue));
+
+ const int kTimeoutMs = 0;
+ int fence_fd = -1;
+ ASSERT_EQ(0, dvrWriteBufferQueueDequeue(write_queue_, kTimeoutMs,
+ write_buffer, &fence_fd));
+ EXPECT_EQ(-1, fence_fd);
+ EXPECT_TRUE(dvrWriteBufferIsValid(write_buffer));
+
+ ASSERT_EQ(0, dvrWriteBufferClear(write_buffer));
+ EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer));
+}
+
TEST_F(DvrBufferQueueTest, TestDequeuePostDequeueRelease) {
static constexpr int kTimeout = 0;
DvrReadBufferQueue* read_queue = nullptr;
@@ -100,12 +136,18 @@
ASSERT_EQ(0, ret);
ASSERT_NE(nullptr, read_queue);
+ dvrWriteBufferCreateEmpty(&wb);
+ ASSERT_NE(nullptr, wb);
+
+ dvrReadBufferCreateEmpty(&rb);
+ ASSERT_NE(nullptr, rb);
+
AllocateBuffers(kQueueCapacity);
// Gain buffer for writing.
- ret = dvrWriteBufferQueueDequeue(write_queue_, kTimeout, &wb, &fence_fd);
+ ret = dvrWriteBufferQueueDequeue(write_queue_, kTimeout, wb, &fence_fd);
ASSERT_EQ(0, ret);
- ASSERT_NE(nullptr, wb);
+ ASSERT_TRUE(dvrWriteBufferIsValid(wb));
ALOGD_IF(TRACE, "TestDequeuePostDequeueRelease, gain buffer %p, fence_fd=%d",
wb, fence_fd);
pdx::LocalHandle release_fence(fence_fd);
@@ -119,10 +161,10 @@
// Acquire buffer for reading.
TestMeta acquired_seq = 0U;
- ret = dvrReadBufferQueueDequeue(read_queue, kTimeout, &rb, &fence_fd,
+ ret = dvrReadBufferQueueDequeue(read_queue, kTimeout, rb, &fence_fd,
&acquired_seq, sizeof(acquired_seq));
ASSERT_EQ(0, ret);
- ASSERT_NE(nullptr, rb);
+ ASSERT_TRUE(dvrReadBufferIsValid(rb));
ASSERT_EQ(seq, acquired_seq);
ALOGD_IF(TRACE,
"TestDequeuePostDequeueRelease, acquire buffer %p, fence_fd=%d", rb,
@@ -156,10 +198,11 @@
// A write queue with DvrNativeBufferMetadata should work fine.
std::unique_ptr<DvrWriteBufferQueue, decltype(&dvrWriteBufferQueueDestroy)>
- write_queue(new DvrWriteBufferQueue, dvrWriteBufferQueueDestroy);
- write_queue->producer_queue_ =
- ProducerQueue::Create<DvrNativeBufferMetadata>(0, 0, 0, 0);
- ASSERT_NE(nullptr, write_queue->producer_queue_);
+ write_queue(
+ CreateDvrWriteBufferQueueFromProducerQueue(
+ ProducerQueue::Create<DvrNativeBufferMetadata>(0, 0, 0, 0)),
+ dvrWriteBufferQueueDestroy);
+ ASSERT_NE(nullptr, write_queue.get());
ret = dvrWriteBufferQueueGetExternalSurface(write_queue.get(), &window);
ASSERT_EQ(0, ret);
diff --git a/libs/vr/libdvr/tests/dvr_display_manager-test.cpp b/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
new file mode 100644
index 0000000..0150984
--- /dev/null
+++ b/libs/vr/libdvr/tests/dvr_display_manager-test.cpp
@@ -0,0 +1,539 @@
+#include <base/logging.h>
+#include <gtest/gtest.h>
+#include <poll.h>
+
+#include <android/hardware_buffer.h>
+
+#include <algorithm>
+#include <set>
+#include <thread>
+#include <vector>
+
+#include <dvr/dvr_deleter.h>
+#include <dvr/dvr_display_manager.h>
+#include <dvr/dvr_surface.h>
+
+#include <pdx/status.h>
+
+using android::pdx::ErrorStatus;
+using android::pdx::Status;
+
+namespace android {
+namespace dvr {
+
+namespace {
+
+DvrSurfaceAttribute GetAttribute(DvrSurfaceAttributeKey key, bool value) {
+ DvrSurfaceAttribute attribute;
+ attribute.key = key;
+ attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL;
+ attribute.value.bool_value = value;
+ return attribute;
+}
+
+DvrSurfaceAttribute GetAttribute(DvrSurfaceAttributeKey key, int32_t value) {
+ DvrSurfaceAttribute attribute;
+ attribute.key = key;
+ attribute.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT32;
+ attribute.value.bool_value = value;
+ return attribute;
+}
+
+Status<UniqueDvrSurface> CreateApplicationSurface(bool visible = false,
+ int32_t z_order = 0) {
+ DvrSurface* surface = nullptr;
+ DvrSurfaceAttribute attributes[] = {
+ GetAttribute(DVR_SURFACE_ATTRIBUTE_Z_ORDER, z_order),
+ GetAttribute(DVR_SURFACE_ATTRIBUTE_VISIBLE, visible)};
+
+ const int ret = dvrSurfaceCreate(
+ attributes, std::extent<decltype(attributes)>::value, &surface);
+ if (ret < 0)
+ return ErrorStatus(-ret);
+ else
+ return {UniqueDvrSurface(surface)};
+}
+
+Status<UniqueDvrWriteBufferQueue> CreateSurfaceQueue(
+ const UniqueDvrSurface& surface, uint32_t width, uint32_t height,
+ uint32_t format, uint64_t usage, size_t capacity) {
+ DvrWriteBufferQueue* queue;
+ const int ret = dvrSurfaceCreateWriteBufferQueue(
+ surface.get(), width, height, format, usage, capacity, &queue);
+ if (ret < 0)
+ return ErrorStatus(-ret);
+ else
+ return {UniqueDvrWriteBufferQueue(queue)};
+}
+
+class TestDisplayManager {
+ public:
+ TestDisplayManager(UniqueDvrDisplayManager display_manager,
+ UniqueDvrSurfaceState surface_state)
+ : display_manager_(std::move(display_manager)),
+ surface_state_(std::move(surface_state)) {
+ const int fd = dvrDisplayManagerGetEventFd(display_manager_.get());
+ LOG_IF(INFO, fd < 0) << "Failed to get event fd: " << strerror(-fd);
+ display_manager_event_fd_ = fd;
+ }
+
+ Status<UniqueDvrReadBufferQueue> GetReadBufferQueue(int surface_id,
+ int queue_id) {
+ DvrReadBufferQueue* queue;
+ const int ret = dvrDisplayManagerGetReadBufferQueue(
+ display_manager_.get(), surface_id, queue_id, &queue);
+ if (ret < 0)
+ return ErrorStatus(-ret);
+ else
+ return {UniqueDvrReadBufferQueue(queue)};
+ }
+
+ Status<void> UpdateSurfaceState() {
+ const int ret = dvrDisplayManagerGetSurfaceState(display_manager_.get(),
+ surface_state_.get());
+ if (ret < 0)
+ return ErrorStatus(-ret);
+ else
+ return {};
+ }
+
+ Status<void> WaitForUpdate() {
+ if (display_manager_event_fd_ < 0)
+ return ErrorStatus(-display_manager_event_fd_);
+
+ const int kTimeoutMs = 10000; // 10s
+ pollfd pfd = {display_manager_event_fd_, POLLIN, 0};
+ const int count = poll(&pfd, 1, kTimeoutMs);
+ if (count < 0)
+ return ErrorStatus(errno);
+ else if (count == 0)
+ return ErrorStatus(ETIMEDOUT);
+
+ int events;
+ const int ret = dvrDisplayManagerTranslateEpollEventMask(
+ display_manager_.get(), pfd.revents, &events);
+ if (ret < 0)
+ return ErrorStatus(-ret);
+ else if (events & POLLIN)
+ return UpdateSurfaceState();
+ else
+ return ErrorStatus(EPROTO);
+ }
+
+ Status<size_t> GetSurfaceCount() {
+ size_t count = 0;
+ const int ret =
+ dvrSurfaceStateGetSurfaceCount(surface_state_.get(), &count);
+ if (ret < 0)
+ return ErrorStatus(-ret);
+ else
+ return {count};
+ }
+
+ Status<DvrSurfaceUpdateFlags> GetUpdateFlags(size_t surface_index) {
+ DvrSurfaceUpdateFlags update_flags;
+ const int ret = dvrSurfaceStateGetUpdateFlags(surface_state_.get(),
+ surface_index, &update_flags);
+ if (ret < 0)
+ return ErrorStatus(-ret);
+ else
+ return {update_flags};
+ }
+
+ Status<int> GetSurfaceId(size_t surface_index) {
+ int surface_id;
+ const int ret = dvrSurfaceStateGetSurfaceId(surface_state_.get(),
+ surface_index, &surface_id);
+ if (ret < 0)
+ return ErrorStatus(-ret);
+ else
+ return {surface_id};
+ }
+
+ Status<int> GetProcessId(size_t surface_index) {
+ int process_id;
+ const int ret = dvrSurfaceStateGetProcessId(surface_state_.get(),
+ surface_index, &process_id);
+ if (ret < 0)
+ return ErrorStatus(-ret);
+ else
+ return {process_id};
+ }
+
+ Status<std::vector<DvrSurfaceAttribute>> GetAttributes(size_t surface_index) {
+ std::vector<DvrSurfaceAttribute> attributes;
+ size_t count = 0;
+ const int ret = dvrSurfaceStateGetAttributeCount(surface_state_.get(),
+ surface_index, &count);
+ if (ret < 0)
+ return ErrorStatus(-ret);
+
+ attributes.resize(count);
+ const ssize_t return_count = dvrSurfaceStateGetAttributes(
+ surface_state_.get(), surface_index, attributes.data(), count);
+ if (return_count < 0)
+ return ErrorStatus(-return_count);
+
+ attributes.resize(return_count);
+ return {std::move(attributes)};
+ }
+
+ Status<std::vector<int>> GetQueueIds(size_t surface_index) {
+ std::vector<int> queue_ids;
+ size_t count = 0;
+ const int ret = dvrSurfaceStateGetQueueCount(surface_state_.get(),
+ surface_index, &count);
+ if (ret < 0)
+ return ErrorStatus(-ret);
+
+ if (count > 0) {
+ queue_ids.resize(count);
+ const ssize_t return_count = dvrSurfaceStateGetQueueIds(
+ surface_state_.get(), surface_index, queue_ids.data(), count);
+ if (return_count < 0)
+ return ErrorStatus(-return_count);
+
+ queue_ids.resize(return_count);
+ }
+
+ return {std::move(queue_ids)};
+ }
+
+ private:
+ UniqueDvrDisplayManager display_manager_;
+ UniqueDvrSurfaceState surface_state_;
+
+ // Owned by object in display_manager_, do not explicitly close.
+ int display_manager_event_fd_;
+
+ TestDisplayManager(const TestDisplayManager&) = delete;
+ void operator=(const TestDisplayManager&) = delete;
+};
+
+class DvrDisplayManagerTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ int ret;
+ DvrDisplayManager* display_manager;
+ DvrSurfaceState* surface_state;
+
+ ret = dvrDisplayManagerCreate(&display_manager);
+ ASSERT_EQ(0, ret) << "Failed to create display manager client";
+ ASSERT_NE(nullptr, display_manager);
+
+ ret = dvrSurfaceStateCreate(&surface_state);
+ ASSERT_EQ(0, ret) << "Failed to create surface state object";
+ ASSERT_NE(nullptr, surface_state);
+
+ manager_.reset(
+ new TestDisplayManager(UniqueDvrDisplayManager(display_manager),
+ UniqueDvrSurfaceState(surface_state)));
+ }
+ void TearDown() override {}
+
+ std::unique_ptr<TestDisplayManager> manager_;
+};
+
+// TODO(eieio): Consider moving these somewhere more central because they are
+// broadly useful.
+
+template <typename T>
+testing::AssertionResult StatusOk(const char* status_expression,
+ const Status<T>& status) {
+ if (!status.ok()) {
+ return testing::AssertionFailure()
+ << "(" << status_expression
+ << ") expected to indicate success but actually contains error ("
+ << status.error() << ")";
+ } else {
+ return testing::AssertionSuccess();
+ }
+}
+
+template <typename T>
+testing::AssertionResult StatusError(const char* status_expression,
+ const Status<T>& status) {
+ if (status.ok()) {
+ return testing::AssertionFailure()
+ << "(" << status_expression
+ << ") expected to indicate error but instead indicates success.";
+ } else {
+ return testing::AssertionSuccess();
+ }
+}
+
+template <typename T>
+testing::AssertionResult StatusHasError(const char* status_expression,
+ const char* /*error_code_expression*/,
+ const Status<T>& status,
+ int error_code) {
+ if (status.ok()) {
+ return StatusError(status_expression, status);
+ } else if (status.error() != error_code) {
+ return testing::AssertionFailure()
+ << "(" << status_expression << ") expected to indicate error ("
+ << error_code << ") but actually indicates error (" << status.error()
+ << ")";
+ } else {
+ return testing::AssertionSuccess();
+ }
+}
+
+template <typename T, typename U>
+testing::AssertionResult StatusHasValue(const char* status_expression,
+ const char* /*value_expression*/,
+ const Status<T>& status,
+ const U& value) {
+ if (!status.ok()) {
+ return StatusOk(status_expression, status);
+ } else if (status.get() != value) {
+ return testing::AssertionFailure()
+ << "(" << status_expression << ") expected to contain value ("
+ << testing::PrintToString(value) << ") but actually contains value ("
+ << testing::PrintToString(status.get()) << ")";
+ } else {
+ return testing::AssertionSuccess();
+ }
+}
+
+template <typename T, typename Op>
+testing::AssertionResult StatusPred(const char* status_expression,
+ const char* pred_expression,
+ const Status<T>& status, Op pred) {
+ if (!status.ok()) {
+ return StatusOk(status_expression, status);
+ } else if (!pred(status.get())) {
+ return testing::AssertionFailure()
+ << status_expression << " value ("
+ << testing::PrintToString(status.get())
+ << ") failed to pass predicate " << pred_expression;
+ } else {
+ return testing::AssertionSuccess();
+ }
+}
+
+#define ASSERT_STATUS_OK(status) ASSERT_PRED_FORMAT1(StatusOk, status)
+#define ASSERT_STATUS_ERROR(status) ASSERT_PRED_FORMAT1(StatusError, status)
+
+#define ASSERT_STATUS_ERROR_VALUE(value, status) \
+ ASSERT_PRED_FORMAT2(StatusHasError, status, value)
+
+#define ASSERT_STATUS_EQ(value, status) \
+ ASSERT_PRED_FORMAT2(StatusHasValue, status, value)
+
+#define EXPECT_STATUS_OK(status) EXPECT_PRED_FORMAT1(StatusOk, status)
+#define EXPECT_STATUS_ERROR(status) EXPECT_PRED_FORMAT1(StatusError, status)
+
+#define EXPECT_STATUS_ERROR_VALUE(value, status) \
+ EXPECT_PRED_FORMAT2(StatusHasError, status, value)
+
+#define EXPECT_STATUS_EQ(value, status) \
+ EXPECT_PRED_FORMAT2(StatusHasValue, status, value)
+
+#define EXPECT_STATUS_PRED(pred, status) \
+ EXPECT_PRED_FORMAT2(StatusPred, status, pred)
+
+#if 0
+// Verify utility predicate/macro functionality. This section is commented out
+// because it is designed to fail in some cases to validate the helpers.
+TEST_F(DvrDisplayManagerTest, ExpectVoid) {
+ Status<void> status_error{ErrorStatus{EINVAL}};
+ Status<void> status_ok{};
+
+ EXPECT_STATUS_ERROR(status_error);
+ EXPECT_STATUS_ERROR(status_ok);
+ EXPECT_STATUS_OK(status_error);
+ EXPECT_STATUS_OK(status_ok);
+
+ EXPECT_STATUS_ERROR_VALUE(EINVAL, status_error);
+ EXPECT_STATUS_ERROR_VALUE(ENOMEM, status_error);
+ EXPECT_STATUS_ERROR_VALUE(EINVAL, status_ok);
+ EXPECT_STATUS_ERROR_VALUE(ENOMEM, status_ok);
+}
+
+TEST_F(DvrDisplayManagerTest, ExpectInt) {
+ Status<int> status_error{ErrorStatus{EINVAL}};
+ Status<int> status_ok{10};
+
+ EXPECT_STATUS_ERROR(status_error);
+ EXPECT_STATUS_ERROR(status_ok);
+ EXPECT_STATUS_OK(status_error);
+ EXPECT_STATUS_OK(status_ok);
+
+ EXPECT_STATUS_ERROR_VALUE(EINVAL, status_error);
+ EXPECT_STATUS_ERROR_VALUE(ENOMEM, status_error);
+ EXPECT_STATUS_ERROR_VALUE(EINVAL, status_ok);
+ EXPECT_STATUS_ERROR_VALUE(ENOMEM, status_ok);
+
+ EXPECT_STATUS_EQ(10, status_error);
+ EXPECT_STATUS_EQ(20, status_error);
+ EXPECT_STATUS_EQ(10, status_ok);
+ EXPECT_STATUS_EQ(20, status_ok);
+
+ auto pred1 = [](const auto& value) { return value < 15; };
+ auto pred2 = [](const auto& value) { return value > 5; };
+ auto pred3 = [](const auto& value) { return value > 15; };
+ auto pred4 = [](const auto& value) { return value < 5; };
+
+ EXPECT_STATUS_PRED(pred1, status_error);
+ EXPECT_STATUS_PRED(pred2, status_error);
+ EXPECT_STATUS_PRED(pred3, status_error);
+ EXPECT_STATUS_PRED(pred4, status_error);
+ EXPECT_STATUS_PRED(pred1, status_ok);
+ EXPECT_STATUS_PRED(pred2, status_ok);
+ EXPECT_STATUS_PRED(pred3, status_ok);
+ EXPECT_STATUS_PRED(pred4, status_ok);
+}
+#endif
+
+TEST_F(DvrDisplayManagerTest, SurfaceCreateEvent) {
+ // Get surface state and verify there are no surfaces.
+ ASSERT_STATUS_OK(manager_->UpdateSurfaceState());
+ ASSERT_STATUS_EQ(0u, manager_->GetSurfaceCount());
+
+ // Get flags for invalid surface index.
+ EXPECT_STATUS_ERROR_VALUE(EINVAL, manager_->GetUpdateFlags(0));
+
+ // Create an application surface.
+ auto surface_status = CreateApplicationSurface();
+ ASSERT_STATUS_OK(surface_status);
+ UniqueDvrSurface surface = surface_status.take();
+ ASSERT_NE(nullptr, surface.get());
+
+ const int surface_id = dvrSurfaceGetId(surface.get());
+ ASSERT_GE(surface_id, 0);
+
+ // Now there should be one new surface.
+ ASSERT_STATUS_OK(manager_->WaitForUpdate());
+ EXPECT_STATUS_EQ(1u, manager_->GetSurfaceCount());
+
+ // Verify the new surface flag is set.
+ auto check_flags = [](const auto& value) {
+ return value & DVR_SURFACE_UPDATE_FLAGS_NEW_SURFACE;
+ };
+ EXPECT_STATUS_PRED(check_flags, manager_->GetUpdateFlags(0));
+
+ // Verify the surface id matches.
+ EXPECT_STATUS_EQ(surface_id, manager_->GetSurfaceId(0));
+
+ // Verify the owning process of the surface.
+ EXPECT_STATUS_EQ(getpid(), manager_->GetProcessId(0));
+
+ surface.reset();
+
+ ASSERT_STATUS_OK(manager_->WaitForUpdate());
+ EXPECT_STATUS_EQ(0u, manager_->GetSurfaceCount());
+}
+
+TEST_F(DvrDisplayManagerTest, SurfaceAttributeEvent) {
+ // Get surface state and verify there are no surfaces.
+ ASSERT_STATUS_OK(manager_->UpdateSurfaceState());
+ ASSERT_STATUS_EQ(0u, manager_->GetSurfaceCount());
+
+ // Get attributes for an invalid surface index.
+ EXPECT_STATUS_ERROR_VALUE(EINVAL, manager_->GetAttributes(0));
+
+ const bool kInitialVisibility = true;
+ const int32_t kInitialZOrder = 10;
+ auto surface_status =
+ CreateApplicationSurface(kInitialVisibility, kInitialZOrder);
+ ASSERT_STATUS_OK(surface_status);
+ auto surface = surface_status.take();
+ ASSERT_NE(nullptr, surface.get());
+
+ ASSERT_STATUS_OK(manager_->WaitForUpdate());
+ ASSERT_STATUS_EQ(1u, manager_->GetSurfaceCount());
+
+ // Check the initial attribute values.
+ auto attribute_status = manager_->GetAttributes(0);
+ ASSERT_STATUS_OK(attribute_status);
+ auto attributes = attribute_status.take();
+ EXPECT_GE(attributes.size(), 2u);
+
+ const std::set<int32_t> expected_keys = {DVR_SURFACE_ATTRIBUTE_Z_ORDER,
+ DVR_SURFACE_ATTRIBUTE_VISIBLE};
+
+ // Collect all the keys in attributes that match the expected keys.
+ std::set<int32_t> actual_keys;
+ std::for_each(attributes.begin(), attributes.end(),
+ [&expected_keys, &actual_keys](const auto& attribute) {
+ if (expected_keys.find(attribute.key) != expected_keys.end())
+ actual_keys.emplace(attribute.key);
+ });
+
+ // If the sets match then attributes contained at least the expected keys,
+ // even if other keys were also present.
+ EXPECT_EQ(expected_keys, actual_keys);
+}
+
+TEST_F(DvrDisplayManagerTest, SurfaceQueueEvent) {
+ // Create an application surface.
+ auto surface_status = CreateApplicationSurface();
+ ASSERT_STATUS_OK(surface_status);
+ UniqueDvrSurface surface = surface_status.take();
+ ASSERT_NE(nullptr, surface.get());
+
+ const int surface_id = dvrSurfaceGetId(surface.get());
+ ASSERT_GE(surface_id, 0);
+ // Get surface state and verify there is one surface.
+ ASSERT_STATUS_OK(manager_->WaitForUpdate());
+ ASSERT_STATUS_EQ(1u, manager_->GetSurfaceCount());
+
+ // Verify there are no queues for the surface recorded in the state snapshot.
+ EXPECT_STATUS_EQ(std::vector<int>{}, manager_->GetQueueIds(0));
+
+ // Create a new queue in the surface.
+ auto write_queue_status = CreateSurfaceQueue(
+ surface, 320, 240, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
+ AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, 1);
+ ASSERT_STATUS_OK(write_queue_status);
+ UniqueDvrWriteBufferQueue write_queue = write_queue_status.take();
+ ASSERT_NE(nullptr, write_queue.get());
+
+ const int queue_id = dvrWriteBufferQueueGetId(write_queue.get());
+ ASSERT_GE(queue_id, 0);
+
+ // Update surface state.
+ ASSERT_STATUS_OK(manager_->WaitForUpdate());
+ ASSERT_STATUS_EQ(1u, manager_->GetSurfaceCount());
+
+ // Verify the buffers changed flag is set.
+ auto check_flags = [](const auto& value) {
+ return value & DVR_SURFACE_UPDATE_FLAGS_BUFFERS_CHANGED;
+ };
+ EXPECT_STATUS_PRED(check_flags, manager_->GetUpdateFlags(0));
+
+ auto queue_ids_status = manager_->GetQueueIds(0);
+ ASSERT_STATUS_OK(queue_ids_status);
+
+ auto queue_ids = queue_ids_status.take();
+ ASSERT_EQ(1u, queue_ids.size());
+ EXPECT_EQ(queue_id, queue_ids[0]);
+
+ auto read_queue_status = manager_->GetReadBufferQueue(surface_id, queue_id);
+ ASSERT_STATUS_OK(read_queue_status);
+ UniqueDvrReadBufferQueue read_queue = read_queue_status.take();
+ ASSERT_NE(nullptr, read_queue.get());
+ EXPECT_EQ(queue_id, dvrReadBufferQueueGetId(read_queue.get()));
+
+ write_queue.reset();
+
+ // Verify that destroying the queue generates a surface update event.
+ ASSERT_STATUS_OK(manager_->WaitForUpdate());
+ ASSERT_STATUS_EQ(1u, manager_->GetSurfaceCount());
+
+ // Verify that the buffers changed flag is set.
+ EXPECT_STATUS_PRED(check_flags, manager_->GetUpdateFlags(0));
+
+ // Verify that the queue ids reflect the change.
+ queue_ids_status = manager_->GetQueueIds(0);
+ ASSERT_STATUS_OK(queue_ids_status);
+
+ queue_ids = queue_ids_status.take();
+ ASSERT_EQ(0u, queue_ids.size());
+}
+
+} // namespace
+
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
index caf20a5..e65f6d5 100644
--- a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
@@ -1,6 +1,6 @@
#include <android/hardware_buffer.h>
-#include <dvr/display_manager_client.h>
#include <dvr/dvr_buffer.h>
+#include <dvr/dvr_display_manager.h>
#include <dvr/dvr_surface.h>
#include <system/graphics.h>
@@ -15,28 +15,31 @@
class DvrNamedBufferTest : public ::testing::Test {
protected:
void SetUp() override {
- client_ = dvrDisplayManagerClientCreate();
+ const int ret = dvrDisplayManagerCreate(&client_);
+ ASSERT_EQ(0, ret);
ASSERT_NE(nullptr, client_);
}
void TearDown() override {
- if (client_ != nullptr) {
- dvrDisplayManagerClientDestroy(client_);
- client_ = nullptr;
- }
+ dvrDisplayManagerDestroy(client_);
+ client_ = nullptr;
}
- DvrDisplayManagerClient* client_ = nullptr;
+ DvrDisplayManager* client_ = nullptr;
};
TEST_F(DvrNamedBufferTest, TestNamedBuffersSameName) {
const char* buffer_name = "same_name";
- DvrBuffer* buffer1 =
- dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, 0);
+ DvrBuffer* buffer1 = nullptr;
+ int ret1 =
+ dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, &buffer1);
+ ASSERT_EQ(0, ret1);
ASSERT_NE(nullptr, buffer1);
- DvrBuffer* buffer2 =
- dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, 0);
+ DvrBuffer* buffer2 = nullptr;
+ int ret2 =
+ dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, &buffer2);
+ ASSERT_EQ(0, ret1);
ASSERT_NE(nullptr, buffer2);
AHardwareBuffer* hardware_buffer1 = nullptr;
@@ -73,7 +76,7 @@
ASSERT_EQ(0, e3);
AHardwareBuffer* hardware_buffer3 = nullptr;
- int e4 = dvrBufferGetAHardwareBuffer(buffer2, &hardware_buffer3);
+ int e4 = dvrBufferGetAHardwareBuffer(buffer3, &hardware_buffer3);
ASSERT_EQ(0, e4);
ASSERT_NE(nullptr, hardware_buffer3);
@@ -95,13 +98,17 @@
TEST_F(DvrNamedBufferTest, TestMultipleNamedBuffers) {
const char* buffer_name1 = "test1";
const char* buffer_name2 = "test2";
- DvrBuffer* setup_buffer1 =
- dvrDisplayManagerSetupNamedBuffer(client_, buffer_name1, 10, 0, 0);
+ DvrBuffer* setup_buffer1 = nullptr;
+ int ret1 = dvrDisplayManagerSetupNamedBuffer(client_, buffer_name1, 10, 0,
+ &setup_buffer1);
+ ASSERT_EQ(0, ret1);
ASSERT_NE(nullptr, setup_buffer1);
dvrBufferDestroy(setup_buffer1);
- DvrBuffer* setup_buffer2 =
- dvrDisplayManagerSetupNamedBuffer(client_, buffer_name2, 10, 0, 0);
+ DvrBuffer* setup_buffer2 = nullptr;
+ int ret2 = dvrDisplayManagerSetupNamedBuffer(client_, buffer_name2, 10, 0,
+ &setup_buffer2);
+ ASSERT_EQ(0, ret2);
ASSERT_NE(nullptr, setup_buffer2);
dvrBufferDestroy(setup_buffer2);
@@ -126,11 +133,13 @@
// GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER, and these two values are different.
// If all is good, when we get the AHardwareBuffer, it should be converted
// back to AHARDWAREBUFFER_USAGE_VIDEO_ENCODE.
- const int64_t usage = AHARDWAREBUFFER_USAGE_VIDEO_ENCODE;
+ const uint64_t usage = AHARDWAREBUFFER_USAGE_VIDEO_ENCODE;
- DvrBuffer* setup_buffer =
- dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, usage, 0);
+ DvrBuffer* setup_buffer = nullptr;
+ int e1 = dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, usage,
+ &setup_buffer);
ASSERT_NE(nullptr, setup_buffer);
+ ASSERT_EQ(0, e1);
AHardwareBuffer* hardware_buffer = nullptr;
int e2 = dvrBufferGetAHardwareBuffer(setup_buffer, &hardware_buffer);
@@ -139,14 +148,12 @@
AHardwareBuffer_Desc desc = {};
AHardwareBuffer_describe(hardware_buffer, &desc);
-
- ASSERT_EQ(desc.usage, AHARDWAREBUFFER_USAGE_VIDEO_ENCODE);
+ ASSERT_EQ(usage, desc.usage);
dvrBufferDestroy(setup_buffer);
AHardwareBuffer_release(hardware_buffer);
}
-
} // namespace
} // namespace dvr
diff --git a/libs/vr/libdvr/vsync_client_api.cpp b/libs/vr/libdvr/vsync_client_api.cpp
deleted file mode 100644
index dbddd3d..0000000
--- a/libs/vr/libdvr/vsync_client_api.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "include/dvr/vsync_client_api.h"
-
-#include <private/dvr/vsync_client.h>
-
-extern "C" {
-
-dvr_vsync_client* dvr_vsync_client_create() {
- auto client = android::dvr::VSyncClient::Create();
- return static_cast<dvr_vsync_client*>(client.release());
-}
-
-void dvr_vsync_client_destroy(dvr_vsync_client* client) {
- delete static_cast<android::dvr::VSyncClient*>(client);
-}
-
-int dvr_vsync_client_get_sched_info(dvr_vsync_client* client,
- int64_t* vsync_period_ns,
- int64_t* next_timestamp_ns,
- uint32_t* next_vsync_count) {
- return static_cast<android::dvr::VSyncClient*>(client)->GetSchedInfo(
- vsync_period_ns, next_timestamp_ns, next_vsync_count);
-}
-
-} // extern "C"
diff --git a/libs/vr/libdvrcommon/include/private/dvr/epoll_file_descriptor.h b/libs/vr/libdvrcommon/include/private/dvr/epoll_file_descriptor.h
index 91e12c5..099a409 100644
--- a/libs/vr/libdvrcommon/include/private/dvr/epoll_file_descriptor.h
+++ b/libs/vr/libdvrcommon/include/private/dvr/epoll_file_descriptor.h
@@ -52,6 +52,8 @@
return ret;
}
+ int Get() const { return fd_.get(); }
+
private:
base::unique_fd fd_;
};
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 632978b..dc81c60 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -14,17 +14,11 @@
sourceFiles = [
"acquired_buffer.cpp",
- "compositor.cpp",
- "debug_hud_data.cpp",
- "debug_hud_view.cpp",
+ "epoll_event_dispatcher.cpp",
"display_manager_service.cpp",
"display_service.cpp",
"display_surface.cpp",
"hardware_composer.cpp",
- "screenshot_service.cpp",
- "surface_channel.cpp",
- "video_compositor.cpp",
- "video_mesh_surface.cpp",
"vr_flinger.cpp",
"vsync_service.cpp",
]
diff --git a/libs/vr/libvrflinger/acquired_buffer.cpp b/libs/vr/libvrflinger/acquired_buffer.cpp
index 5a3aa7f..7932a9c 100644
--- a/libs/vr/libvrflinger/acquired_buffer.cpp
+++ b/libs/vr/libvrflinger/acquired_buffer.cpp
@@ -9,7 +9,7 @@
namespace dvr {
AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
- LocalHandle acquire_fence, uint64_t /*sequence*/)
+ LocalHandle acquire_fence)
: buffer_(buffer), acquire_fence_(std::move(acquire_fence)) {}
AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
diff --git a/libs/vr/libvrflinger/acquired_buffer.h b/libs/vr/libvrflinger/acquired_buffer.h
index 1d14a38..dd4fcc5 100644
--- a/libs/vr/libvrflinger/acquired_buffer.h
+++ b/libs/vr/libvrflinger/acquired_buffer.h
@@ -21,7 +21,7 @@
// this constructor; the constructor does not attempt to ACQUIRE the buffer
// itself.
AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
- pdx::LocalHandle acquire_fence, uint64_t sequence);
+ pdx::LocalHandle acquire_fence);
// Constructs an AcquiredBuffer from a BufferConsumer. The BufferConsumer MUST
// be in the POSTED state prior to calling this constructor, as this
diff --git a/libs/vr/libvrflinger/compositor.cpp b/libs/vr/libvrflinger/compositor.cpp
deleted file mode 100644
index d1d4f45..0000000
--- a/libs/vr/libvrflinger/compositor.cpp
+++ /dev/null
@@ -1,878 +0,0 @@
-#include "compositor.h"
-
-#include <EGL/eglext.h>
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#include <GLES2/gl2.h>
-
-#include <memory>
-
-#include <cutils/properties.h>
-
-#include <dvr/graphics.h>
-#include <private/dvr/buffer_hub_client.h>
-#include <private/dvr/clock_ns.h>
-#include <private/dvr/debug.h>
-#include <private/dvr/device_metrics.h>
-#include <private/dvr/display_types.h>
-#include <private/dvr/dummy_native_window.h>
-#include <private/dvr/gl_fenced_flush.h>
-#include <private/dvr/graphics/blur.h>
-#include <private/dvr/graphics/gpu_profiler.h>
-#include <private/dvr/native_buffer.h>
-#include <private/dvr/platform_defines.h>
-#include <utils/Log.h>
-#include <utils/Trace.h>
-
-#include "debug_hud_data.h"
-#include "debug_hud_view.h"
-#include "display_surface.h"
-
-#define BINNING_CONTROL_HINT_QCOM 0x8FB0
-
-// Accepted by the <hint> parameter of glHint:
-#define BINNING_QCOM 0x8FB1
-#define VISIBILITY_OPTIMIZED_BINNING_QCOM 0x8FB2
-#define RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3
-
-#ifndef EGL_CONTEXT_MAJOR_VERSION
-#define EGL_CONTEXT_MAJOR_VERSION 0x3098
-#define EGL_CONTEXT_MINOR_VERSION 0x30FB
-#endif
-
-using android::pdx::LocalHandle;
-
-static const int kDistortionMeshResolution = 40;
-
-static std::shared_ptr<int64_t> eds_gpu_duration_ns =
- std::make_shared<int64_t>(0);
-
-static constexpr char kDisableLensDistortionProp[] =
- "persist.dvr.disable_distort";
-
-static constexpr char kEnableEdsPoseSaveProp[] =
- "persist.dvr.save_eds_pose";
-
-namespace android {
-namespace dvr {
-
-namespace {
-
-// An implementation of ANativeWindowBuffer backed by a temporary IonBuffer.
-// Do not hold on to this kind of object, because the IonBuffer may become
-// invalid in other scopes.
-class TemporaryNativeBuffer
- : public ANativeObjectBase<ANativeWindowBuffer, TemporaryNativeBuffer,
- LightRefBase<TemporaryNativeBuffer>> {
- public:
- explicit TemporaryNativeBuffer(const IonBuffer* buffer) : BASE() {
- ANativeWindowBuffer::width = buffer->width();
- ANativeWindowBuffer::height = buffer->height();
- ANativeWindowBuffer::stride = buffer->stride();
- ANativeWindowBuffer::format = buffer->format();
- ANativeWindowBuffer::usage = buffer->usage();
- // TODO(eieio): Update NYC to support layer_count.
- // ANativeWindowBuffer::layer_count = 1;
- handle = buffer->handle();
- }
-
- private:
- friend class android::LightRefBase<TemporaryNativeBuffer>;
-
- TemporaryNativeBuffer(const TemporaryNativeBuffer&) = delete;
- void operator=(TemporaryNativeBuffer&) = delete;
-};
-
-std::vector<uint8_t> ReadTextureRGBA(GLuint texture_id, int width, int height) {
- std::vector<uint8_t> data(width * height * 4);
- GLuint fbo;
- glGenFramebuffers(1, &fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, fbo);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
- texture_id, 0);
- // Using default GL_PACK_ALIGNMENT of 4 for the 4 byte source data.
- glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- glDeleteFramebuffers(1, &fbo);
- CHECK_GL();
- return data;
-}
-
-} // namespace
-
-class Compositor::Texture {
- public:
- Texture(std::shared_ptr<BufferConsumer> consumer, EGLDisplay display,
- int index);
- ~Texture();
-
- std::shared_ptr<BufferConsumer> consumer() const { return consumer_; }
- GLuint texture_id() const { return texture_id_; }
- vec2i size() const {
- return vec2i(native_buffer_.get()->width, native_buffer_.get()->height);
- }
- int index() const { return index_; }
-
- bool Initialize();
-
- private:
- Texture(const Texture&) = delete;
- void operator=(const Texture&) = delete;
-
- std::shared_ptr<BufferConsumer> consumer_;
-
- android::sp<NativeBufferConsumer> native_buffer_;
-
- EGLDisplay display_;
- EGLImageKHR image_;
- GLuint texture_id_;
- int index_;
-};
-
-Compositor::Texture::Texture(std::shared_ptr<BufferConsumer> consumer,
- EGLDisplay display, int index)
- : consumer_(consumer),
- display_(display),
- image_(nullptr),
- texture_id_(0),
- index_(index) {}
-
-Compositor::Texture::~Texture() {
- glDeleteTextures(1, &texture_id_);
- eglDestroyImageKHR(display_, image_);
-}
-
-bool Compositor::Texture::Initialize() {
- native_buffer_ = new NativeBufferConsumer(consumer_, index_);
-
- CHECK_GL();
- image_ = eglCreateImageKHR(
- display_, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
- static_cast<ANativeWindowBuffer*>(native_buffer_.get()), nullptr);
- if (!image_) {
- ALOGE("Failed to create EGLImage\n");
- return false;
- }
-
- glGenTextures(1, &texture_id_);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, texture_id_);
- glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image_);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- CHECK_GL();
- return true;
-}
-
-Compositor::RenderTarget::RenderTarget()
- : buffer_texture_id_(0),
- buffer_framebuffer_id_(0),
- buffer_image_(nullptr) {}
-
-Compositor::RenderTarget::~RenderTarget() { Destroy(); }
-
-void Compositor::RenderTarget::Destroy() {
- glDeleteFramebuffers(1, &buffer_framebuffer_id_);
- glDeleteTextures(1, &buffer_texture_id_);
- eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), buffer_image_);
- buffer_texture_id_ = 0;
- buffer_framebuffer_id_ = 0;
- buffer_image_ = nullptr;
-}
-
-void Compositor::RenderTarget::Initialize(int width, int height) {
- LOG_ALWAYS_FATAL_IF(buffer_texture_id_ || buffer_framebuffer_id_ ||
- buffer_image_);
- constexpr int usage = GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER |
- GRALLOC_USAGE_HW_RENDER |
- GRALLOC_USAGE_QCOM_FRAMEBUFFER_COMPRESSION;
- buffer_ = std::make_shared<IonBuffer>(width, height,
- HAL_PIXEL_FORMAT_RGBA_8888, usage);
-
- native_buffer_ = new NativeBuffer(buffer_);
-
- buffer_image_ = eglCreateImageKHR(
- eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_NO_CONTEXT,
- EGL_NATIVE_BUFFER_ANDROID,
- static_cast<ANativeWindowBuffer*>(native_buffer_.get()), nullptr);
-
- glGenTextures(1, &buffer_texture_id_);
- glBindTexture(GL_TEXTURE_2D, buffer_texture_id_);
- CHECK_GL();
-
- glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, buffer_image_);
- CHECK_GL();
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glBindTexture(GL_TEXTURE_2D, 0);
-
- // Generate a framebuffer.
- glGenFramebuffers(1, &buffer_framebuffer_id_);
- glBindFramebuffer(GL_FRAMEBUFFER, buffer_framebuffer_id_);
- CHECK_GL();
-
- // Attach the color buffer
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
- buffer_texture_id_, 0);
- CHECK_GL();
- GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- CHECK_GL();
- if (result != GL_FRAMEBUFFER_COMPLETE) {
- ALOGE("Framebuffer incomplete: %d", result);
- }
-
- // Clear the render target to black once. In direct render mode we never draw
- // the corner pixels.
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glClear(GL_COLOR_BUFFER_BIT);
- glFlush();
-
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- CHECK_GL();
-}
-
-void Compositor::RenderTarget::BindFramebuffer() {
- glBindFramebuffer(GL_FRAMEBUFFER, buffer_framebuffer_id_);
-}
-
-void Compositor::RenderTarget::DiscardColorAttachment() {
- GLenum attachment = GL_COLOR_ATTACHMENT0;
- glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &attachment);
- CHECK_GL();
-}
-
-class Compositor::RenderPoseBufferObject {
- public:
- RenderPoseBufferObject(LocalHandle&& render_pose_buffer_fd) :
- fd_(std::move(render_pose_buffer_fd)) {
- // Create new pose tracking buffer for this surface.
- glGenBuffers(1, &render_pose_buffer_object_);
- glBindBuffer(GL_UNIFORM_BUFFER, render_pose_buffer_object_);
- if (fd_) {
- LOG_ALWAYS_FATAL_IF(!glBindSharedBufferQCOM);
- if (glBindSharedBufferQCOM)
- glBindSharedBufferQCOM(GL_UNIFORM_BUFFER,
- sizeof(DisplaySurfaceMetadata),
- fd_.Get());
- else
- ALOGE("Error: Missing gralloc buffer extension");
- CHECK_GL();
- }
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
- }
-
- ~RenderPoseBufferObject() { glDeleteBuffers(1, &render_pose_buffer_object_); }
-
- GLuint object_id() const { return render_pose_buffer_object_; }
-
- private:
- // Render pose buffer object. This contains an array of poses that corresponds
- // with the surface buffers.
- GLuint render_pose_buffer_object_;
- LocalHandle fd_;
-
- RenderPoseBufferObject(const RenderPoseBufferObject&) = delete;
- void operator=(const RenderPoseBufferObject&) = delete;
-};
-
-HeadMountMetrics CreateDefaultHeadMountMetrics() {
- const bool enable_distortion =
- property_get_bool(kDisableLensDistortionProp, 0) == 0;
- return enable_distortion ? CreateHeadMountMetrics()
- : CreateUndistortedHeadMountMetrics();
-}
-
-Compositor::Compositor()
- : head_mount_metrics_(CreateDefaultHeadMountMetrics()),
- display_(0),
- config_(0),
- surface_(0),
- context_(0),
- active_render_target_(0),
- is_render_direct_(false),
- compute_fbo_(0),
- compute_fbo_texture_(0),
- hmd_metrics_requires_update_(false),
- eds_pose_capture_enabled_(false) {}
-
-Compositor::~Compositor() {}
-
-bool Compositor::Initialize(const DisplayMetrics& display_metrics) {
- ATRACE_NAME("Compositor::Initialize");
- if (!InitializeEGL())
- return false;
-
- display_metrics_ = display_metrics;
- const int width = display_metrics_.GetSizePixels().x();
- const int height = display_metrics_.GetSizePixels().y();
-
- render_target_[0].Initialize(width, height);
- render_target_[1].Initialize(width, height);
-
- // EDS:
- GpuProfiler::Get()->SetEnableGpuTracing(true);
-
- eds_pose_capture_enabled_ = property_get_bool(kEnableEdsPoseSaveProp, 0) == 1;
-
- CheckAndUpdateHeadMountMetrics(true);
-
- debug_hud_.reset(new DebugHudView(*composite_hmd_.get()));
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- return true;
-}
-
-void Compositor::UpdateHeadMountMetrics(
- const HeadMountMetrics& head_mount_metrics) {
- // Recalculating the mesh must be done in the draw loop, defer until then.
- std::lock_guard<std::mutex> _lock(mutex_);
- head_mount_metrics_ = head_mount_metrics;
- hmd_metrics_requires_update_ = true;
-}
-
-void Compositor::CheckAndUpdateHeadMountMetrics(bool force_update) {
- std::lock_guard<std::mutex> _lock(mutex_);
- if (hmd_metrics_requires_update_ || force_update) {
- hmd_metrics_requires_update_ = false;
- composite_hmd_.reset(
- new CompositeHmd(head_mount_metrics_, display_metrics_));
- CHECK_GL();
- eds_renderer_.reset(new DistortionRenderer(
- *composite_hmd_.get(), display_metrics_.GetSizePixels(),
- kDistortionMeshResolution, true, false, false, true, true));
- }
-}
-
-bool Compositor::InitializeEGL() {
- ATRACE_NAME("Compositor::InitializeEGL");
- display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (!display_) {
- ALOGE("Failed to get egl display\n");
- return false;
- }
-
- eglInitialize(display_, nullptr, nullptr);
-
- EGLint attribs[] = {
- EGL_BUFFER_SIZE,
- 32,
- EGL_ALPHA_SIZE,
- 0,
- EGL_BLUE_SIZE,
- 8,
- EGL_RED_SIZE,
- 8,
- EGL_GREEN_SIZE,
- 8,
- EGL_DEPTH_SIZE,
- 0,
- EGL_SURFACE_TYPE,
- EGL_WINDOW_BIT,
- EGL_RENDERABLE_TYPE,
- EGL_OPENGL_ES2_BIT,
- EGL_NONE,
- };
-
- EGLint num_configs;
- if (!eglChooseConfig(display_, attribs, &config_, 1, &num_configs)) {
- ALOGE("Couldn't find config");
- return false;
- }
-
- std::unique_ptr<DummyNativeWindow> window(new DummyNativeWindow());
-
- surface_ = eglCreateWindowSurface(display_, config_, window.get(), nullptr);
- if (surface_ == EGL_NO_SURFACE) {
- ALOGE("Failed to create egl surface");
- return false;
- }
- window.release();
-
- EGLint context_attribs[] = {EGL_CONTEXT_MAJOR_VERSION,
- 3,
- EGL_CONTEXT_MINOR_VERSION,
- 1,
- EGL_CONTEXT_PRIORITY_LEVEL_IMG,
- EGL_CONTEXT_PRIORITY_HIGH_IMG,
- EGL_NONE};
- context_ = eglCreateContext(display_, config_, nullptr, context_attribs);
- if (!eglMakeCurrent(display_, surface_, surface_, context_)) {
- ALOGE("Unable to create GLESv2 context");
- return false;
- }
-
- load_gl_extensions();
- GpuProfiler::Get()->OnGlContextCreated();
-
- glEnable(BINNING_CONTROL_HINT_QCOM);
- glHint(BINNING_CONTROL_HINT_QCOM, RENDER_DIRECT_TO_FRAMEBUFFER_QCOM);
- is_render_direct_ = true;
- CHECK_GL();
-
- // Initialize the placeholder 1x1 framebuffer that we bind during compute
- // shader instances to avoid accesses to other framebuffers.
- glGenFramebuffers(1, &compute_fbo_);
- glGenTextures(1, &compute_fbo_texture_);
- glBindFramebuffer(GL_FRAMEBUFFER, compute_fbo_);
- glBindTexture(GL_TEXTURE_2D, compute_fbo_texture_);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
- nullptr);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
- compute_fbo_texture_, 0);
- CHECK_GL();
- CHECK_GL_FBO();
- glBindTexture(GL_TEXTURE_2D, 0);
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
- return true;
-}
-
-void Compositor::Shutdown() {
- glFinish();
- render_target_[0].Destroy();
- render_target_[1].Destroy();
- layers_.clear();
- glDeleteFramebuffers(1, &compute_fbo_);
- glDeleteTextures(1, &compute_fbo_texture_);
-
- debug_hud_.reset();
- eds_renderer_.reset();
-
- if (context_) {
- GpuProfiler::Get()->OnGlContextDestroyed();
- eglDestroyContext(display_, context_);
- context_ = 0;
- }
-
- if (surface_ != EGL_NO_SURFACE) {
- eglDestroySurface(display_, surface_);
- surface_ = EGL_NO_SURFACE;
- }
-}
-
-void Compositor::RemoveAllBuffers() { layers_.clear(); }
-
-void Compositor::UpdateSurfaces(
- const std::vector<std::shared_ptr<DisplaySurface>>& surfaces) {
- // Delete the removed surfaces.
- layers_.erase(
- std::remove_if(layers_.begin(), layers_.end(),
- [&surfaces](const AppFrame& layer) {
- for (const auto& surface : surfaces)
- if (surface->surface_id() == layer.surface_id())
- return false;
- return true;
- }),
- layers_.end());
- // New surfaces are added on-demand as buffers are posted.
-}
-
-Compositor::AppFrame::AppFrame()
- : surface_id_(-1),
- blur_(0.0f),
- z_order_(0),
- vertical_flip_(false),
- enable_cac_(true),
- render_buffer_index_(0) {}
-
-Compositor::AppFrame::~AppFrame() {}
-
-const Compositor::Texture* Compositor::AppFrame::GetGlTextureId(
- EGLDisplay display, int index) {
- auto buffer_consumer = buffer_.buffer();
- if (!buffer_consumer) {
- return nullptr;
- }
- auto texture_it = std::find_if(
- textures_.begin(), textures_.end(),
- [buffer_consumer, index](const std::shared_ptr<Texture>& t) {
- return t->consumer() == buffer_consumer && t->index() == index;
- });
-
- if (texture_it != textures_.end()) {
- return (*texture_it).get();
- }
-
- textures_.push_back(
- std::make_shared<Texture>(buffer_consumer, display, index));
- if (!textures_.back()->Initialize()) {
- textures_.pop_back();
- return nullptr;
- }
- return textures_.back().get();
-}
-
-bool Compositor::AppFrame::UpdateSurface(
- const std::shared_ptr<DisplaySurface>& surface) {
- int surface_id = surface->surface_id();
- float blur = surface->manager_blur();
- bool need_sort = false;
- if (z_order_ != surface->layer_order()) {
- need_sort = true;
- z_order_ = surface->layer_order();
- }
-
- surface_id_ = surface_id;
- if (!render_pose_buffer_object_) {
- render_pose_buffer_object_.reset(
- new RenderPoseBufferObject(surface->GetMetadataBufferFd()));
- }
-
- blur_ = blur;
- vertical_flip_ =
- !!(surface->flags() & DVR_DISPLAY_SURFACE_FLAGS_VERTICAL_FLIP);
- enable_cac_ =
- !(surface->flags() & DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_CAC);
-
- AcquiredBuffer skipped_buffer;
- AcquiredBuffer buffer =
- surface->AcquireNewestAvailableBuffer(&skipped_buffer);
- if (!skipped_buffer.IsEmpty()) {
- DebugHudData::data.SkipLayerFrame(z_order_);
- ATRACE_NAME("DropToCatchUp");
- ATRACE_ASYNC_END("BufferPost", skipped_buffer.buffer()->id());
- }
- if (!buffer.IsEmpty()) {
- DebugHudData::data.AddLayerFrame(z_order_);
- // Buffer was already ready, so we don't need to wait on the fence.
- buffer.ClaimAcquireFence().Close();
- ATRACE_ASYNC_END("BufferPost", buffer.buffer()->id());
-
- render_buffer_index_ = surface->GetRenderBufferIndex(buffer.buffer()->id());
-
-#ifdef TRACE
- const volatile DisplaySurfaceMetadata* data =
- surface->GetMetadataBufferPtr();
-#endif
- ALOGE_IF(TRACE, "read pose index %d %f %f", render_buffer_index_,
- data->orientation[render_buffer_index_][0],
- data->orientation[render_buffer_index_][1]);
-
- // Move the new buffer over the old. AcquiredBuffer releases the old one.
- buffer_ = std::move(buffer);
- }
- return need_sort;
-}
-
-void Compositor::AppFrame::UpdateVideoMeshSurface(
- const std::shared_ptr<DisplaySurface>& surface) {
- // Update |video_compositors_| with |video_surface|. Note that
- // |UpdateVideoMeshSurface| should only be called on the PostThread before
- // |DrawFrame| is called. Thus, no synchronization is required for
- // |video_compositors_|.
- if (!surface->video_mesh_surfaces_updated())
- return;
-
- // TODO(jwcai) The following loop handles adding new surfaces; video mesh
- // removal logic shall be handled by listening to |OnChannelClose| event from
- // DisplayService.
- for (const auto& video_surface : surface->GetVideoMeshSurfaces()) {
- // Here we assume number of |video_surface|s is relatively small, thus, the
- // merge should be efficient enough.
- auto video_compositor_it = std::find_if(
- video_compositors_.begin(), video_compositors_.end(),
- [video_surface](const std::shared_ptr<VideoCompositor>& c) {
- return c->surface_id() == video_surface->surface_id();
- });
-
- if (video_compositor_it == video_compositors_.end()) {
- // This video surface is new, create a new VideoCompositor.
- video_compositors_.push_back(std::make_shared<VideoCompositor>(
- video_surface, surface->GetMetadataBufferPtr()));
- } else {
- // There is a compositor in |video_compositors_| is already set up for
- // this |video_surface|.
- ALOGW("Duplicated video_mesh_surface: surface_id=%d",
- video_surface->surface_id());
- }
- }
-}
-
-void Compositor::AppFrame::ResetBlurrers() { blurrers_.clear(); }
-
-void Compositor::AppFrame::AddBlurrer(Blur* blurrer) {
- blurrers_.emplace_back(blurrer);
-}
-
-void Compositor::PostBuffer(const std::shared_ptr<DisplaySurface>& surface) {
- int surface_id = surface->surface_id();
-
- ALOGD_IF(TRACE, "Post surface %d", surface_id);
-
- auto layer_it = std::find_if(layers_.begin(), layers_.end(),
- [surface_id](const AppFrame& frame) {
- return frame.surface_id() == surface_id;
- });
-
- bool need_sort = false;
- if (layer_it == layers_.end()) {
- layers_.push_back(AppFrame());
- layer_it = layers_.end() - 1;
- need_sort = true;
- }
-
- need_sort |= layer_it->UpdateSurface(surface);
- layer_it->UpdateVideoMeshSurface(surface);
-
- if (need_sort) {
- std::stable_sort(layers_.begin(), layers_.end());
- }
-}
-
-std::vector<uint8_t> Compositor::ReadLayerPixels(size_t index, int* width,
- int* height) {
- if (index >= layers_.size()) {
- return {};
- }
-
- const Texture* texture = layers_[index].GetGlTextureId(display_, 0);
- if (!texture) {
- return {};
- }
-
- *width = texture->size()[0];
- *height = texture->size()[1];
- return ReadTextureRGBA(texture->texture_id(), *width, *height);
-}
-
-std::vector<uint8_t> Compositor::ReadBufferPixels(const IonBuffer* buffer) {
- android::sp<TemporaryNativeBuffer> native_buffer =
- new TemporaryNativeBuffer(buffer);
-
- // Finish to make sure the GL driver has completed drawing of prior FBOs.
- // Since we are creating an EGL image here, the driver will not know that
- // there is a dependency on earlier GL draws.
- glFinish();
-
- EGLImageKHR image = eglCreateImageKHR(
- display_, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
- static_cast<ANativeWindowBuffer*>(native_buffer.get()), nullptr);
- if (!image) {
- ALOGE("Failed to create EGLImage\n");
- return {};
- }
-
- GLuint texture_id;
- glGenTextures(1, &texture_id);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, texture_id);
- glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
-
- int width = buffer->width();
- int height = buffer->height();
- std::vector<uint8_t> data = ReadTextureRGBA(texture_id, width, height);
-
- glBindTexture(GL_TEXTURE_2D, 0);
- glDeleteTextures(1, &texture_id);
- eglDestroyImageKHR(display_, image);
- return data;
-}
-
-bool Compositor::DrawFrame(uint32_t target_vsync_count,
- LocalHandle* buffer_fence_fd) {
- CheckAndUpdateHeadMountMetrics(false);
-
- ATRACE_NAME("Compositor::DrawFrame");
- GpuProfiler::Get()->PollGlTimerQueries();
-
- if (buffer_fence_fd)
- buffer_fence_fd->Close();
-
- int num_layers = 0;
- const int kMaxLayers = 4;
- GLuint texture_id[2][kMaxLayers] = {{0}};
- GLuint render_pose_buffer_id[kMaxLayers] = {0};
- uint32_t render_buffer_index[kMaxLayers] = {0};
- bool vertical_flip[kMaxLayers] = {false};
- bool separate_eye_textures[kMaxLayers] = {false};
- bool enable_cac[kMaxLayers] = {};
- CHECK_GL();
- for (auto& layer : layers_) {
- if (!layer.buffer().buffer()) {
- ATRACE_NAME("no_buffer");
- continue;
- }
-
- // Extract surface parameters.
- render_buffer_index[num_layers] = layer.render_buffer_index();
- render_pose_buffer_id[num_layers] =
- layer.render_pose_buffer_object()->object_id();
- vertical_flip[num_layers] = layer.vertical_flip();
- enable_cac[num_layers] =
- head_mount_metrics_.supports_chromatic_aberration_correction() &&
- layer.enable_cac();
-
- // Extract per-eye textures. These may be separate or joined (atlased).
- vec2i size(0, 0);
- int view_count = layer.buffer().buffer()->slice_count();
- ALOGE_IF(view_count > 2, "Error: more than 2 views not supported");
- view_count = std::min(2, view_count);
- separate_eye_textures[num_layers] = (view_count > 1);
- bool is_missing_texture = false;
- for (int eye = 0; eye < 2; ++eye) {
- // If view_count is 1, each eye texture is the 0th.
- int view_index = (view_count == 2) ? eye : 0;
- const Texture* texture = layer.GetGlTextureId(display_, view_index);
- // Texture will be null if the EGL image creation fails (hopefully never).
- if (!texture) {
- is_missing_texture = true;
- break;
- }
- // All views are currently expected to have the same size.
- size = texture->size();
- texture_id[eye][num_layers] = texture->texture_id();
- }
- if (is_missing_texture) {
- continue;
- }
-
- // Perform blur if requested.
- if (fabs(layer.blur()) > 0.001f) {
- // No need for CAC on blurred layers.
- enable_cac[num_layers] = false;
- if (layer.blurrer_count() < 1 || layer.blurrer(0)->width() != size[0] ||
- layer.blurrer(0)->height() != size[1]) {
- // Blur is created with the left eye texture, but the same instance
- // can be used for the right eye as well.
- layer.ResetBlurrers();
- layer.AddBlurrer(new Blur(size[0], size[1], texture_id[0][num_layers],
- GL_TEXTURE_2D, GL_TEXTURE_2D, true, display_,
- view_count));
- }
- // Reset blur instances to prepare for drawing.
- layer.blurrer(0)->StartFrame();
- layer.blurrer(0)->set_scale(layer.blur());
- // Perform blur and replace source texture with blurred output texture.
- if (view_count == 1) {
- // Single wide buffer for both eyes, blur both eyes in one operation.
- texture_id[0][num_layers] = texture_id[1][num_layers] =
- layer.blurrer(0)->DrawBlur(texture_id[0][num_layers]);
- } else {
- // Split eye buffers in a single frame, blur each framebuffer.
- texture_id[0][num_layers] =
- layer.blurrer(0)->DrawBlur(texture_id[0][num_layers]);
- texture_id[1][num_layers] =
- layer.blurrer(0)->DrawBlur(texture_id[1][num_layers]);
- }
- }
-
- ++num_layers;
- if (num_layers >= kMaxLayers)
- break;
- }
-
- CHECK_GL();
- // Set appropriate binning mode for the number of layers.
- if (num_layers > 1 && is_render_direct_) {
- is_render_direct_ = false;
- glDisable(BINNING_CONTROL_HINT_QCOM);
- } else if (num_layers <= 1 && !is_render_direct_) {
- is_render_direct_ = true;
- glEnable(BINNING_CONTROL_HINT_QCOM);
- glHint(BINNING_CONTROL_HINT_QCOM, RENDER_DIRECT_TO_FRAMEBUFFER_QCOM);
- }
-
- // Workaround for GL driver bug that causes the currently bound FBO to be
- // accessed during a compute shader pass (DoLateLatch below). Based on an
- // analysis with systrace, the best pattern here was to run the compute shader
- // with a *different* FBO than what will be drawn to afterward. So we bind
- // a dummy 1x1 FBO here and discard it. If instead, the current render target
- // is bound during the compute shader, the following draw calls will be forced
- // into direct mode rendering.
- glBindFramebuffer(GL_FRAMEBUFFER, compute_fbo_);
- GLenum attachment = GL_COLOR_ATTACHMENT0;
- glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &attachment);
-
- // Double buffer the render target. Get the render target we're drawing into,
- // and update the active buffer to the next buffer.
- RenderTarget& render_target = GetRenderTarget();
- SetNextRenderTarget();
-
- if (num_layers > 0) {
- // This trace prints the EDS+Warp GPU overhead and prints every 5 seconds:
- TRACE_GPU_PRINT("GPU EDS+Warp", 5 * 60);
- CHECK_GL();
- eds_renderer_->DoLateLatch(target_vsync_count, render_buffer_index,
- render_pose_buffer_id, vertical_flip,
- separate_eye_textures, num_layers);
-
- render_target.BindFramebuffer();
-
- // Discard to avoid unresolving the framebuffer during tiled rendering.
- render_target.DiscardColorAttachment();
-
- // For tiled mode rendering, we clear every frame to avoid garbage showing
- // up in the parts of tiles that are not rendered.
- if (!is_render_direct_) {
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glClear(GL_COLOR_BUFFER_BIT);
- }
-
- for (int eye = kLeftEye; eye <= kRightEye; ++eye) {
- eds_renderer_->PrepGlState(static_cast<EyeType>(eye));
- for (int layer_i = 0; layer_i < num_layers; ++layer_i) {
- bool blend_with_previous = layer_i > 0;
- uint32_t current_buffer_index = render_buffer_index[layer_i];
-
- // Render video mesh in the background of each graphics layer.
- layers_[layer_i].ForEachVideoCompositor([this, eye, layer_i,
- current_buffer_index,
- &blend_with_previous](
- const std::shared_ptr<VideoCompositor>& video_compositor) mutable {
- eds_renderer_->DrawVideoQuad(
- static_cast<EyeType>(eye), layer_i,
- video_compositor->GetActiveTextureId(display_),
- video_compositor->GetTransform(eye, current_buffer_index));
- blend_with_previous = true;
- });
-
- // Apply distortion to frame submitted from the app's GL context.
- eds_renderer_->SetChromaticAberrationCorrectionEnabled(
- enable_cac[layer_i]);
- eds_renderer_->ApplyDistortionCorrectionToTexture(
- static_cast<EyeType>(eye), &texture_id[eye][layer_i],
- &vertical_flip[layer_i], &separate_eye_textures[layer_i], &layer_i,
- 1, blend_with_previous, false);
- }
- }
- eds_renderer_->ResetGlState(1);
- CHECK_GL();
- } else {
- ALOGI("No buffers for compositing, clearing to black.");
- render_target.BindFramebuffer();
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glClear(GL_COLOR_BUFFER_BIT);
- }
-
- debug_hud_->Update();
- debug_hud_->Draw();
-
- LocalHandle fence_fd = CreateGLSyncAndFlush(display_);
-
- if (buffer_fence_fd)
- *buffer_fence_fd = std::move(fence_fd);
-
- if (eds_pose_capture_enabled_) {
- std::lock_guard<std::mutex> _lock(mutex_);
- eds_renderer_->GetLastEdsPose(&eds_pose_capture_);
- }
-
- return true;
-}
-
-bool Compositor::GetLastEdsPose(LateLatchOutput* out_data) {
- if (eds_pose_capture_enabled_) {
- std::lock_guard<std::mutex> _lock(mutex_);
- *out_data = eds_pose_capture_;
- return true;
- } else {
- ALOGE("Eds pose capture is not enabled.");
- return false;
- }
-}
-
-} // namespace dvr
-} // namespace android
diff --git a/libs/vr/libvrflinger/compositor.h b/libs/vr/libvrflinger/compositor.h
deleted file mode 100644
index be26d31..0000000
--- a/libs/vr/libvrflinger/compositor.h
+++ /dev/null
@@ -1,233 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_COMPOSITOR_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_COMPOSITOR_H_
-
-#include <EGL/egl.h>
-#include <log/log.h>
-#include <utils/StrongPointer.h>
-
-#include <memory>
-#include <mutex>
-#include <queue>
-#include <vector>
-
-#include <pdx/file_handle.h>
-#include <private/dvr/clock_ns.h>
-#include <private/dvr/composite_hmd.h>
-#include <private/dvr/display_metrics.h>
-#include <private/dvr/distortion_renderer.h>
-#include <private/dvr/frame_time_history.h>
-#include <private/dvr/ion_buffer.h>
-#include <private/dvr/native_buffer.h>
-
-#include "acquired_buffer.h"
-#include "video_compositor.h"
-struct DvrPose;
-
-namespace android {
-namespace dvr {
-
-class Blur;
-class BufferConsumer;
-class CompositeHmd;
-class DebugHudView;
-class DisplaySurface;
-
-// This is a GPU compositor for software EDS and lens warp on buffers provided
-// by HardwareComposer.
-class Compositor {
- public:
- Compositor();
- ~Compositor();
-
- bool Initialize(const DisplayMetrics& display_metrics);
- void UpdateHeadMountMetrics(const HeadMountMetrics& head_mount_metrics);
- void Shutdown();
-
- // Renders a frame with the latest buffers with EDS and warp applied.
- // buffer_fence_fd can be used to get a fence for the rendered frame. It can
- // be set to null if the fence isn't needed.
- bool DrawFrame(uint32_t target_vsync_count,
- pdx::LocalHandle* buffer_fence_fd);
-
- // Remove all buffers.
- void RemoveAllBuffers();
-
- // Synchronize compositor layers with in given surfaces.
- void UpdateSurfaces(
- const std::vector<std::shared_ptr<DisplaySurface>>& surfaces);
-
- // This must be called for each surface before DrawFrame is called.
- void PostBuffer(const std::shared_ptr<DisplaySurface>& surface);
-
- std::shared_ptr<IonBuffer> GetBuffer() const {
- return render_target_[active_render_target_].buffer();
- }
-
- // Returns the number of layers being rendered by the compositor.
- size_t GetLayerCount() const { return layers_.size(); }
-
- // Returns the source buffer at the given layer index or nullptr if none is
- // available.
- std::shared_ptr<BufferConsumer> PeekAtLayer(size_t index) const {
- if (index >= GetLayerCount())
- return nullptr;
- return layers_[index].buffer().buffer();
- }
-
- // Expensive operation to transfer the pixels of the given layer index into
- // unformatted memory and return as a RGBA buffer.
- // On success, returns non-zero sized vector and sets width and height.
- // On failure, returns empty vector.
- std::vector<uint8_t> ReadLayerPixels(size_t index, int* width, int* height);
-
- // Expensive operation to transfer the pixels of the given buffer into
- // unformatted memory and return as a RGBA buffer.
- // On success, returns non-zero sized vector.
- // On failure, returns empty vector.
- std::vector<uint8_t> ReadBufferPixels(const IonBuffer* buffer);
-
- bool GetLastEdsPose(LateLatchOutput* out_data);
-
- const HeadMountMetrics& head_mount_metrics() const {
- return head_mount_metrics_;
- }
-
- private:
- class Texture;
- class RenderPoseBufferObject;
-
- // A rendered frame from an application.
- class AppFrame {
- public:
- AppFrame();
- ~AppFrame();
-
- AppFrame(AppFrame&& other) = default;
- AppFrame& operator=(AppFrame&&) = default;
-
- // Gets a GL texture object for the current buffer. The resulting texture
- // object will be cached for future calls. Returns a pointer for temporary
- // access - not meant to hold on to.
- const Texture* GetGlTextureId(EGLDisplay display, int index);
-
- bool operator<(const AppFrame& rhs) const {
- return z_order_ < rhs.z_order_;
- }
- int z_order() const { return z_order_; }
- // Return true if this surface z order has been changed.
- bool UpdateSurface(const std::shared_ptr<DisplaySurface>& surface);
- void UpdateVideoMeshSurface(const std::shared_ptr<DisplaySurface>& surface);
- void ResetBlurrers();
- void AddBlurrer(Blur* blurrer);
-
- const AcquiredBuffer& buffer() const { return buffer_; }
- int surface_id() const { return surface_id_; }
- float blur() const { return blur_; }
- bool vertical_flip() const { return vertical_flip_; }
- bool enable_cac() const { return enable_cac_; }
- size_t blurrer_count() const { return blurrers_.size(); }
- Blur* blurrer(size_t i) {
- return blurrers_.size() < i ? nullptr : blurrers_[i].get();
- }
- uint32_t render_buffer_index() const { return render_buffer_index_; }
- const RenderPoseBufferObject* render_pose_buffer_object() const {
- return render_pose_buffer_object_.get();
- }
-
- template <class A>
- void ForEachVideoCompositor(A action) const {
- for (auto& c : video_compositors_) {
- action(c);
- }
- }
-
- private:
- int surface_id_;
- float blur_;
- int z_order_;
- bool vertical_flip_;
- bool enable_cac_;
- std::vector<std::unique_ptr<Blur>> blurrers_;
- AcquiredBuffer buffer_;
- std::vector<std::shared_ptr<Texture>> textures_;
- uint32_t render_buffer_index_;
- std::unique_ptr<RenderPoseBufferObject> render_pose_buffer_object_;
-
- // Active video mesh compositors
- std::vector<std::shared_ptr<VideoCompositor>> video_compositors_;
-
- AppFrame(const AppFrame& other) = delete;
- AppFrame& operator=(const AppFrame&) = delete;
- };
-
- class RenderTarget {
- public:
- RenderTarget();
- ~RenderTarget();
-
- void Initialize(int width, int height);
- void Destroy();
- void BindFramebuffer();
- void DiscardColorAttachment();
-
- std::shared_ptr<IonBuffer> buffer() const { return buffer_; }
-
- private:
- std::shared_ptr<IonBuffer> buffer_;
- android::sp<NativeBuffer> native_buffer_;
-
- GLuint buffer_texture_id_;
- GLuint buffer_framebuffer_id_;
- EGLImageKHR buffer_image_;
- };
-
- Compositor(const Compositor&) = delete;
- void operator=(const Compositor&) = delete;
-
- bool InitializeEGL();
-
- void UpdateHudToggle();
- void PrintStatsHud();
- void CheckAndUpdateHeadMountMetrics(bool force_update);
-
- RenderTarget& GetRenderTarget() {
- return render_target_[active_render_target_];
- }
-
- void SetNextRenderTarget() {
- active_render_target_ = (active_render_target_ + 1) & 1;
- }
-
- std::vector<AppFrame> layers_;
-
- DisplayMetrics display_metrics_;
- HeadMountMetrics head_mount_metrics_;
-
- EGLDisplay display_;
- EGLConfig config_;
- EGLSurface surface_;
- EGLContext context_;
- int active_render_target_;
- RenderTarget render_target_[2];
- bool is_render_direct_;
-
- // FBO for compute shader.
- GLuint compute_fbo_;
- GLuint compute_fbo_texture_;
-
- std::unique_ptr<DebugHudView> debug_hud_;
-
- // EDS:
- std::unique_ptr<CompositeHmd> composite_hmd_;
- bool hmd_metrics_requires_update_;
- std::unique_ptr<DistortionRenderer> eds_renderer_;
-
- bool eds_pose_capture_enabled_;
- std::mutex mutex_;
- LateLatchOutput eds_pose_capture_;
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_SERVICES_DISPLAYD_COMPOSITOR_H_
diff --git a/libs/vr/libvrflinger/debug_hud_data.cpp b/libs/vr/libvrflinger/debug_hud_data.cpp
deleted file mode 100644
index d387bba..0000000
--- a/libs/vr/libvrflinger/debug_hud_data.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-#include "debug_hud_data.h"
-
-namespace android {
-namespace dvr {
-
-DebugHudData DebugHudData::data;
-
-} // namespace dvr
-} // namespace android
diff --git a/libs/vr/libvrflinger/debug_hud_data.h b/libs/vr/libvrflinger/debug_hud_data.h
deleted file mode 100644
index 778169d..0000000
--- a/libs/vr/libvrflinger/debug_hud_data.h
+++ /dev/null
@@ -1,110 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_DEBUG_HUD_DATA_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_DEBUG_HUD_DATA_H_
-
-#include <stdint.h>
-
-#include <private/dvr/clock_ns.h>
-#include <private/dvr/frame_time_history.h>
-
-namespace android {
-namespace dvr {
-
-// Tracks debug stats for the displayd debug HUD. Unless otherwise noted,
-// there is no synchronization of data accesses to avoid performance impact.
-// All accesses to this data are on the displayd HWC post thread. Accesses from
-// other threads will need to be duly protected from races.
-// This is a lightweight struct to make it easy to add and remove
-// tracking data.
-struct DebugHudData {
- // Maximum supported layers for the debug HUD.
- enum { kMaxLayers = 4 };
-
- // The global singleton HUD data instance.
- static DebugHudData data;
-
- // Tracks framerate and skipped frames.
- struct FrameStats {
- void AddFrame() {
- int64_t now = GetSystemClockNs();
- frame_time.AddSample(now - last_frame_ts);
- last_frame_ts = now;
- }
-
- void SkipFrame() {
- AddFrame();
- ++drops;
- }
-
- int drops = 0;
- int64_t last_frame_ts = 0;
- FrameTimeHistory frame_time;
- };
-
- // Debug data for compositor layers (applications, system UI, etc).
- struct LayerData {
- void Reset() {
- ResetStats();
- width = 0;
- height = 0;
- is_separate = false;
- }
-
- void ResetStats() { frame_stats.drops = 0; }
-
- FrameStats frame_stats;
- int width = 0;
- int height = 0;
- bool is_separate = false;
- };
-
- // Resets the stats.
- void ResetStats() {
- hwc_frame_stats.drops = 0;
- hwc_latency = 0;
- for (auto& l : layer_data)
- l.ResetStats();
- }
-
- // Resets the layer configuration.
- void ResetLayers() {
- num_layers = 0;
- for (auto& l : layer_data)
- l.Reset();
- }
-
- // Tracks a frame arrival for the given layer.
- void AddLayerFrame(size_t layer) {
- if (layer < kMaxLayers) {
- num_layers = std::max(layer + 1, num_layers);
- layer_data[layer].frame_stats.AddFrame();
- }
- }
-
- // Tracks a frame skip/drop for the given layer.
- void SkipLayerFrame(size_t layer) {
- if (layer < kMaxLayers) {
- num_layers = std::max(layer + 1, num_layers);
- layer_data[layer].frame_stats.SkipFrame();
- }
- }
-
- // Sets the resolution and other details of the layer.
- void SetLayerInfo(size_t layer, int width, int height, bool is_separate) {
- if (layer < kMaxLayers) {
- num_layers = std::max(layer + 1, num_layers);
- layer_data[layer].width = width;
- layer_data[layer].height = height;
- layer_data[layer].is_separate = is_separate;
- }
- }
-
- FrameStats hwc_frame_stats;
- int64_t hwc_latency = 0;
- size_t num_layers = 0;
- LayerData layer_data[kMaxLayers];
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_SERVICES_DISPLAYD_DEBUG_HUD_DATA_H_
diff --git a/libs/vr/libvrflinger/debug_hud_view.cpp b/libs/vr/libvrflinger/debug_hud_view.cpp
deleted file mode 100644
index 4936ac6..0000000
--- a/libs/vr/libvrflinger/debug_hud_view.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-#include "debug_hud_view.h"
-
-#include <dvr/pose_client.h>
-
-#include "debug_hud_data.h"
-
-namespace android {
-namespace dvr {
-
-DebugHudView::DebugHudView(const CompositeHmd& hmd) {
- pose_client_ = dvrPoseCreate();
-
- display_size_ = hmd.GetDisplayMetrics().GetSizePixels();
- vec2 display_size_meters = hmd.GetDisplayMetrics().GetSizeMeters();
- inter_lens_dist_screen_space_ =
- 2.0f * hmd.GetHeadMountMetrics().GetInterLensDistance() /
- std::max(display_size_meters[0], display_size_meters[1]);
-}
-
-DebugHudView::~DebugHudView() {
- if (pose_client_)
- dvrPoseDestroy(pose_client_);
- pose_client_ = nullptr;
-}
-
-void DebugHudView::Update() {
- // Check for gesture that enables the debug stats HUD.
- if (!pose_client_)
- return;
- DvrPoseAsync pose;
- dvrPoseGet(pose_client_, 0, &pose);
- float32x4_t q = pose.orientation;
- quat orientation(q[3], q[0], q[1], q[2]);
- vec3 up = orientation * vec3(0, 1, 0);
- if (up[1] < -0.8f) {
- ++switch_timer_;
- } else {
- switch_timer_ = 0;
- }
- // A few seconds upside down => toggle stats HUD.
- if (switch_timer_ > 200) {
- switch_timer_ = 0;
- enabled_ = !enabled_;
- DebugHudData::data.ResetStats();
- ALOGE("Toggle debug stats HUD: %s", enabled_ ? "ON" : "OFF");
- }
-}
-
-void DebugHudView::Draw() {
- if (!enabled_)
- return;
- if (!debug_text_)
- debug_text_.reset(new DebugText(400, display_size_[0], display_size_[1]));
-
- const DebugHudData& data = DebugHudData::data;
- const size_t layer_char_count = 50;
- char layer_data[DebugHudData::kMaxLayers][layer_char_count];
- for (size_t i = 0; i < data.num_layers; ++i) {
- float fps = data.layer_data[i].frame_stats.frame_time.GetAverageFps();
- snprintf(layer_data[i], layer_char_count,
- "Layer %d %dx%d%s FPS: %.2f Drops: %d\n", static_cast<int>(i),
- data.layer_data[i].width, data.layer_data[i].height,
- data.layer_data[i].is_separate ? "x2" : "", fps,
- data.layer_data[i].frame_stats.drops);
- }
-
- float hwc_fps = data.hwc_frame_stats.frame_time.GetAverageFps();
-
- char text[400];
- float hwc_latency_ms = static_cast<float>(data.hwc_latency) / 1000000.0f;
- snprintf(text, sizeof(text), "HWC FPS: %.2f Latency: %.3f ms Skips: %d\n",
- hwc_fps, hwc_latency_ms, data.hwc_frame_stats.drops);
-
- for (size_t i = 0; i < data.num_layers; ++i) {
- strncat(text, layer_data[i], sizeof(text) - strlen(text) - 1);
- }
-
- // Ensure text termination.
- text[sizeof(text) - 1] = '\0';
-
- glViewport(0, 0, display_size_[0], display_size_[1]);
- glEnable(GL_BLEND);
- // No stereo, because you can see the HUD OK in one eye. Stereo actually
- // makes it more difficult to focus sometimes. To enable stereo:
- // replace the second to last parameter with inter_lens_dist_screen_space_.
- debug_text_->Draw(0.0f, -0.7f * inter_lens_dist_screen_space_, text, 0.0f, 1);
- glDisable(GL_BLEND);
-}
-
-} // namespace dvr
-} // namespace android
diff --git a/libs/vr/libvrflinger/debug_hud_view.h b/libs/vr/libvrflinger/debug_hud_view.h
deleted file mode 100644
index 50f38a8..0000000
--- a/libs/vr/libvrflinger/debug_hud_view.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_DEBUG_HUD_VIEW_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_DEBUG_HUD_VIEW_H_
-
-#include <stdint.h>
-
-#include <utils/Log.h>
-
-#include <private/dvr/composite_hmd.h>
-#include <private/dvr/graphics/debug_text.h>
-
-struct DvrPose;
-
-namespace android {
-namespace dvr {
-
-class CompositeHmd;
-
-// The view and the controller for the displayd debug HUD.
-// The HUD is enabled and disabled by internally tracking the head pose.
-// When the head pose is upside down for ~3 seconds, the enabled state toggles.
-// See DebugHudData for the data that is reported.
-class DebugHudView {
- public:
- DebugHudView(const CompositeHmd& hmd);
- ~DebugHudView();
-
- // Updates HUD state.
- void Update();
-
- // Draws HUD into the current framebuffer if it is currently enabled.
- void Draw();
-
- private:
- DebugHudView(const DebugHudView&) = delete;
- DebugHudView& operator=(const DebugHudView&) = delete;
-
- DvrPose* pose_client_ = nullptr;
- vec2i display_size_;
- bool enabled_ = false;
- int switch_timer_ = 0;
- float inter_lens_dist_screen_space_ = 0.0f;
- std::unique_ptr<DebugText> debug_text_;
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_SERVICES_DISPLAYD_DEBUG_HUD_VIEW_H_
diff --git a/libs/vr/libvrflinger/display_manager_service.cpp b/libs/vr/libvrflinger/display_manager_service.cpp
index 99f93bf..a0b3efe 100644
--- a/libs/vr/libvrflinger/display_manager_service.cpp
+++ b/libs/vr/libvrflinger/display_manager_service.cpp
@@ -3,32 +3,21 @@
#include <pdx/channel_handle.h>
#include <pdx/default_transport/service_endpoint.h>
#include <private/android_filesystem_config.h>
-#include <private/dvr/display_rpc.h>
+#include <private/dvr/display_protocol.h>
#include <private/dvr/trusted_uids.h>
#include <sys/poll.h>
#include <array>
+using android::dvr::display::DisplayManagerProtocol;
using android::pdx::Channel;
using android::pdx::LocalChannelHandle;
using android::pdx::Message;
using android::pdx::default_transport::Endpoint;
+using android::pdx::ErrorStatus;
using android::pdx::rpc::DispatchRemoteMethod;
using android::pdx::rpc::IfAnyOf;
-
-namespace {
-
-// As a first line of defense, the display manager endpoint is only accessible
-// to the user and group.
-
-// TODO(dnicoara): Remove read/write permission for others. This is in here just
-// to allow us to experiment with cast functionality from a plain old app.
-constexpr mode_t kDisplayManagerEndpointFileMode =
- S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
-
-constexpr size_t kMaxSurfacesPerRequest = 32;
-
-} // anonymous namespace
+using android::pdx::rpc::RemoteMethodError;
namespace android {
namespace dvr {
@@ -45,8 +34,7 @@
DisplayManagerService::DisplayManagerService(
const std::shared_ptr<DisplayService>& display_service)
: BASE("DisplayManagerService",
- Endpoint::Create(DisplayManagerRPC::kClientPath,
- kDisplayManagerEndpointFileMode)),
+ Endpoint::Create(DisplayManagerProtocol::kClientPath)),
display_service_(display_service) {
display_service_->SetDisplayConfigurationUpdateNotifier(
std::bind(&DisplayManagerService::OnDisplaySurfaceChange, this));
@@ -54,9 +42,15 @@
std::shared_ptr<pdx::Channel> DisplayManagerService::OnChannelOpen(
pdx::Message& message) {
- // Prevent more than one display manager from registering at a time.
- if (display_manager_)
- REPLY_ERROR_RETURN(message, EPERM, nullptr);
+ const int user_id = message.GetEffectiveUserId();
+ const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
+
+ // Prevent more than one display manager from registering at a time or
+ // untrusted UIDs from connecting.
+ if (display_manager_ || !trusted) {
+ RemoteMethodError(message, EPERM);
+ return nullptr;
+ }
display_manager_ =
std::make_shared<DisplayManager>(this, message.GetChannelId());
@@ -74,18 +68,18 @@
auto channel = std::static_pointer_cast<DisplayManager>(message.GetChannel());
switch (message.GetOp()) {
- case DisplayManagerRPC::GetSurfaceList::Opcode:
- DispatchRemoteMethod<DisplayManagerRPC::GetSurfaceList>(
- *this, &DisplayManagerService::OnGetSurfaceList, message);
+ case DisplayManagerProtocol::GetSurfaceState::Opcode:
+ DispatchRemoteMethod<DisplayManagerProtocol::GetSurfaceState>(
+ *this, &DisplayManagerService::OnGetSurfaceState, message);
return {};
- case DisplayManagerRPC::UpdateSurfaces::Opcode:
- DispatchRemoteMethod<DisplayManagerRPC::UpdateSurfaces>(
- *this, &DisplayManagerService::OnUpdateSurfaces, message);
+ case DisplayManagerProtocol::GetSurfaceQueue::Opcode:
+ DispatchRemoteMethod<DisplayManagerProtocol::GetSurfaceQueue>(
+ *this, &DisplayManagerService::OnGetSurfaceQueue, message);
return {};
- case DisplayManagerRPC::SetupNamedBuffer::Opcode:
- DispatchRemoteMethod<DisplayManagerRPC::SetupNamedBuffer>(
+ case DisplayManagerProtocol::SetupNamedBuffer::Opcode:
+ DispatchRemoteMethod<DisplayManagerProtocol::SetupNamedBuffer>(
*this, &DisplayManagerService::OnSetupNamedBuffer, message);
return {};
@@ -94,130 +88,67 @@
}
}
-std::vector<DisplaySurfaceInfo> DisplayManagerService::OnGetSurfaceList(
- pdx::Message& /*message*/) {
- std::vector<DisplaySurfaceInfo> items;
+pdx::Status<std::vector<display::SurfaceState>>
+DisplayManagerService::OnGetSurfaceState(pdx::Message& /*message*/) {
+ std::vector<display::SurfaceState> items;
display_service_->ForEachDisplaySurface(
+ SurfaceType::Application,
[&items](const std::shared_ptr<DisplaySurface>& surface) mutable {
- DisplaySurfaceInfo item;
-
- item.surface_id = surface->surface_id();
- item.process_id = surface->process_id();
- item.type = surface->type();
- item.flags = 0; // TODO(eieio)
- item.client_attributes = DisplaySurfaceAttributes{
- {DisplaySurfaceAttributeEnum::Visible,
- DisplaySurfaceAttributeValue{surface->client_visible()}},
- {DisplaySurfaceAttributeEnum::ZOrder,
- DisplaySurfaceAttributeValue{surface->client_z_order()}},
- {DisplaySurfaceAttributeEnum::Blur,
- DisplaySurfaceAttributeValue{0.f}}};
- item.manager_attributes = DisplaySurfaceAttributes{
- {DisplaySurfaceAttributeEnum::Visible,
- DisplaySurfaceAttributeValue{surface->manager_visible()}},
- {DisplaySurfaceAttributeEnum::ZOrder,
- DisplaySurfaceAttributeValue{surface->manager_z_order()}},
- {DisplaySurfaceAttributeEnum::Blur,
- DisplaySurfaceAttributeValue{surface->manager_blur()}}};
-
- items.push_back(item);
+ items.push_back({surface->surface_id(), surface->process_id(),
+ surface->user_id(), surface->attributes(),
+ surface->update_flags(), surface->GetQueueIds()});
+ surface->ClearUpdate();
});
// The fact that we're in the message handler implies that display_manager_ is
// not nullptr. No check required, unless this service becomes multi-threaded.
display_manager_->SetNotificationsPending(false);
-
return items;
}
-int DisplayManagerService::OnUpdateSurfaces(
- pdx::Message& /*message*/,
- const std::map<int, DisplaySurfaceAttributes>& updates) {
- for (const auto& surface_update : updates) {
- const int surface_id = surface_update.first;
- const DisplaySurfaceAttributes& attributes = surface_update.second;
+pdx::Status<pdx::LocalChannelHandle> DisplayManagerService::OnGetSurfaceQueue(
+ pdx::Message& /*message*/, int surface_id, int queue_id) {
+ auto surface = display_service_->GetDisplaySurface(surface_id);
+ if (!surface || surface->surface_type() != SurfaceType::Application)
+ return ErrorStatus(EINVAL);
- std::shared_ptr<DisplaySurface> surface =
- display_service_->GetDisplaySurface(surface_id);
+ auto queue =
+ std::static_pointer_cast<ApplicationDisplaySurface>(surface)->GetQueue(
+ queue_id);
+ if (!queue)
+ return ErrorStatus(EINVAL);
- if (!surface)
- return -ENOENT;
+ auto status = queue->CreateConsumerQueueHandle();
+ ALOGE_IF(
+ !status,
+ "DisplayManagerService::OnGetSurfaceQueue: Failed to create consumer "
+ "queue for queue_id=%d: %s",
+ queue->id(), status.GetErrorMessage().c_str());
- for (const auto& attribute : attributes) {
- const auto& key = attribute.first;
- const auto* variant = &attribute.second;
- bool invalid_value = false;
- switch (key) {
- case DisplaySurfaceAttributeEnum::ZOrder:
- invalid_value =
- !IfAnyOf<int32_t>::Call(variant, [&surface](const auto& value) {
- surface->ManagerSetZOrder(value);
- });
- break;
- case DisplaySurfaceAttributeEnum::Visible:
- invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
- variant, [&surface](const auto& value) {
- surface->ManagerSetVisible(value);
- });
- break;
- case DisplaySurfaceAttributeEnum::Blur:
- invalid_value = !IfAnyOf<int32_t, int64_t, float>::Call(
- variant, [&surface](const auto& value) {
- surface->ManagerSetBlur(value);
- });
- break;
- default:
- ALOGW(
- "DisplayManagerService::OnUpdateSurfaces: Attempt to set invalid "
- "attribute %u on surface %d",
- key, surface_id);
- break;
- }
-
- if (invalid_value) {
- ALOGW(
- "DisplayManagerService::OnUpdateSurfaces: Failed to set display "
- "surface attribute '%s' because of incompatible type: %d",
- DisplaySurfaceAttributeEnum::ToString(key).c_str(),
- variant->index());
- }
- }
- }
-
- // Reconfigure the display layers for any active surface changes.
- display_service_->UpdateActiveDisplaySurfaces();
- return 0;
+ return status;
}
pdx::Status<BorrowedNativeBufferHandle>
DisplayManagerService::OnSetupNamedBuffer(pdx::Message& message,
const std::string& name, size_t size,
- uint64_t producer_usage,
- uint64_t consumer_usage) {
- if (message.GetEffectiveUserId() != AID_ROOT &&
- !IsTrustedUid(message.GetEffectiveUserId())) {
- // Only trusted users can setup named buffers.
- ALOGE("DisplayService::SetupNamedBuffer: Called by untrusted user: uid=%d.",
- message.GetEffectiveUserId());
- return {};
+ uint64_t usage) {
+ const int user_id = message.GetEffectiveUserId();
+ const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
+
+ if (!trusted) {
+ ALOGE(
+ "DisplayService::SetupNamedBuffer: Named buffers may only be created "
+ "by trusted UIDs: user_id=%d",
+ user_id);
+ return ErrorStatus(EPERM);
}
- return display_service_->SetupNamedBuffer(name, size, producer_usage,
- consumer_usage);
+ return display_service_->SetupNamedBuffer(name, size, usage);
}
void DisplayManagerService::OnDisplaySurfaceChange() {
- if (display_manager_) {
+ if (display_manager_)
display_manager_->SetNotificationsPending(true);
- } else {
- // If there isn't a display manager registered, default all display surfaces
- // to visible.
- display_service_->ForEachDisplaySurface(
- [](const std::shared_ptr<DisplaySurface>& surface) {
- surface->ManagerSetVisible(true);
- });
- display_service_->UpdateActiveDisplaySurfaces();
- }
}
} // namespace dvr
diff --git a/libs/vr/libvrflinger/display_manager_service.h b/libs/vr/libvrflinger/display_manager_service.h
index 7b037de..0857eb5 100644
--- a/libs/vr/libvrflinger/display_manager_service.h
+++ b/libs/vr/libvrflinger/display_manager_service.h
@@ -1,8 +1,9 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_MANAGER_SERVICE_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_MANAGER_SERVICE_H_
+#ifndef ANDROID_DVR_SERVICES_VRFLINGER_DISPLAY_MANAGER_SERVICE_H_
+#define ANDROID_DVR_SERVICES_VRFLINGER_DISPLAY_MANAGER_SERVICE_H_
#include <pdx/service.h>
-#include <private/dvr/display_rpc.h>
+#include <pdx/status.h>
+#include <private/dvr/display_protocol.h>
#include "display_service.h"
@@ -50,13 +51,14 @@
explicit DisplayManagerService(
const std::shared_ptr<DisplayService>& display_service);
- std::vector<DisplaySurfaceInfo> OnGetSurfaceList(pdx::Message& message);
- int OnUpdateSurfaces(pdx::Message& message,
- const std::map<int, DisplaySurfaceAttributes>& updates);
-
+ pdx::Status<std::vector<display::SurfaceState>> OnGetSurfaceState(
+ pdx::Message& message);
+ pdx::Status<pdx::LocalChannelHandle> OnGetSurfaceQueue(pdx::Message& message,
+ int surface_id,
+ int queue_id);
pdx::Status<BorrowedNativeBufferHandle> OnSetupNamedBuffer(
pdx::Message& message, const std::string& name, size_t size,
- uint64_t producer_usage, uint64_t consumer_usage);
+ uint64_t usage);
// Called by the display service to indicate changes to display surfaces that
// the display manager should evaluate.
@@ -72,4 +74,4 @@
} // namespace dvr
} // namespace android
-#endif // ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_MANAGER_SERVICE_H_
+#endif // ANDROID_DVR_SERVICES_VRFLINGER_DISPLAY_MANAGER_SERVICE_H_
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index 097edce..47efa76 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -3,30 +3,30 @@
#include <unistd.h>
#include <vector>
+#include <dvr/dvr_display_types.h>
#include <pdx/default_transport/service_endpoint.h>
#include <pdx/rpc/remote_method.h>
-#include <private/dvr/composite_hmd.h>
-#include <private/dvr/device_metrics.h>
-#include <private/dvr/display_rpc.h>
-#include <private/dvr/display_types.h>
+#include <private/dvr/display_protocol.h>
#include <private/dvr/numeric.h>
-#include <private/dvr/polynomial_radial_distortion.h>
#include <private/dvr/types.h>
+using android::dvr::display::DisplayProtocol;
using android::pdx::Channel;
+using android::pdx::ErrorStatus;
using android::pdx::Message;
+using android::pdx::Status;
using android::pdx::default_transport::Endpoint;
using android::pdx::rpc::DispatchRemoteMethod;
-using android::pdx::rpc::WrapBuffer;
namespace android {
namespace dvr {
-DisplayService::DisplayService() : DisplayService(nullptr) {}
-
-DisplayService::DisplayService(Hwc2::Composer* hidl)
- : BASE("DisplayService", Endpoint::Create(DisplayRPC::kClientPath)),
- hardware_composer_(hidl) {
+DisplayService::DisplayService(Hwc2::Composer* hidl,
+ RequestDisplayCallback request_display_callback)
+ : BASE("DisplayService",
+ Endpoint::Create(display::DisplayProtocol::kClientPath)),
+ hardware_composer_(hidl, request_display_callback),
+ request_display_callback_(request_display_callback) {
hardware_composer_.Initialize();
}
@@ -34,68 +34,51 @@
return BASE::IsInitialized() && hardware_composer_.IsInitialized();
}
-std::string DisplayService::DumpState(size_t max_length) {
- std::vector<char> buffer(max_length);
- uint32_t max_len_p = static_cast<uint32_t>(max_length);
- hardware_composer_.Dump(buffer.data(), &max_len_p);
- return std::string(buffer.data());
+std::string DisplayService::DumpState(size_t /*max_length*/) {
+ return hardware_composer_.Dump();
}
-void DisplayService::OnChannelClose(pdx::Message& /*message*/,
+void DisplayService::OnChannelClose(pdx::Message& message,
const std::shared_ptr<Channel>& channel) {
- auto surface = std::static_pointer_cast<SurfaceChannel>(channel);
- if (surface && surface->type() == SurfaceTypeEnum::Normal) {
- auto display_surface = std::static_pointer_cast<DisplaySurface>(surface);
- display_surface->ManagerSetVisible(false);
- display_surface->ClientSetVisible(false);
- NotifyDisplayConfigurationUpdate();
+ if (auto surface = std::static_pointer_cast<DisplaySurface>(channel)) {
+ surface->OnSetAttributes(message,
+ {{display::SurfaceAttribute::Visible,
+ display::SurfaceAttributeValue{false}}});
+ SurfaceUpdated(surface->surface_type(),
+ display::SurfaceUpdateFlags::VisibilityChanged);
}
- // TODO(jwcai) Handle ChannelClose of VideoMeshSurface.
}
// First-level dispatch for display service messages. Directly handles messages
// that are independent of the display surface (metrics, creation) and routes
// surface-specific messages to the per-instance handlers.
-pdx::Status<void> DisplayService::HandleMessage(pdx::Message& message) {
- auto channel = message.GetChannel<SurfaceChannel>();
-
+Status<void> DisplayService::HandleMessage(pdx::Message& message) {
+ ALOGD_IF(TRACE, "DisplayService::HandleMessage: opcode=%d", message.GetOp());
switch (message.GetOp()) {
- case DisplayRPC::GetMetrics::Opcode:
- DispatchRemoteMethod<DisplayRPC::GetMetrics>(
+ case DisplayProtocol::GetMetrics::Opcode:
+ DispatchRemoteMethod<DisplayProtocol::GetMetrics>(
*this, &DisplayService::OnGetMetrics, message);
return {};
- case DisplayRPC::GetEdsCapture::Opcode:
- DispatchRemoteMethod<DisplayRPC::GetEdsCapture>(
- *this, &DisplayService::OnGetEdsCapture, message);
- return {};
-
- case DisplayRPC::CreateSurface::Opcode:
- DispatchRemoteMethod<DisplayRPC::CreateSurface>(
+ case DisplayProtocol::CreateSurface::Opcode:
+ DispatchRemoteMethod<DisplayProtocol::CreateSurface>(
*this, &DisplayService::OnCreateSurface, message);
return {};
- case DisplayRPC::SetViewerParams::Opcode:
- DispatchRemoteMethod<DisplayRPC::SetViewerParams>(
- *this, &DisplayService::OnSetViewerParams, message);
- return {};
-
- case DisplayRPC::GetNamedBuffer::Opcode:
- DispatchRemoteMethod<DisplayRPC::GetNamedBuffer>(
+ case DisplayProtocol::GetNamedBuffer::Opcode:
+ DispatchRemoteMethod<DisplayProtocol::GetNamedBuffer>(
*this, &DisplayService::OnGetNamedBuffer, message);
return {};
- case DisplayRPC::IsVrAppRunning::Opcode:
- DispatchRemoteMethod<DisplayRPC::IsVrAppRunning>(
+ case DisplayProtocol::IsVrAppRunning::Opcode:
+ DispatchRemoteMethod<DisplayProtocol::IsVrAppRunning>(
*this, &DisplayService::IsVrAppRunning, message);
return {};
// Direct the surface specific messages to the surface instance.
- case DisplayRPC::CreateBufferQueue::Opcode:
- case DisplayRPC::SetAttributes::Opcode:
- case DisplayRPC::GetMetadataBuffer::Opcode:
- case DisplayRPC::CreateVideoMeshSurface::Opcode:
- case DisplayRPC::VideoMeshSurfaceCreateProducerQueue::Opcode:
+ case DisplayProtocol::SetAttributes::Opcode:
+ case DisplayProtocol::CreateQueue::Opcode:
+ case DisplayProtocol::GetSurfaceInfo::Opcode:
return HandleSurfaceMessage(message);
default:
@@ -103,49 +86,29 @@
}
}
-SystemDisplayMetrics DisplayService::OnGetMetrics(pdx::Message& message) {
- const Compositor* compositor = hardware_composer_.GetCompositor();
- if (compositor == nullptr)
- REPLY_ERROR_RETURN(message, EINVAL, {});
-
- HeadMountMetrics head_mount = compositor->head_mount_metrics();
- CompositeHmd hmd(head_mount, hardware_composer_.GetHmdDisplayMetrics());
- vec2i distorted_render_size = hmd.GetRecommendedRenderTargetSize();
- FieldOfView left_fov = hmd.GetEyeFov(kLeftEye);
- FieldOfView right_fov = hmd.GetEyeFov(kRightEye);
-
- SystemDisplayMetrics metrics;
-
- metrics.display_native_width = GetDisplayMetrics().width;
- metrics.display_native_height = GetDisplayMetrics().height;
- metrics.display_x_dpi = GetDisplayMetrics().dpi.x;
- metrics.display_y_dpi = GetDisplayMetrics().dpi.y;
- metrics.distorted_width = distorted_render_size[0];
- metrics.distorted_height = distorted_render_size[1];
- metrics.vsync_period_ns =
- hardware_composer_.native_display_metrics().vsync_period_ns;
- metrics.hmd_ipd_mm = 0;
- metrics.inter_lens_distance_m = head_mount.GetInterLensDistance();
- metrics.left_fov_lrbt[0] = left_fov.GetLeft();
- metrics.left_fov_lrbt[1] = left_fov.GetRight();
- metrics.left_fov_lrbt[2] = left_fov.GetBottom();
- metrics.left_fov_lrbt[3] = left_fov.GetTop();
- metrics.right_fov_lrbt[0] = right_fov.GetLeft();
- metrics.right_fov_lrbt[1] = right_fov.GetRight();
- metrics.right_fov_lrbt[2] = right_fov.GetBottom();
- metrics.right_fov_lrbt[3] = right_fov.GetTop();
-
- return metrics;
+Status<display::Metrics> DisplayService::OnGetMetrics(
+ pdx::Message& /*message*/) {
+ return {{static_cast<uint32_t>(GetDisplayMetrics().width),
+ static_cast<uint32_t>(GetDisplayMetrics().height),
+ static_cast<uint32_t>(GetDisplayMetrics().dpi.x),
+ static_cast<uint32_t>(GetDisplayMetrics().dpi.y),
+ static_cast<uint32_t>(
+ hardware_composer_.native_display_metrics().vsync_period_ns),
+ 0,
+ 0,
+ 0,
+ 0.0,
+ {},
+ {}}};
}
// Creates a new DisplaySurface and associates it with this channel. This may
// only be done once per channel.
-int DisplayService::OnCreateSurface(pdx::Message& message, int width,
- int height, int format, int usage,
- DisplaySurfaceFlags flags) {
+Status<display::SurfaceInfo> DisplayService::OnCreateSurface(
+ pdx::Message& message, const display::SurfaceAttributes& attributes) {
// A surface may only be created once per channel.
if (message.GetChannel())
- return -EINVAL;
+ return ErrorStatus(EINVAL);
ALOGI_IF(TRACE, "DisplayService::OnCreateSurface: cid=%d",
message.GetChannelId());
@@ -153,119 +116,66 @@
// Use the channel id as the unique surface id.
const int surface_id = message.GetChannelId();
const int process_id = message.GetProcessId();
+ const int user_id = message.GetEffectiveUserId();
ALOGI_IF(TRACE,
- "DisplayService::OnCreateSurface: surface_id=%d process_id=%d "
- "width=%d height=%d format=%x usage=%x flags=%x",
- surface_id, process_id, width, height, format, usage, flags);
+ "DisplayService::OnCreateSurface: surface_id=%d process_id=%d",
+ surface_id, process_id);
- // TODO(eieio,jbates): Validate request parameters.
- auto channel = std::make_shared<DisplaySurface>(
- this, surface_id, process_id, width, height, format, usage, flags);
+ auto surface_status =
+ DisplaySurface::Create(this, surface_id, process_id, user_id, attributes);
+ if (!surface_status) {
+ ALOGE("DisplayService::OnCreateSurface: Failed to create surface: %s",
+ surface_status.GetErrorMessage().c_str());
+ return ErrorStatus(surface_status.error());
+ }
- message.SetChannel(channel);
- NotifyDisplayConfigurationUpdate();
- return 0;
+ SurfaceType surface_type = surface_status.get()->surface_type();
+ display::SurfaceUpdateFlags update_flags =
+ surface_status.get()->update_flags();
+ display::SurfaceInfo surface_info{surface_status.get()->surface_id(),
+ surface_status.get()->visible(),
+ surface_status.get()->z_order()};
+
+ message.SetChannel(surface_status.take());
+
+ SurfaceUpdated(surface_type, update_flags);
+ return {surface_info};
}
-DisplayRPC::ByteBuffer DisplayService::OnGetEdsCapture(pdx::Message& message) {
- Compositor* compositor = hardware_composer_.GetCompositor();
- if (compositor == nullptr)
- REPLY_ERROR_RETURN(message, EINVAL, {});
-
- std::vector<std::uint8_t> buffer(sizeof(LateLatchOutput));
-
- if (!compositor->GetLastEdsPose(
- reinterpret_cast<LateLatchOutput*>(buffer.data()))) {
- REPLY_ERROR_RETURN(message, EPERM, {});
+void DisplayService::SurfaceUpdated(SurfaceType surface_type,
+ display::SurfaceUpdateFlags update_flags) {
+ ALOGD_IF(TRACE, "DisplayService::SurfaceUpdated: update_flags=%x",
+ update_flags.value());
+ if (update_flags.value() != 0) {
+ if (surface_type == SurfaceType::Application)
+ NotifyDisplayConfigurationUpdate();
+ else
+ UpdateActiveDisplaySurfaces();
}
-
- return WrapBuffer(std::move(buffer));
-}
-
-void DisplayService::OnSetViewerParams(pdx::Message& message,
- const ViewerParams& view_params) {
- Compositor* compositor = hardware_composer_.GetCompositor();
- if (compositor == nullptr)
- REPLY_ERROR_RETURN(message, EINVAL);
-
- FieldOfView left(55.0f, 55.0f, 55.0f, 55.0f);
- FieldOfView right(55.0f, 55.0f, 55.0f, 55.0f);
- if (view_params.left_eye_field_of_view_angles.size() >= 4) {
- left = FieldOfView(ToRad(view_params.left_eye_field_of_view_angles[0]),
- ToRad(view_params.left_eye_field_of_view_angles[1]),
- ToRad(view_params.left_eye_field_of_view_angles[2]),
- ToRad(view_params.left_eye_field_of_view_angles[3]));
- right = FieldOfView(ToRad(view_params.left_eye_field_of_view_angles[1]),
- ToRad(view_params.left_eye_field_of_view_angles[0]),
- ToRad(view_params.left_eye_field_of_view_angles[2]),
- ToRad(view_params.left_eye_field_of_view_angles[3]));
- }
-
- std::shared_ptr<ColorChannelDistortion> red_distortion;
- std::shared_ptr<ColorChannelDistortion> green_distortion;
- std::shared_ptr<ColorChannelDistortion> blue_distortion;
-
- // We should always have a red distortion.
- LOG_FATAL_IF(view_params.distortion_coefficients_r.empty());
- red_distortion = std::make_shared<PolynomialRadialDistortion>(
- view_params.distortion_coefficients_r);
-
- if (!view_params.distortion_coefficients_g.empty()) {
- green_distortion = std::make_shared<PolynomialRadialDistortion>(
- view_params.distortion_coefficients_g);
- }
-
- if (!view_params.distortion_coefficients_b.empty()) {
- blue_distortion = std::make_shared<PolynomialRadialDistortion>(
- view_params.distortion_coefficients_b);
- }
-
- HeadMountMetrics::EyeOrientation left_orientation =
- HeadMountMetrics::EyeOrientation::kCCW0Degrees;
- HeadMountMetrics::EyeOrientation right_orientation =
- HeadMountMetrics::EyeOrientation::kCCW0Degrees;
-
- if (view_params.eye_orientations.size() > 1) {
- left_orientation = static_cast<HeadMountMetrics::EyeOrientation>(
- view_params.eye_orientations[0]);
- right_orientation = static_cast<HeadMountMetrics::EyeOrientation>(
- view_params.eye_orientations[1]);
- }
-
- HeadMountMetrics head_mount_metrics(
- view_params.inter_lens_distance, view_params.tray_to_lens_distance,
- view_params.screen_to_lens_distance,
- static_cast<HeadMountMetrics::VerticalAlignment>(
- view_params.vertical_alignment),
- left, right, red_distortion, green_distortion, blue_distortion,
- left_orientation, right_orientation,
- view_params.screen_center_to_lens_distance);
-
- compositor->UpdateHeadMountMetrics(head_mount_metrics);
}
pdx::Status<BorrowedNativeBufferHandle> DisplayService::OnGetNamedBuffer(
pdx::Message& /* message */, const std::string& name) {
+ ALOGD_IF(TRACE, "displayService::OnGetNamedBuffer: name=%s", name.c_str());
auto named_buffer = named_buffers_.find(name);
- if (named_buffer != named_buffers_.end()) {
+ if (named_buffer != named_buffers_.end())
return {BorrowedNativeBufferHandle(*named_buffer->second, 0)};
- }
-
- return pdx::ErrorStatus(EINVAL);
+ else
+ return pdx::ErrorStatus(EINVAL);
}
// Calls the message handler for the DisplaySurface associated with this
// channel.
-pdx::Status<void> DisplayService::HandleSurfaceMessage(pdx::Message& message) {
- auto surface = std::static_pointer_cast<SurfaceChannel>(message.GetChannel());
+Status<void> DisplayService::HandleSurfaceMessage(pdx::Message& message) {
+ auto surface = std::static_pointer_cast<DisplaySurface>(message.GetChannel());
ALOGW_IF(!surface,
"DisplayService::HandleSurfaceMessage: surface is nullptr!");
if (surface)
return surface->HandleMessage(message);
else
- REPLY_ERROR_RETURN(message, EINVAL, {});
+ return ErrorStatus(EINVAL);
}
std::shared_ptr<DisplaySurface> DisplayService::GetDisplaySurface(
@@ -278,14 +188,18 @@
return GetChannels<DisplaySurface>();
}
-std::vector<std::shared_ptr<DisplaySurface>>
+std::vector<std::shared_ptr<DirectDisplaySurface>>
DisplayService::GetVisibleDisplaySurfaces() const {
- std::vector<std::shared_ptr<DisplaySurface>> visible_surfaces;
+ std::vector<std::shared_ptr<DirectDisplaySurface>> visible_surfaces;
ForEachDisplaySurface(
+ SurfaceType::Direct,
[&](const std::shared_ptr<DisplaySurface>& surface) mutable {
- if (surface->IsVisible())
- visible_surfaces.push_back(surface);
+ if (surface->visible()) {
+ visible_surfaces.push_back(
+ std::static_pointer_cast<DirectDisplaySurface>(surface));
+ surface->ClearUpdate();
+ }
});
return visible_surfaces;
@@ -294,46 +208,25 @@
void DisplayService::UpdateActiveDisplaySurfaces() {
auto visible_surfaces = GetVisibleDisplaySurfaces();
- // Sort the surfaces based on manager z order first, then client z order.
std::sort(visible_surfaces.begin(), visible_surfaces.end(),
[](const std::shared_ptr<DisplaySurface>& a,
const std::shared_ptr<DisplaySurface>& b) {
- return a->manager_z_order() != b->manager_z_order()
- ? a->manager_z_order() < b->manager_z_order()
- : a->client_z_order() < b->client_z_order();
+ return a->z_order() < b->z_order();
});
ALOGD_IF(TRACE,
"DisplayService::UpdateActiveDisplaySurfaces: %zd visible surfaces",
visible_surfaces.size());
- // TODO(jbates) Have the shell manage blurred layers.
- bool blur_requested = false;
- auto end = visible_surfaces.crend();
- for (auto it = visible_surfaces.crbegin(); it != end; ++it) {
- auto surface = *it;
- // Surfaces with exclude_from_blur==true are not blurred
- // and are excluded from blur computation of other layers.
- if (surface->client_exclude_from_blur()) {
- surface->ManagerSetBlur(0.0f);
- continue;
- }
- surface->ManagerSetBlur(blur_requested ? 1.0f : 0.0f);
- if (surface->client_blur_behind())
- blur_requested = true;
- }
-
hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces));
}
pdx::Status<BorrowedNativeBufferHandle> DisplayService::SetupNamedBuffer(
- const std::string& name, size_t size, int producer_usage,
- int consumer_usage) {
+ const std::string& name, size_t size, uint64_t usage) {
auto named_buffer = named_buffers_.find(name);
if (named_buffer == named_buffers_.end()) {
- auto ion_buffer = std::make_unique<IonBuffer>(
- static_cast<int>(size), 1, HAL_PIXEL_FORMAT_BLOB,
- (producer_usage | consumer_usage));
+ auto ion_buffer = std::make_unique<IonBuffer>(static_cast<int>(size), 1,
+ HAL_PIXEL_FORMAT_BLOB, usage);
named_buffer =
named_buffers_.insert(std::make_pair(name, std::move(ion_buffer)))
.first;
@@ -356,15 +249,16 @@
update_notifier_();
}
-int DisplayService::IsVrAppRunning(pdx::Message& message) {
+Status<bool> DisplayService::IsVrAppRunning(pdx::Message& /*message*/) {
bool visible = false;
ForEachDisplaySurface(
+ SurfaceType::Application,
[&visible](const std::shared_ptr<DisplaySurface>& surface) {
- if (surface->client_z_order() == 0 && surface->IsVisible())
+ if (surface->visible())
visible = true;
});
- REPLY_SUCCESS_RETURN(message, visible, 0);
+ return {visible};
}
} // namespace dvr
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index db89064..bb4eeef 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -2,10 +2,10 @@
#define ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SERVICE_H_
#include <pdx/service.h>
+#include <pdx/status.h>
#include <private/dvr/buffer_hub_client.h>
#include <private/dvr/bufferhub_rpc.h>
-#include <private/dvr/display_rpc.h>
-#include <private/dvr/late_latch.h>
+#include <private/dvr/display_protocol.h>
#include <functional>
#include <iterator>
@@ -15,12 +15,13 @@
#include "acquired_buffer.h"
#include "display_surface.h"
+#include "epoll_event_dispatcher.h"
#include "hardware_composer.h"
namespace android {
namespace dvr {
-// DisplayService implements the displayd display service over ServiceFS.
+// DisplayService implements the display service component of VrFlinger.
class DisplayService : public pdx::ServiceBase<DisplayService> {
public:
bool IsInitialized() const override;
@@ -32,7 +33,7 @@
std::shared_ptr<DisplaySurface> GetDisplaySurface(int surface_id) const;
std::vector<std::shared_ptr<DisplaySurface>> GetDisplaySurfaces() const;
- std::vector<std::shared_ptr<DisplaySurface>> GetVisibleDisplaySurfaces()
+ std::vector<std::shared_ptr<DirectDisplaySurface>> GetVisibleDisplaySurfaces()
const;
// Updates the list of actively displayed surfaces. This must be called after
@@ -40,15 +41,15 @@
void UpdateActiveDisplaySurfaces();
pdx::Status<BorrowedNativeBufferHandle> SetupNamedBuffer(
- const std::string& name, size_t size, int producer_usage,
- int consumer_usage);
+ const std::string& name, size_t size, uint64_t usage);
template <class A>
- void ForEachDisplaySurface(A action) const {
- ForEachChannel([action](const ChannelIterator::value_type& pair) mutable {
- auto surface = std::static_pointer_cast<SurfaceChannel>(pair.second);
- if (surface->type() == SurfaceTypeEnum::Normal)
- action(std::static_pointer_cast<DisplaySurface>(surface));
+ void ForEachDisplaySurface(SurfaceType surface_type, A action) const {
+ ForEachChannel([surface_type,
+ action](const ChannelIterator::value_type& pair) mutable {
+ auto surface = std::static_pointer_cast<DisplaySurface>(pair.second);
+ if (surface->surface_type() == surface_type)
+ action(surface);
});
}
@@ -76,22 +77,30 @@
friend class VrDisplayStateService;
- DisplayService();
- DisplayService(android::Hwc2::Composer* hidl);
+ using RequestDisplayCallback = std::function<void(bool)>;
- SystemDisplayMetrics OnGetMetrics(pdx::Message& message);
- int OnCreateSurface(pdx::Message& message, int width, int height, int format,
- int usage, DisplaySurfaceFlags flags);
+ DisplayService(android::Hwc2::Composer* hidl,
+ RequestDisplayCallback request_display_callback);
- DisplayRPC::ByteBuffer OnGetEdsCapture(pdx::Message& message);
-
- void OnSetViewerParams(pdx::Message& message,
- const ViewerParams& view_params);
pdx::Status<BorrowedNativeBufferHandle> OnGetNamedBuffer(
pdx::Message& message, const std::string& name);
+ pdx::Status<display::Metrics> OnGetMetrics(pdx::Message& message);
+ pdx::Status<display::SurfaceInfo> OnCreateSurface(
+ pdx::Message& message, const display::SurfaceAttributes& attributes);
// Temporary query for current VR status. Will be removed later.
- int IsVrAppRunning(pdx::Message& message);
+ pdx::Status<bool> IsVrAppRunning(pdx::Message& message);
+
+ pdx::Status<void> AddEventHandler(int fd, int events,
+ EpollEventDispatcher::Handler handler) {
+ return dispatcher_.AddEventHandler(fd, events, handler);
+ }
+ pdx::Status<void> RemoveEventHandler(int fd) {
+ return dispatcher_.RemoveEventHandler(fd);
+ }
+
+ void SurfaceUpdated(SurfaceType surface_type,
+ display::SurfaceUpdateFlags update_flags);
// Called by DisplaySurface to signal that a surface property has changed and
// the display manager should be notified.
@@ -99,13 +108,15 @@
pdx::Status<void> HandleSurfaceMessage(pdx::Message& message);
- DisplayService(const DisplayService&) = delete;
- void operator=(const DisplayService&) = delete;
-
HardwareComposer hardware_composer_;
+ RequestDisplayCallback request_display_callback_;
+ EpollEventDispatcher dispatcher_;
DisplayConfigurationUpdateNotifier update_notifier_;
std::unordered_map<std::string, std::unique_ptr<IonBuffer>> named_buffers_;
+
+ DisplayService(const DisplayService&) = delete;
+ void operator=(const DisplayService&) = delete;
};
} // namespace dvr
diff --git a/libs/vr/libvrflinger/display_surface.cpp b/libs/vr/libvrflinger/display_surface.cpp
index a7220fe..5829788 100644
--- a/libs/vr/libvrflinger/display_surface.cpp
+++ b/libs/vr/libvrflinger/display_surface.cpp
@@ -1,16 +1,21 @@
#include "display_surface.h"
+#include <private/android_filesystem_config.h>
#include <utils/Trace.h>
#include <private/dvr/platform_defines.h>
+#include <private/dvr/trusted_uids.h>
#include "display_service.h"
#include "hardware_composer.h"
#define LOCAL_TRACE 1
+using android::dvr::display::DisplayProtocol;
using android::pdx::BorrowedChannelHandle;
+using android::pdx::ErrorStatus;
using android::pdx::LocalChannelHandle;
+using android::pdx::LocalHandle;
using android::pdx::Message;
using android::pdx::RemoteChannelHandle;
using android::pdx::Status;
@@ -20,104 +25,320 @@
namespace android {
namespace dvr {
-DisplaySurface::DisplaySurface(DisplayService* service, int surface_id,
- int process_id, int width, int height,
- int format, int usage, int flags)
- : SurfaceChannel(service, surface_id, SurfaceTypeEnum::Normal,
- sizeof(DisplaySurfaceMetadata)),
+DisplaySurface::DisplaySurface(DisplayService* service,
+ SurfaceType surface_type, int surface_id,
+ int process_id, int user_id,
+ const display::SurfaceAttributes& attributes)
+ : service_(service),
+ surface_type_(surface_type),
+ surface_id_(surface_id),
process_id_(process_id),
- acquired_buffers_(kMaxPostedBuffers),
- video_mesh_surfaces_updated_(false),
- width_(width),
- height_(height),
- format_(format),
- usage_(usage),
- flags_(flags),
- client_visible_(false),
- client_z_order_(0),
- client_exclude_from_blur_(false),
- client_blur_behind_(false),
- manager_visible_(false),
- manager_z_order_(0),
- manager_blur_(0.0f),
- layer_order_(0),
- allocated_buffer_index_(0) {}
+ user_id_(user_id),
+ attributes_(attributes),
+ update_flags_(display::SurfaceUpdateFlags::NewSurface) {}
DisplaySurface::~DisplaySurface() {
ALOGD_IF(LOCAL_TRACE,
"DisplaySurface::~DisplaySurface: surface_id=%d process_id=%d",
- surface_id(), process_id_);
+ surface_id(), process_id());
}
-void DisplaySurface::ManagerSetVisible(bool visible) {
+Status<void> DisplaySurface::HandleMessage(pdx::Message& message) {
+ switch (message.GetOp()) {
+ case DisplayProtocol::SetAttributes::Opcode:
+ DispatchRemoteMethod<DisplayProtocol::SetAttributes>(
+ *this, &DisplaySurface::OnSetAttributes, message);
+ break;
+
+ case DisplayProtocol::GetSurfaceInfo::Opcode:
+ DispatchRemoteMethod<DisplayProtocol::GetSurfaceInfo>(
+ *this, &DisplaySurface::OnGetSurfaceInfo, message);
+ break;
+
+ case DisplayProtocol::CreateQueue::Opcode:
+ DispatchRemoteMethod<DisplayProtocol::CreateQueue>(
+ *this, &DisplaySurface::OnCreateQueue, message);
+ break;
+ }
+
+ return {};
+}
+
+Status<void> DisplaySurface::OnSetAttributes(
+ pdx::Message& /*message*/, const display::SurfaceAttributes& attributes) {
+ display::SurfaceUpdateFlags update_flags;
+
+ for (const auto& attribute : attributes) {
+ const auto& key = attribute.first;
+ const auto* variant = &attribute.second;
+ bool invalid_value = false;
+ bool visibility_changed = false;
+
+ // Catch attributes that have significance to the display service.
+ switch (key) {
+ case display::SurfaceAttribute::ZOrder:
+ invalid_value = !IfAnyOf<int32_t, int64_t, float>::Call(
+ variant, [&](const auto& value) {
+ if (z_order_ != value) {
+ visibility_changed = true;
+ z_order_ = value;
+ }
+ });
+ break;
+ case display::SurfaceAttribute::Visible:
+ invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
+ variant, [&](const auto& value) {
+ if (visible_ != value) {
+ visibility_changed = true;
+ visible_ = value;
+ }
+ });
+ break;
+ }
+
+ if (invalid_value) {
+ ALOGW(
+ "DisplaySurface::OnClientSetAttributes: Failed to set display "
+ "surface attribute '%d' because of incompatible type: %d",
+ key, variant->index());
+ } else {
+ // Only update the attribute map with valid values.
+ attributes_[attribute.first] = attribute.second;
+
+ // All attribute changes generate a notification, even if the value
+ // doesn't change. Visibility attributes set a flag only if the value
+ // changes.
+ update_flags.Set(display::SurfaceUpdateFlags::AttributesChanged);
+ if (visibility_changed)
+ update_flags.Set(display::SurfaceUpdateFlags::VisibilityChanged);
+ }
+ }
+
+ SurfaceUpdated(update_flags);
+ return {};
+}
+
+void DisplaySurface::SurfaceUpdated(display::SurfaceUpdateFlags update_flags) {
+ ALOGD_IF(TRACE,
+ "DisplaySurface::SurfaceUpdated: surface_id=%d update_flags=0x%x",
+ surface_id(), update_flags.value());
+
+ update_flags_.Set(update_flags);
+ service()->SurfaceUpdated(surface_type(), update_flags_);
+}
+
+void DisplaySurface::ClearUpdate() {
+ ALOGD_IF(TRACE, "DisplaySurface::ClearUpdate: surface_id=%d", surface_id());
+ update_flags_ = display::SurfaceUpdateFlags::None;
+}
+
+Status<display::SurfaceInfo> DisplaySurface::OnGetSurfaceInfo(
+ Message& /*message*/) {
+ ALOGD_IF(
+ TRACE,
+ "DisplaySurface::OnGetSurfaceInfo: surface_id=%d visible=%d z_order=%d",
+ surface_id(), visible(), z_order());
+ return {{surface_id(), visible(), z_order()}};
+}
+
+Status<void> DisplaySurface::RegisterQueue(
+ const std::shared_ptr<ConsumerQueue>& consumer_queue) {
+ ALOGD_IF(TRACE, "DisplaySurface::RegisterQueue: surface_id=%d queue_id=%d",
+ surface_id(), consumer_queue->id());
+ // Capture references for the lambda to work around apparent clang bug.
+ // TODO(eieio): Figure out if there is a clang bug or C++11 ambiguity when
+ // capturing self and consumer_queue by copy in the following case:
+ // auto self = Self();
+ // [self, consumer_queue](int events) {
+ // self->OnQueueEvent(consuemr_queue, events); }
+ //
+ struct State {
+ std::shared_ptr<DisplaySurface> surface;
+ std::shared_ptr<ConsumerQueue> queue;
+ };
+ State state{Self(), consumer_queue};
+
+ return service()->AddEventHandler(
+ consumer_queue->queue_fd(), EPOLLIN | EPOLLHUP | EPOLLET,
+ [state](int events) {
+ state.surface->OnQueueEvent(state.queue, events);
+ });
+}
+
+Status<void> DisplaySurface::UnregisterQueue(
+ const std::shared_ptr<ConsumerQueue>& consumer_queue) {
+ ALOGD_IF(TRACE, "DisplaySurface::UnregisterQueue: surface_id=%d queue_id=%d",
+ surface_id(), consumer_queue->id());
+ return service()->RemoveEventHandler(consumer_queue->queue_fd());
+}
+
+void DisplaySurface::OnQueueEvent(
+ const std::shared_ptr<ConsumerQueue>& /*consumer_queue*/, int /*events*/) {
+ ALOGE(
+ "DisplaySurface::OnQueueEvent: ERROR base virtual method should not be "
+ "called!!!");
+}
+
+std::shared_ptr<ConsumerQueue> ApplicationDisplaySurface::GetQueue(
+ int32_t queue_id) {
+ ALOGD_IF(TRACE,
+ "ApplicationDisplaySurface::GetQueue: surface_id=%d queue_id=%d",
+ surface_id(), queue_id);
+
+ auto search = consumer_queues_.find(queue_id);
+ if (search != consumer_queues_.end())
+ return search->second;
+ else
+ return nullptr;
+}
+
+std::vector<int32_t> ApplicationDisplaySurface::GetQueueIds() const {
+ std::vector<int32_t> queue_ids;
+ for (const auto& entry : consumer_queues_)
+ queue_ids.push_back(entry.first);
+ return queue_ids;
+}
+
+Status<LocalChannelHandle> ApplicationDisplaySurface::OnCreateQueue(
+ Message& /*message*/, size_t meta_size_bytes) {
+ ATRACE_NAME("ApplicationDisplaySurface::OnCreateQueue");
+ ALOGD_IF(TRACE,
+ "ApplicationDisplaySurface::OnCreateQueue: surface_id=%d, "
+ "meta_size_bytes=%zu",
+ surface_id(), meta_size_bytes);
+
std::lock_guard<std::mutex> autolock(lock_);
- manager_visible_ = visible;
-}
-
-void DisplaySurface::ManagerSetZOrder(int z_order) {
- std::lock_guard<std::mutex> autolock(lock_);
- manager_z_order_ = z_order;
-}
-
-void DisplaySurface::ManagerSetBlur(float blur) {
- std::lock_guard<std::mutex> autolock(lock_);
- manager_blur_ = blur;
-}
-
-void DisplaySurface::ClientSetVisible(bool visible) {
- std::lock_guard<std::mutex> autolock(lock_);
- client_visible_ = visible;
-}
-
-void DisplaySurface::ClientSetZOrder(int z_order) {
- std::lock_guard<std::mutex> autolock(lock_);
- client_z_order_ = z_order;
-}
-
-void DisplaySurface::ClientSetExcludeFromBlur(bool exclude_from_blur) {
- std::lock_guard<std::mutex> autolock(lock_);
- client_exclude_from_blur_ = exclude_from_blur;
-}
-
-void DisplaySurface::ClientSetBlurBehind(bool blur_behind) {
- std::lock_guard<std::mutex> autolock(lock_);
- client_blur_behind_ = blur_behind;
-}
-
-void DisplaySurface::DequeueBuffersLocked() {
- if (consumer_queue_ == nullptr) {
+ auto producer = ProducerQueue::Create(meta_size_bytes);
+ if (!producer) {
ALOGE(
- "DisplaySurface::DequeueBuffersLocked: Consumer queue is not "
+ "ApplicationDisplaySurface::OnCreateQueue: Failed to create producer "
+ "queue!");
+ return ErrorStatus(ENOMEM);
+ }
+
+ std::shared_ptr<ConsumerQueue> consumer =
+ producer->CreateSilentConsumerQueue();
+ auto status = RegisterQueue(consumer);
+ if (!status) {
+ ALOGE(
+ "ApplicationDisplaySurface::OnCreateQueue: Failed to register consumer "
+ "queue: %s",
+ status.GetErrorMessage().c_str());
+ return status.error_status();
+ }
+
+ consumer_queues_[consumer->id()] = std::move(consumer);
+
+ SurfaceUpdated(display::SurfaceUpdateFlags::BuffersChanged);
+ return std::move(producer->GetChannelHandle());
+}
+
+void ApplicationDisplaySurface::OnQueueEvent(
+ const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) {
+ ALOGD_IF(TRACE,
+ "ApplicationDisplaySurface::OnQueueEvent: queue_id=%d events=%x",
+ consumer_queue->id(), events);
+
+ // Always give the queue a chance to handle its internal bookkeeping.
+ consumer_queue->HandleQueueEvents();
+
+ // Check for hangup and remove a queue that is no longer needed.
+ std::lock_guard<std::mutex> autolock(lock_);
+ if (consumer_queue->hung_up()) {
+ ALOGD_IF(TRACE, "ApplicationDisplaySurface::OnQueueEvent: Removing queue.");
+ UnregisterQueue(consumer_queue);
+ auto search = consumer_queues_.find(consumer_queue->id());
+ if (search != consumer_queues_.end()) {
+ consumer_queues_.erase(search);
+ } else {
+ ALOGE(
+ "ApplicationDisplaySurface::OnQueueEvent: Failed to find queue_id=%d",
+ consumer_queue->id());
+ }
+ SurfaceUpdated(display::SurfaceUpdateFlags::BuffersChanged);
+ }
+}
+
+Status<LocalChannelHandle> DirectDisplaySurface::OnCreateQueue(
+ Message& /*message*/, size_t meta_size_bytes) {
+ ATRACE_NAME("DirectDisplaySurface::OnCreateQueue");
+ ALOGD_IF(
+ TRACE,
+ "DirectDisplaySurface::OnCreateQueue: surface_id=%d meta_size_bytes=%zu",
+ surface_id(), meta_size_bytes);
+
+ std::lock_guard<std::mutex> autolock(lock_);
+ if (!direct_queue_) {
+ auto producer = ProducerQueue::Create(meta_size_bytes);
+ if (!producer) {
+ ALOGE(
+ "DirectDisplaySurface::OnCreateQueue: Failed to create producer "
+ "queue!");
+ return ErrorStatus(ENOMEM);
+ }
+
+ direct_queue_ = producer->CreateConsumerQueue();
+ auto status = RegisterQueue(direct_queue_);
+ if (!status) {
+ ALOGE(
+ "DirectDisplaySurface::OnCreateQueue: Failed to register consumer "
+ "queue: %s",
+ status.GetErrorMessage().c_str());
+ return status.error_status();
+ }
+
+ return std::move(producer->GetChannelHandle());
+ } else {
+ return ErrorStatus(EALREADY);
+ }
+}
+
+void DirectDisplaySurface::OnQueueEvent(
+ const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) {
+ ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: queue_id=%d events=%x",
+ consumer_queue->id(), events);
+
+ // Always give the queue a chance to handle its internal bookkeeping.
+ consumer_queue->HandleQueueEvents();
+
+ // Check for hangup and remove a queue that is no longer needed.
+ std::lock_guard<std::mutex> autolock(lock_);
+ if (consumer_queue->hung_up()) {
+ ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: Removing queue.");
+ UnregisterQueue(consumer_queue);
+ direct_queue_ = nullptr;
+ }
+}
+
+void DirectDisplaySurface::DequeueBuffersLocked() {
+ if (direct_queue_ == nullptr) {
+ ALOGE(
+ "DirectDisplaySurface::DequeueBuffersLocked: Consumer queue is not "
"initialized.");
return;
}
- size_t slot;
- uint64_t sequence;
while (true) {
LocalHandle acquire_fence;
- auto buffer_consumer =
- consumer_queue_->Dequeue(0, &slot, &sequence, &acquire_fence);
- if (!buffer_consumer) {
- ALOGD_IF(TRACE,
- "DisplaySurface::DequeueBuffersLocked: We have dequeued all "
- "available buffers.");
+ size_t slot;
+ auto buffer_status = direct_queue_->Dequeue(0, &slot, &acquire_fence);
+ if (!buffer_status) {
+ ALOGD_IF(
+ TRACE && buffer_status.error() == ETIMEDOUT,
+ "DirectDisplaySurface::DequeueBuffersLocked: All buffers dequeued.");
+ ALOGE_IF(buffer_status.error() != ETIMEDOUT,
+ "DirectDisplaySurface::DequeueBuffersLocked: Failed to dequeue "
+ "buffer: %s",
+ buffer_status.GetErrorMessage().c_str());
return;
}
+ auto buffer_consumer = buffer_status.take();
- // Save buffer index, associated with the buffer id so that it can be looked
- // up later.
- int buffer_id = buffer_consumer->id();
- if (buffer_id_to_index_.find(buffer_id) == buffer_id_to_index_.end()) {
- buffer_id_to_index_[buffer_id] = allocated_buffer_index_;
- ++allocated_buffer_index_;
- }
-
- if (!IsVisible()) {
+ if (!visible()) {
ATRACE_NAME("DropFrameOnInvisibleSurface");
ALOGD_IF(TRACE,
- "DisplaySurface::DequeueBuffersLocked: Discarding buffer_id=%d "
- "on invisible surface.",
+ "DirectDisplaySurface::DequeueBuffersLocked: Discarding "
+ "buffer_id=%d on invisible surface.",
buffer_consumer->id());
buffer_consumer->Discard();
continue;
@@ -125,34 +346,34 @@
if (acquired_buffers_.IsFull()) {
ALOGE(
- "DisplaySurface::DequeueBuffersLocked: Posted buffers full, "
+ "DirectDisplaySurface::DequeueBuffersLocked: Posted buffers full, "
"overwriting.");
acquired_buffers_.PopBack();
}
acquired_buffers_.Append(
- AcquiredBuffer(buffer_consumer, std::move(acquire_fence), sequence));
+ AcquiredBuffer(buffer_consumer, std::move(acquire_fence)));
}
}
-AcquiredBuffer DisplaySurface::AcquireCurrentBuffer() {
+AcquiredBuffer DirectDisplaySurface::AcquireCurrentBuffer() {
std::lock_guard<std::mutex> autolock(lock_);
DequeueBuffersLocked();
if (acquired_buffers_.IsEmpty()) {
ALOGE(
- "DisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer when "
- "none are posted.");
+ "DirectDisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer "
+ "when none are posted.");
return AcquiredBuffer();
}
AcquiredBuffer buffer = std::move(acquired_buffers_.Front());
acquired_buffers_.PopFront();
- ALOGD_IF(TRACE, "DisplaySurface::AcquireCurrentBuffer: buffer: %p",
+ ALOGD_IF(TRACE, "DirectDisplaySurface::AcquireCurrentBuffer: buffer: %p",
buffer.buffer().get());
return buffer;
}
-AcquiredBuffer DisplaySurface::AcquireNewestAvailableBuffer(
+AcquiredBuffer DirectDisplaySurface::AcquireNewestAvailableBuffer(
AcquiredBuffer* skipped_buffer) {
std::lock_guard<std::mutex> autolock(lock_);
DequeueBuffersLocked();
@@ -175,23 +396,13 @@
if (frames == 2)
break;
}
- ALOGD_IF(TRACE, "DisplaySurface::AcquireNewestAvailableBuffer: buffer: %p",
+ ALOGD_IF(TRACE,
+ "DirectDisplaySurface::AcquireNewestAvailableBuffer: buffer: %p",
buffer.buffer().get());
return buffer;
}
-uint32_t DisplaySurface::GetRenderBufferIndex(int buffer_id) {
- std::lock_guard<std::mutex> autolock(lock_);
-
- if (buffer_id_to_index_.find(buffer_id) == buffer_id_to_index_.end()) {
- ALOGW("DisplaySurface::GetRenderBufferIndex: unknown buffer_id %d.",
- buffer_id);
- return 0;
- }
- return buffer_id_to_index_[buffer_id];
-}
-
-bool DisplaySurface::IsBufferAvailable() {
+bool DirectDisplaySurface::IsBufferAvailable() {
std::lock_guard<std::mutex> autolock(lock_);
DequeueBuffersLocked();
@@ -199,158 +410,48 @@
acquired_buffers_.Front().IsAvailable();
}
-bool DisplaySurface::IsBufferPosted() {
+bool DirectDisplaySurface::IsBufferPosted() {
std::lock_guard<std::mutex> autolock(lock_);
DequeueBuffersLocked();
return !acquired_buffers_.IsEmpty();
}
-pdx::Status<void> DisplaySurface::HandleMessage(pdx::Message& message) {
- switch (message.GetOp()) {
- case DisplayRPC::SetAttributes::Opcode:
- DispatchRemoteMethod<DisplayRPC::SetAttributes>(
- *this, &DisplaySurface::OnClientSetAttributes, message);
- break;
-
- case DisplayRPC::CreateBufferQueue::Opcode:
- DispatchRemoteMethod<DisplayRPC::CreateBufferQueue>(
- *this, &DisplaySurface::OnCreateBufferQueue, message);
- break;
-
- case DisplayRPC::CreateVideoMeshSurface::Opcode:
- DispatchRemoteMethod<DisplayRPC::CreateVideoMeshSurface>(
- *this, &DisplaySurface::OnCreateVideoMeshSurface, message);
- break;
-
- default:
- return SurfaceChannel::HandleMessage(message);
- }
-
- return {};
-}
-
-int DisplaySurface::OnClientSetAttributes(
- pdx::Message& /*message*/, const DisplaySurfaceAttributes& attributes) {
- for (const auto& attribute : attributes) {
- const auto& key = attribute.first;
- const auto* variant = &attribute.second;
- bool invalid_value = false;
- switch (key) {
- case DisplaySurfaceAttributeEnum::ZOrder:
- invalid_value = !IfAnyOf<int32_t, int64_t, float>::Call(
- variant, [this](const auto& value) {
- DisplaySurface::ClientSetZOrder(value);
- });
- break;
- case DisplaySurfaceAttributeEnum::Visible:
- invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
- variant, [this](const auto& value) {
- DisplaySurface::ClientSetVisible(value);
- });
- break;
- case DisplaySurfaceAttributeEnum::ExcludeFromBlur:
- invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
- variant, [this](const auto& value) {
- DisplaySurface::ClientSetExcludeFromBlur(value);
- });
- break;
- case DisplaySurfaceAttributeEnum::BlurBehind:
- invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call(
- variant, [this](const auto& value) {
- DisplaySurface::ClientSetBlurBehind(value);
- });
- break;
- default:
- ALOGW(
- "DisplaySurface::OnClientSetAttributes: Unrecognized attribute %d "
- "surface_id=%d",
- key, surface_id());
- break;
- }
-
- if (invalid_value) {
- ALOGW(
- "DisplaySurface::OnClientSetAttributes: Failed to set display "
- "surface attribute '%s' because of incompatible type: %d",
- DisplaySurfaceAttributeEnum::ToString(key).c_str(), variant->index());
+Status<std::shared_ptr<DisplaySurface>> DisplaySurface::Create(
+ DisplayService* service, int surface_id, int process_id, int user_id,
+ const display::SurfaceAttributes& attributes) {
+ bool direct = false;
+ auto search = attributes.find(display::SurfaceAttribute::Direct);
+ if (search != attributes.end()) {
+ if (!IfAnyOf<int32_t, int64_t, bool, float>::Get(&search->second,
+ &direct)) {
+ ALOGE(
+ "DisplaySurface::Create: Invalid type for SurfaceAttribute::Direct!");
+ return ErrorStatus(EINVAL);
}
}
- service()->NotifyDisplayConfigurationUpdate();
- return 0;
-}
+ ALOGD_IF(TRACE,
+ "DisplaySurface::Create: surface_id=%d process_id=%d user_id=%d "
+ "direct=%d",
+ surface_id, process_id, user_id, direct);
-LocalChannelHandle DisplaySurface::OnCreateBufferQueue(Message& message) {
- ATRACE_NAME("DisplaySurface::OnCreateBufferQueue");
-
- if (consumer_queue_ != nullptr) {
- ALOGE(
- "DisplaySurface::OnCreateBufferQueue: A ProdcuerQueue has already been "
- "created and transported to DisplayClient.");
- REPLY_ERROR_RETURN(message, EALREADY, {});
- }
-
- auto producer = ProducerQueue::Create<uint64_t>();
- consumer_queue_ = producer->CreateConsumerQueue();
-
- return std::move(producer->GetChannelHandle());
-}
-
-RemoteChannelHandle DisplaySurface::OnCreateVideoMeshSurface(
- pdx::Message& message) {
- if (flags_ & DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION) {
- ALOGE(
- "DisplaySurface::OnCreateVideoMeshSurface: system distortion is "
- "disabled on this display surface, cannot create VideoMeshSurface on "
- "top of it.");
- REPLY_ERROR_RETURN(message, EINVAL, {});
- }
-
- int channel_id;
- auto status = message.PushChannel(0, nullptr, &channel_id);
- if (!status) {
- ALOGE(
- "DisplaySurface::OnCreateVideoMeshSurface: failed to push channel: %s",
- status.GetErrorMessage().c_str());
- REPLY_ERROR_RETURN(message, status.error(), {});
- }
-
- auto surface = std::make_shared<VideoMeshSurface>(service(), channel_id);
- auto channel_status = service()->SetChannel(channel_id, surface);
- if (!channel_status) {
- ALOGE(
- "DisplaySurface::OnCreateVideoMeshSurface: failed to set new video "
- "mesh surface channel: %s",
- channel_status.GetErrorMessage().c_str());
- REPLY_ERROR_RETURN(message, channel_status.error(), {});
- }
-
- {
- std::lock_guard<std::mutex> autolock(lock_);
- pending_video_mesh_surfaces_.push_back(surface);
- video_mesh_surfaces_updated_ = true;
- }
-
- return status.take();
-}
-
-std::vector<std::shared_ptr<VideoMeshSurface>>
-DisplaySurface::GetVideoMeshSurfaces() {
- std::lock_guard<std::mutex> autolock(lock_);
- std::vector<std::shared_ptr<VideoMeshSurface>> surfaces;
-
- for (auto& surface : pending_video_mesh_surfaces_) {
- if (auto video_surface = surface.lock()) {
- surfaces.push_back(video_surface);
+ if (direct) {
+ const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
+ if (trusted) {
+ return {std::shared_ptr<DisplaySurface>{new DirectDisplaySurface(
+ service, surface_id, process_id, user_id, attributes)}};
} else {
- ALOGE("Unable to lock video mesh surface.");
+ ALOGE(
+ "DisplaySurface::Create: Direct surfaces may only be created by "
+ "trusted UIDs: user_id=%d",
+ user_id);
+ return ErrorStatus(EPERM);
}
+ } else {
+ return {std::shared_ptr<DisplaySurface>{new ApplicationDisplaySurface(
+ service, surface_id, process_id, user_id, attributes)}};
}
-
- pending_video_mesh_surfaces_.clear();
- video_mesh_surfaces_updated_ = false;
- return surfaces;
}
} // namespace dvr
diff --git a/libs/vr/libvrflinger/display_surface.h b/libs/vr/libvrflinger/display_surface.h
index 2e4cf75..47a07f0 100644
--- a/libs/vr/libvrflinger/display_surface.h
+++ b/libs/vr/libvrflinger/display_surface.h
@@ -3,7 +3,9 @@
#include <pdx/file_handle.h>
#include <pdx/service.h>
-#include <private/dvr/display_rpc.h>
+#include <private/dvr/buffer_hub_queue_client.h>
+#include <private/dvr/display_protocol.h>
+#include <private/dvr/graphics_private.h>
#include <private/dvr/ring_buffer.h>
#include <functional>
@@ -13,54 +15,136 @@
#include <vector>
#include "acquired_buffer.h"
-#include "surface_channel.h"
-#include "video_mesh_surface.h"
namespace android {
namespace dvr {
class DisplayService;
-// DisplaySurface is the service-side notion of a client display context. It is
-// responsible for managing display buffer format, geometry, and state, and
-// maintains the buffer consumers connected to the client.
-class DisplaySurface : public SurfaceChannel {
+enum class SurfaceType {
+ Direct,
+ Application,
+};
+
+class DisplaySurface : public pdx::Channel {
public:
- DisplaySurface(DisplayService* service, int surface_id, int process_id,
- int width, int height, int format, int usage, int flags);
+ static pdx::Status<std::shared_ptr<DisplaySurface>> Create(
+ DisplayService* service, int surface_id, int process_id, int user_id,
+ const display::SurfaceAttributes& attributes);
+
~DisplaySurface() override;
+ DisplayService* service() const { return service_; }
+ SurfaceType surface_type() const { return surface_type_; }
+ int surface_id() const { return surface_id_; }
int process_id() const { return process_id_; }
- int width() const { return width_; }
- int height() const { return height_; }
- int format() const { return format_; }
- int usage() const { return usage_; }
- int flags() const { return flags_; }
+ int user_id() const { return user_id_; }
- bool client_visible() const { return client_visible_; }
- int client_z_order() const { return client_z_order_; }
- bool client_exclude_from_blur() const { return client_exclude_from_blur_; }
- bool client_blur_behind() const { return client_blur_behind_; }
+ bool visible() const { return visible_; }
+ int z_order() const { return z_order_; }
- bool manager_visible() const { return manager_visible_; }
- int manager_z_order() const { return manager_z_order_; }
- float manager_blur() const { return manager_blur_; }
+ const display::SurfaceAttributes& attributes() const { return attributes_; }
+ display::SurfaceUpdateFlags update_flags() const { return update_flags_; }
- bool video_mesh_surfaces_updated() const {
- return video_mesh_surfaces_updated_;
+ virtual std::vector<int32_t> GetQueueIds() const { return {}; }
+
+ bool IsUpdatePending() const {
+ return update_flags_.value() != display::SurfaceUpdateFlags::None;
}
- volatile const DisplaySurfaceMetadata* GetMetadataBufferPtr() {
- if (EnsureMetadataBuffer()) {
- void* addr = nullptr;
- metadata_buffer_->GetBlobReadWritePointer(metadata_size(), &addr);
- return static_cast<const volatile DisplaySurfaceMetadata*>(addr);
- } else {
- return nullptr;
- }
+ protected:
+ DisplaySurface(DisplayService* service, SurfaceType surface_type,
+ int surface_id, int process_id, int user_id,
+ const display::SurfaceAttributes& attributes);
+
+ // Utility to retrieve a shared pointer to this channel as the desired derived
+ // type.
+ template <
+ typename T = DisplaySurface,
+ typename = std::enable_if_t<std::is_base_of<DisplaySurface, T>::value>>
+ std::shared_ptr<T> Self() {
+ return std::static_pointer_cast<T>(shared_from_this());
}
- uint32_t GetRenderBufferIndex(int buffer_id);
+ virtual pdx::Status<pdx::LocalChannelHandle> OnCreateQueue(
+ pdx::Message& message, size_t meta_size_bytes) = 0;
+
+ // Registers a consumer queue with the event dispatcher in DisplayService. The
+ // OnQueueEvent callback below is called to handle queue events.
+ pdx::Status<void> RegisterQueue(
+ const std::shared_ptr<ConsumerQueue>& consumer_queue);
+ pdx::Status<void> UnregisterQueue(
+ const std::shared_ptr<ConsumerQueue>& consumer_queue);
+
+ // Called by the event dispatcher in DisplayService when a registered queue
+ // event triggers. Executes on the event dispatcher thread.
+ virtual void OnQueueEvent(
+ const std::shared_ptr<ConsumerQueue>& consumer_queue, int events);
+
+ void SurfaceUpdated(display::SurfaceUpdateFlags update_flags);
+ void ClearUpdate();
+
+ // Synchronizes access to mutable state below between message dispatch thread
+ // and frame post thread.
+ mutable std::mutex lock_;
+
+ private:
+ friend class DisplayService;
+ friend class DisplayManagerService;
+
+ // Dispatches display surface messages to the appropriate handlers. This
+ // handler runs on the VrFlinger message dispatch thread.
+ pdx::Status<void> HandleMessage(pdx::Message& message);
+
+ pdx::Status<void> OnSetAttributes(
+ pdx::Message& message, const display::SurfaceAttributes& attributes);
+ pdx::Status<display::SurfaceInfo> OnGetSurfaceInfo(pdx::Message& message);
+
+ DisplayService* service_;
+ SurfaceType surface_type_;
+ int surface_id_;
+ int process_id_;
+ int user_id_;
+
+ display::SurfaceAttributes attributes_;
+ display::SurfaceUpdateFlags update_flags_ = display::SurfaceUpdateFlags::None;
+
+ // Subset of attributes that may be interpreted by the display service.
+ bool visible_ = false;
+ int z_order_ = 0;
+
+ DisplaySurface(const DisplaySurface&) = delete;
+ void operator=(const DisplaySurface&) = delete;
+};
+
+class ApplicationDisplaySurface : public DisplaySurface {
+ public:
+ ApplicationDisplaySurface(DisplayService* service, int surface_id,
+ int process_id, int user_id,
+ const display::SurfaceAttributes& attributes)
+ : DisplaySurface(service, SurfaceType::Application, surface_id,
+ process_id, user_id, attributes) {}
+
+ std::shared_ptr<ConsumerQueue> GetQueue(int32_t queue_id);
+ std::vector<int32_t> GetQueueIds() const override;
+
+ private:
+ pdx::Status<pdx::LocalChannelHandle> OnCreateQueue(
+ pdx::Message& message, size_t meta_size_bytes) override;
+ void OnQueueEvent(const std::shared_ptr<ConsumerQueue>& consumer_queue,
+ int events) override;
+
+ std::unordered_map<int32_t, std::shared_ptr<ConsumerQueue>> consumer_queues_;
+};
+
+class DirectDisplaySurface : public DisplaySurface {
+ public:
+ DirectDisplaySurface(DisplayService* service, int surface_id, int process_id,
+ int user_id,
+ const display::SurfaceAttributes& attributes)
+ : DisplaySurface(service, SurfaceType::Direct, surface_id, process_id,
+ user_id, attributes),
+ acquired_buffers_(kMaxPostedBuffers) {}
bool IsBufferAvailable();
bool IsBufferPosted();
AcquiredBuffer AcquireCurrentBuffer();
@@ -69,31 +153,11 @@
// skipped, it will be stored in skipped_buffer if non null.
AcquiredBuffer AcquireNewestAvailableBuffer(AcquiredBuffer* skipped_buffer);
- // Display manager interface to control visibility and z order.
- void ManagerSetVisible(bool visible);
- void ManagerSetZOrder(int z_order);
- void ManagerSetBlur(float blur);
-
- // A surface must be set visible by both the client and the display manager to
- // be visible on screen.
- bool IsVisible() const { return client_visible_ && manager_visible_; }
-
- // A surface is blurred if the display manager requests it.
- bool IsBlurred() const { return manager_blur_ > 0.0f; }
-
- // Set by HardwareComposer to the current logical layer order of this surface.
- void SetLayerOrder(int layer_order) { layer_order_ = layer_order; }
- // Gets the unique z-order index of this surface among other visible surfaces.
- // This is not the same as the hardware layer index, as not all display
- // surfaces map directly to hardware layers. Lower layer orders should be
- // composited underneath higher layer orders.
- int layer_order() const { return layer_order_; }
-
- // Lock all video mesh surfaces so that VideoMeshCompositor can access them.
- std::vector<std::shared_ptr<VideoMeshSurface>> GetVideoMeshSurfaces();
-
private:
- friend class DisplayService;
+ pdx::Status<pdx::LocalChannelHandle> OnCreateQueue(
+ pdx::Message& message, size_t meta_size_bytes) override;
+ void OnQueueEvent(const std::shared_ptr<ConsumerQueue>& consumer_queue,
+ int events) override;
// The capacity of the pending buffer queue. Should be enough to hold all the
// buffers of this DisplaySurface, although in practice only 1 or 2 frames
@@ -104,75 +168,14 @@
// Returns whether a frame is available without locking the mutex.
bool IsFrameAvailableNoLock() const;
- // Dispatches display surface messages to the appropriate handlers. This
- // handler runs on the displayd message dispatch thread.
- pdx::Status<void> HandleMessage(pdx::Message& message) override;
-
- // Sets display surface's client-controlled attributes.
- int OnClientSetAttributes(pdx::Message& message,
- const DisplaySurfaceAttributes& attributes);
-
- // Creates a BufferHubQueue associated with this surface and returns the PDX
- // handle of its producer side to the client.
- pdx::LocalChannelHandle OnCreateBufferQueue(pdx::Message& message);
-
- // Creates a video mesh surface associated with this surface and returns its
- // PDX handle to the client.
- pdx::RemoteChannelHandle OnCreateVideoMeshSurface(pdx::Message& message);
-
- // Client interface (called through IPC) to set visibility and z order.
- void ClientSetVisible(bool visible);
- void ClientSetZOrder(int z_order);
- void ClientSetExcludeFromBlur(bool exclude_from_blur);
- void ClientSetBlurBehind(bool blur_behind);
-
// Dequeue all available buffers from the consumer queue.
void DequeueBuffersLocked();
- DisplaySurface(const DisplaySurface&) = delete;
- void operator=(const DisplaySurface&) = delete;
-
- int process_id_;
-
- // Synchronizes access to mutable state below between message dispatch thread,
- // epoll event thread, and frame post thread.
- mutable std::mutex lock_;
-
- // The consumer end of a BufferHubQueue. VrFlinger allocates and controls the
- // buffer queue and pass producer end to the app and the consumer end to
- // compositor.
- // TODO(jwcai) Add support for multiple buffer queues per display surface.
- std::shared_ptr<ConsumerQueue> consumer_queue_;
-
// In a triple-buffered surface, up to kMaxPostedBuffers buffers may be
// posted and pending.
RingBuffer<AcquiredBuffer> acquired_buffers_;
- // Provides access to VideoMeshSurface. Here we don't want to increase
- // the reference count immediately on allocation, will leave it into
- // compositor's hand.
- std::vector<std::weak_ptr<VideoMeshSurface>> pending_video_mesh_surfaces_;
- volatile bool video_mesh_surfaces_updated_;
-
- // Surface parameters.
- int width_;
- int height_;
- int format_;
- int usage_;
- int flags_;
- bool client_visible_;
- int client_z_order_;
- bool client_exclude_from_blur_;
- bool client_blur_behind_;
- bool manager_visible_;
- int manager_z_order_;
- float manager_blur_;
- int layer_order_;
-
- // The monotonically increasing index for allocated buffers in this surface.
- uint32_t allocated_buffer_index_;
- // Maps from the buffer id to the corresponding allocated buffer index.
- std::unordered_map<int, uint32_t> buffer_id_to_index_;
+ std::shared_ptr<ConsumerQueue> direct_queue_;
};
} // namespace dvr
diff --git a/libs/vr/libvrflinger/epoll_event_dispatcher.cpp b/libs/vr/libvrflinger/epoll_event_dispatcher.cpp
new file mode 100644
index 0000000..06b69bb
--- /dev/null
+++ b/libs/vr/libvrflinger/epoll_event_dispatcher.cpp
@@ -0,0 +1,142 @@
+#include "epoll_event_dispatcher.h"
+
+#include <log/log.h>
+#include <sys/epoll.h>
+#include <sys/eventfd.h>
+#include <sys/prctl.h>
+
+#include <dvr/performance_client_api.h>
+
+namespace android {
+namespace dvr {
+
+EpollEventDispatcher::EpollEventDispatcher() {
+ epoll_fd_.Reset(epoll_create(64));
+ if (!epoll_fd_) {
+ ALOGE("Failed to create epoll fd: %s", strerror(errno));
+ return;
+ }
+
+ event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
+ if (!event_fd_) {
+ ALOGE("Failed to create event for epolling: %s", strerror(errno));
+ return;
+ }
+
+ // Add watch for eventfd. This should only watch for EPOLLIN, which gets set
+ // when eventfd_write occurs. Use "this" as a unique sentinal value to
+ // identify events from the event fd.
+ epoll_event event = {.events = EPOLLIN, .data = {.ptr = this}};
+ if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, event_fd_.Get(), &event) < 0) {
+ ALOGE("Failed to add eventfd to epoll set because: %s", strerror(errno));
+ return;
+ }
+
+ thread_ = std::thread(&EpollEventDispatcher::EventThread, this);
+}
+
+EpollEventDispatcher::~EpollEventDispatcher() { Stop(); }
+
+void EpollEventDispatcher::Stop() {
+ exit_thread_.store(true);
+ eventfd_write(event_fd_.Get(), 1);
+}
+
+pdx::Status<void> EpollEventDispatcher::AddEventHandler(int fd, int event_mask,
+ Handler handler) {
+ std::lock_guard<std::mutex> lock(lock_);
+
+ epoll_event event;
+ event.events = event_mask;
+ event.data.ptr = &(handlers_[fd] = handler);
+
+ ALOGD_IF(
+ TRACE,
+ "EpollEventDispatcher::AddEventHandler: fd=%d event_mask=0x%x handler=%p",
+ fd, event_mask, event.data.ptr);
+
+ if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, fd, &event) < 0) {
+ const int error = errno;
+ ALOGE("Failed to add fd to epoll set because: %s", strerror(error));
+ return pdx::ErrorStatus(error);
+ } else {
+ return {};
+ }
+}
+
+pdx::Status<void> EpollEventDispatcher::RemoveEventHandler(int fd) {
+ ALOGD_IF(TRACE, "EpollEventDispatcher::RemoveEventHandler: fd=%d", fd);
+ std::lock_guard<std::mutex> lock(lock_);
+
+ epoll_event dummy; // See BUGS in man 2 epoll_ctl.
+ if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, fd, &dummy) < 0) {
+ const int error = errno;
+ ALOGE("Failed to remove fd from epoll set because: %s", strerror(error));
+ return pdx::ErrorStatus(error);
+ }
+
+ // If the fd was valid above, add it to the list of ids to remove.
+ removed_handlers_.push_back(fd);
+
+ // Wake up the event thread to clean up.
+ eventfd_write(event_fd_.Get(), 1);
+
+ return {};
+}
+
+void EpollEventDispatcher::EventThread() {
+ prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrEvent"), 0, 0, 0);
+
+ const int error = dvrSetSchedulerClass(0, "graphics");
+ LOG_ALWAYS_FATAL_IF(
+ error < 0,
+ "EpollEventDispatcher::EventThread: Failed to set scheduler class: %s",
+ strerror(-error));
+
+ const size_t kMaxNumEvents = 128;
+ epoll_event events[kMaxNumEvents];
+
+ while (!exit_thread_.load()) {
+ const int num_events = epoll_wait(epoll_fd_.Get(), events, kMaxNumEvents, -1);
+ if (num_events < 0 && errno != EINTR)
+ break;
+
+ ALOGD_IF(TRACE, "EpollEventDispatcher::EventThread: num_events=%d",
+ num_events);
+
+ for (int i = 0; i < num_events; i++) {
+ ALOGD_IF(
+ TRACE,
+ "EpollEventDispatcher::EventThread: event %d: handler=%p events=0x%x",
+ i, events[i].data.ptr, events[i].events);
+
+ if (events[i].data.ptr == this) {
+ // Clear pending event on event_fd_. Serialize the read with respect to
+ // writes from other threads.
+ std::lock_guard<std::mutex> lock(lock_);
+ eventfd_t value;
+ eventfd_read(event_fd_.Get(), &value);
+ } else {
+ auto handler = reinterpret_cast<Handler*>(events[i].data.ptr);
+ if (handler)
+ (*handler)(events[i].events);
+ }
+ }
+
+ // Remove any handlers that have been posted for removal. This is done here
+ // instead of in RemoveEventHandler() to prevent races between the dispatch
+ // thread and the code requesting the removal. Handlers are guaranteed to
+ // stay alive between exiting epoll_wait() and the dispatch loop above.
+ std::lock_guard<std::mutex> lock(lock_);
+ for (auto handler_fd : removed_handlers_) {
+ ALOGD_IF(TRACE,
+ "EpollEventDispatcher::EventThread: removing handler: fd=%d",
+ handler_fd);
+ handlers_.erase(handler_fd);
+ }
+ removed_handlers_.clear();
+ }
+}
+
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libvrflinger/epoll_event_dispatcher.h b/libs/vr/libvrflinger/epoll_event_dispatcher.h
new file mode 100644
index 0000000..eb687f4
--- /dev/null
+++ b/libs/vr/libvrflinger/epoll_event_dispatcher.h
@@ -0,0 +1,63 @@
+#ifndef ANDROID_DVR_SERVICES_DISPLAYD_EPOLL_EVENT_DISPATCHER_H_
+#define ANDROID_DVR_SERVICES_DISPLAYD_EPOLL_EVENT_DISPATCHER_H_
+
+#include <sys/epoll.h>
+
+#include <atomic>
+#include <functional>
+#include <mutex>
+#include <thread>
+#include <unordered_map>
+#include <vector>
+
+#include <pdx/file_handle.h>
+#include <pdx/status.h>
+
+namespace android {
+namespace dvr {
+
+class EpollEventDispatcher {
+ public:
+ // Function type for event handlers. The handler receives a bitmask of the
+ // epoll events that occurred on the file descriptor associated with the
+ // handler.
+ using Handler = std::function<void(int)>;
+
+ EpollEventDispatcher();
+ ~EpollEventDispatcher();
+
+ // |handler| is called on the internal dispatch thread when |fd| is signaled
+ // by events in |event_mask|.
+ pdx::Status<void> AddEventHandler(int fd, int event_mask, Handler handler);
+ pdx::Status<void> RemoveEventHandler(int fd);
+
+ void Stop();
+
+ private:
+ void EventThread();
+
+ std::thread thread_;
+ std::atomic<bool> exit_thread_{false};
+
+ // Protects handlers_ and removed_handlers_ and serializes operations on
+ // epoll_fd_ and event_fd_.
+ std::mutex lock_;
+
+ // Maintains a map of fds to event handlers. This is primarily to keep any
+ // references alive that may be bound in the std::function instances. It is
+ // not used at dispatch time to avoid performance problems with different
+ // versions of std::unordered_map.
+ std::unordered_map<int, Handler> handlers_;
+
+ // List of fds to be removed from the map. The actual removal is performed
+ // by the event dispatch thread to avoid races.
+ std::vector<int> removed_handlers_;
+
+ pdx::LocalHandle epoll_fd_;
+ pdx::LocalHandle event_fd_;
+};
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_SERVICES_DISPLAYD_EPOLL_EVENT_DISPATCHER_H_
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index bac9872..079d6fd 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -1,9 +1,9 @@
#include "hardware_composer.h"
-#include <log/log.h>
#include <cutils/properties.h>
#include <cutils/sched_policy.h>
#include <fcntl.h>
+#include <log/log.h>
#include <poll.h>
#include <sync/sync.h>
#include <sys/eventfd.h>
@@ -11,23 +11,27 @@
#include <sys/resource.h>
#include <sys/system_properties.h>
#include <sys/timerfd.h>
+#include <time.h>
#include <unistd.h>
#include <utils/Trace.h>
#include <algorithm>
+#include <chrono>
#include <functional>
#include <map>
+#include <dvr/dvr_display_types.h>
#include <dvr/performance_client_api.h>
#include <private/dvr/clock_ns.h>
-#include <private/dvr/display_types.h>
+#include <private/dvr/ion_buffer.h>
#include <private/dvr/pose_client_internal.h>
#include <private/dvr/sync_util.h>
-#include "debug_hud_data.h"
-#include "screenshot_service.h"
-
using android::pdx::LocalHandle;
+using android::pdx::rpc::EmptyVariant;
+using android::pdx::rpc::IfAnyOf;
+
+using namespace std::chrono_literals;
namespace android {
namespace dvr {
@@ -42,13 +46,8 @@
// display and the EDS timing coincides with zero pending fences, so this is 0.
constexpr int kAllowedPendingFenceCount = 0;
-// If we think we're going to miss vsync by more than this amount, skip the
-// frame.
-constexpr int64_t kFrameSkipThresholdNs = 4000000; // 4ms
-
-// Counter PostLayers() deficiency by requiring apps to produce a frame at least
-// 2.5ms before vsync. See b/28881672.
-constexpr int64_t kFrameTimeEstimateMin = 2500000; // 2.5ms
+// Offset before vsync to submit frames to hardware composer.
+constexpr int64_t kFramePostOffsetNs = 4000000; // 4ms
constexpr size_t kDefaultDisplayConfigCount = 32;
@@ -93,44 +92,52 @@
return (vsync_period_ns * 150) / 100;
}
+// Attempts to set the scheduler class and partiton for the current thread.
+// Returns true on success or false on failure.
+bool SetThreadPolicy(const std::string& scheduler_class,
+ const std::string& partition) {
+ int error = dvrSetSchedulerClass(0, scheduler_class.c_str());
+ if (error < 0) {
+ ALOGE(
+ "SetThreadPolicy: Failed to set scheduler class \"%s\" for "
+ "thread_id=%d: %s",
+ scheduler_class.c_str(), gettid(), strerror(-error));
+ return false;
+ }
+ error = dvrSetCpuPartition(0, partition.c_str());
+ if (error < 0) {
+ ALOGE(
+ "SetThreadPolicy: Failed to set cpu partiton \"%s\" for thread_id=%d: "
+ "%s",
+ partition.c_str(), gettid(), strerror(-error));
+ return false;
+ }
+ return true;
+}
+
} // anonymous namespace
-HardwareComposer::HardwareComposer()
- : HardwareComposer(nullptr) {
-}
+// Layer static data.
+Hwc2::Composer* Layer::hwc2_hidl_;
+const HWCDisplayMetrics* Layer::display_metrics_;
-HardwareComposer::HardwareComposer(Hwc2::Composer* hwc2_hidl)
+// HardwareComposer static data;
+constexpr size_t HardwareComposer::kMaxHardwareLayers;
+
+HardwareComposer::HardwareComposer()
+ : HardwareComposer(nullptr, RequestDisplayCallback()) {}
+
+HardwareComposer::HardwareComposer(
+ Hwc2::Composer* hwc2_hidl, RequestDisplayCallback request_display_callback)
: initialized_(false),
hwc2_hidl_(hwc2_hidl),
- display_transform_(HWC_TRANSFORM_NONE),
- active_surfaces_updated_(false),
- active_layer_count_(0),
- gpu_layer_(nullptr),
- post_thread_enabled_(false),
- post_thread_running_(false),
- post_thread_quit_requested_(false),
- post_thread_interrupt_event_fd_(-1),
- backlight_brightness_fd_(-1),
- primary_display_vsync_event_fd_(-1),
- primary_display_wait_pp_fd_(-1),
- vsync_sleep_timer_fd_(-1),
- last_vsync_timestamp_(0),
- vsync_count_(0),
- frame_skip_count_(0),
- pose_client_(nullptr) {
- std::transform(layer_storage_.begin(), layer_storage_.end(), layers_.begin(),
- [](auto& layer) { return &layer; });
-
- callbacks_ = new ComposerCallback;
-}
+ request_display_callback_(request_display_callback),
+ callbacks_(new ComposerCallback) {}
HardwareComposer::~HardwareComposer(void) {
- std::unique_lock<std::mutex> lock(post_thread_mutex_);
- if (post_thread_.joinable()) {
- post_thread_quit_requested_ = true;
- post_thread_cond_var_.notify_all();
+ UpdatePostThreadState(PostThreadState::Quit, true);
+ if (post_thread_.joinable())
post_thread_.join();
- }
}
bool HardwareComposer::Initialize() {
@@ -139,25 +146,25 @@
return false;
}
- int32_t ret = HWC2_ERROR_NONE;
+ HWC::Error error = HWC::Error::None;
Hwc2::Config config;
- ret = (int32_t)hwc2_hidl_->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
+ error = hwc2_hidl_->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
- if (ret != HWC2_ERROR_NONE) {
+ if (error != HWC::Error::None) {
ALOGE("HardwareComposer: Failed to get current display config : %d",
config);
return false;
}
- ret =
+ error =
GetDisplayMetrics(HWC_DISPLAY_PRIMARY, config, &native_display_metrics_);
- if (ret != HWC2_ERROR_NONE) {
+ if (error != HWC::Error::None) {
ALOGE(
"HardwareComposer: Failed to get display attributes for current "
"configuration : %d",
- ret);
+ error.value);
return false;
}
@@ -173,10 +180,12 @@
display_transform_ = HWC_TRANSFORM_NONE;
display_metrics_ = native_display_metrics_;
- post_thread_interrupt_event_fd_.Reset(
- eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
+ // Pass hwc instance and metrics to setup globals for Layer.
+ Layer::InitializeGlobals(hwc2_hidl_, &native_display_metrics_);
+
+ post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
LOG_ALWAYS_FATAL_IF(
- !post_thread_interrupt_event_fd_,
+ !post_thread_event_fd_,
"HardwareComposer: Failed to create interrupt event fd : %s",
strerror(errno));
@@ -188,38 +197,47 @@
}
void HardwareComposer::Enable() {
- std::lock_guard<std::mutex> lock(post_thread_mutex_);
- post_thread_enabled_ = true;
- post_thread_cond_var_.notify_all();
+ UpdatePostThreadState(PostThreadState::Suspended, false);
}
void HardwareComposer::Disable() {
- std::unique_lock<std::mutex> lock(post_thread_mutex_);
- post_thread_enabled_ = false;
- if (post_thread_running_) {
- // Write to the interrupt fd to get fast interrupt of the post thread
- int error = eventfd_write(post_thread_interrupt_event_fd_.Get(), 1);
- ALOGW_IF(error,
- "HardwareComposer::Disable: could not write post "
- "thread interrupt event fd : %s",
- strerror(errno));
-
- post_thread_cond_var_.wait(lock, [this] { return !post_thread_running_; });
-
- // Read the interrupt fd to clear its state
- uint64_t interrupt_count= 0;
- error = eventfd_read(post_thread_interrupt_event_fd_.Get(),
- &interrupt_count);
- ALOGW_IF(error,
- "HardwareComposer::Disable: could not read post "
- "thread interrupt event fd : %s",
- strerror(errno));
- }
+ UpdatePostThreadState(PostThreadState::Suspended, true);
}
-bool HardwareComposer::PostThreadHasWork() {
- return !display_surfaces_.empty() ||
- (active_surfaces_updated_ && !active_surfaces_.empty());
+// Update the post thread quiescent state based on idle and suspended inputs.
+void HardwareComposer::UpdatePostThreadState(PostThreadStateType state,
+ bool suspend) {
+ std::unique_lock<std::mutex> lock(post_thread_mutex_);
+
+ // Update the votes in the state variable before evaluating the effective
+ // quiescent state. Any bits set in post_thread_state_ indicate that the post
+ // thread should be suspended.
+ if (suspend) {
+ post_thread_state_ |= state;
+ } else {
+ post_thread_state_ &= ~state;
+ }
+
+ const bool quit = post_thread_state_ & PostThreadState::Quit;
+ const bool effective_suspend = post_thread_state_ != PostThreadState::Active;
+ if (quit) {
+ post_thread_quiescent_ = true;
+ eventfd_write(post_thread_event_fd_.Get(), 1);
+ post_thread_wait_.notify_one();
+ } else if (effective_suspend && !post_thread_quiescent_) {
+ post_thread_quiescent_ = true;
+ eventfd_write(post_thread_event_fd_.Get(), 1);
+ } else if (!effective_suspend && post_thread_quiescent_) {
+ post_thread_quiescent_ = false;
+ eventfd_t value;
+ eventfd_read(post_thread_event_fd_.Get(), &value);
+ post_thread_wait_.notify_one();
+ }
+
+ // Wait until the post thread is in the requested state.
+ post_thread_ready_.wait(lock, [this, effective_suspend] {
+ return effective_suspend != post_thread_resumed_;
+ });
}
void HardwareComposer::OnPostThreadResumed() {
@@ -233,16 +251,17 @@
hwc2_hidl_->resetCommands();
- // Associate each Layer instance with a hardware composer layer.
- for (auto layer : layers_) {
- layer->Initialize(hwc2_hidl_.get(), &native_display_metrics_);
- }
-
// Connect to pose service.
pose_client_ = dvrPoseCreate();
ALOGE_IF(!pose_client_, "HardwareComposer: Failed to create pose client");
+ // HIDL HWC seems to have an internal race condition. If we submit a frame too
+ // soon after turning on VSync we don't get any VSync signals. Give poor HWC
+ // implementations a chance to enable VSync before we continue.
+ EnableVsync(false);
+ std::this_thread::sleep_for(100ms);
EnableVsync(true);
+ std::this_thread::sleep_for(100ms);
// TODO(skiazyk): We need to do something about accessing this directly,
// supposedly there is a backlight service on the way.
@@ -251,33 +270,19 @@
// control of the display back to surface flinger?
SetBacklightBrightness(255);
- // Initialize the GPU compositor.
- LOG_ALWAYS_FATAL_IF(!compositor_.Initialize(GetHmdDisplayMetrics()),
- "Failed to initialize the compositor");
-
// Trigger target-specific performance mode change.
property_set(kDvrPerformanceProperty, "performance");
}
void HardwareComposer::OnPostThreadPaused() {
- retire_fence_fds_.clear();
- gpu_layer_ = nullptr;
-
- // We have to destroy the layers to fully clear hwc device state before
- // handing off back to surface flinger
- for (size_t i = 0; i < kMaxHardwareLayers; ++i) {
- layers_[i]->Reset();
- }
-
- active_layer_count_ = 0;
-
framebuffer_target_.reset();
-
+ retire_fence_fds_.clear();
display_surfaces_.clear();
- compositor_surfaces_.clear();
- // Since we're clearing display_surfaces_ we'll need an update.
- active_surfaces_updated_ = true;
+ for (size_t i = 0; i < kMaxHardwareLayers; ++i) {
+ layers_[i].Reset();
+ }
+ active_layer_count_ = 0;
if (pose_client_) {
dvrPoseDestroy(pose_client_);
@@ -286,50 +291,24 @@
EnableVsync(false);
- frame_time_history_.ResetWithSeed(GuessFrameTime(0));
- frame_time_backlog_.clear();
-
- compositor_.Shutdown();
-
hwc2_hidl_->resetCommands();
// Trigger target-specific performance mode change.
property_set(kDvrPerformanceProperty, "idle");
}
-DisplayMetrics HardwareComposer::GetHmdDisplayMetrics() const {
- vec2i screen_size(display_metrics_.width, display_metrics_.height);
- DisplayOrientation orientation =
- (display_metrics_.width > display_metrics_.height
- ? DisplayOrientation::kLandscape
- : DisplayOrientation::kPortrait);
- float dpi_x = static_cast<float>(display_metrics_.dpi.x) / 1000.0f;
- float dpi_y = static_cast<float>(display_metrics_.dpi.y) / 1000.0f;
- float meters_per_pixel_x = kMetersPerInch / dpi_x;
- float meters_per_pixel_y = kMetersPerInch / dpi_y;
- vec2 meters_per_pixel(meters_per_pixel_x, meters_per_pixel_y);
- double frame_duration_s =
- static_cast<double>(display_metrics_.vsync_period_ns) / 1000000000.0;
- // TODO(hendrikw): Hard coding to 3mm. The Pixel is actually 4mm, but it
- // seems that their tray to lens distance is wrong too, which
- // offsets this, at least for the pixel.
- float border_size = 0.003f;
- return DisplayMetrics(screen_size, meters_per_pixel, border_size,
- static_cast<float>(frame_duration_s), orientation);
-}
-
-int32_t HardwareComposer::Validate(hwc2_display_t display) {
+HWC::Error HardwareComposer::Validate(hwc2_display_t display) {
uint32_t num_types;
uint32_t num_requests;
- int32_t error =
- (int32_t)hwc2_hidl_->validateDisplay(display, &num_types, &num_requests);
+ HWC::Error error =
+ hwc2_hidl_->validateDisplay(display, &num_types, &num_requests);
if (error == HWC2_ERROR_HAS_CHANGES) {
// TODO(skiazyk): We might need to inspect the requested changes first, but
// so far it seems like we shouldn't ever hit a bad state.
// error = hwc2_funcs_.accept_display_changes_fn_(hardware_composer_device_,
// display);
- error = (int32_t)hwc2_hidl_->acceptDisplayChanges(display);
+ error = hwc2_hidl_->acceptDisplayChanges(display);
}
return error;
@@ -342,13 +321,13 @@
: HWC2_VSYNC_DISABLE));
}
-int32_t HardwareComposer::Present(hwc2_display_t display) {
+HWC::Error HardwareComposer::Present(hwc2_display_t display) {
int32_t present_fence;
- int32_t error = (int32_t)hwc2_hidl_->presentDisplay(display, &present_fence);
+ HWC::Error error = hwc2_hidl_->presentDisplay(display, &present_fence);
// According to the documentation, this fence is signaled at the time of
// vsync/DMA for physical displays.
- if (error == HWC2_ERROR_NONE) {
+ if (error == HWC::Error::None) {
ATRACE_INT("HardwareComposer: VsyncFence", present_fence);
retire_fence_fds_.emplace_back(present_fence);
} else {
@@ -358,82 +337,81 @@
return error;
}
-int32_t HardwareComposer::GetDisplayAttribute(hwc2_display_t display,
- hwc2_config_t config,
- hwc2_attribute_t attribute,
- int32_t* out_value) const {
- return (int32_t)hwc2_hidl_->getDisplayAttribute(
+HWC::Error HardwareComposer::GetDisplayAttribute(hwc2_display_t display,
+ hwc2_config_t config,
+ hwc2_attribute_t attribute,
+ int32_t* out_value) const {
+ return hwc2_hidl_->getDisplayAttribute(
display, config, (Hwc2::IComposerClient::Attribute)attribute, out_value);
}
-int32_t HardwareComposer::GetDisplayMetrics(
+HWC::Error HardwareComposer::GetDisplayMetrics(
hwc2_display_t display, hwc2_config_t config,
HWCDisplayMetrics* out_metrics) const {
- int32_t ret = HWC2_ERROR_NONE;
+ HWC::Error error;
- ret = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_WIDTH,
- &out_metrics->width);
- if (ret != HWC2_ERROR_NONE) {
- ALOGE("HardwareComposer: Failed to get display width");
- return ret;
+ error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_WIDTH,
+ &out_metrics->width);
+ if (error != HWC::Error::None) {
+ ALOGE(
+ "HardwareComposer::GetDisplayMetrics: Failed to get display width: %s",
+ error.to_string().c_str());
+ return error;
}
- ret = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_HEIGHT,
- &out_metrics->height);
- if (ret != HWC2_ERROR_NONE) {
- ALOGE("HardwareComposer: Failed to get display height");
- return ret;
+ error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_HEIGHT,
+ &out_metrics->height);
+ if (error != HWC::Error::None) {
+ ALOGE(
+ "HardwareComposer::GetDisplayMetrics: Failed to get display height: %s",
+ error.to_string().c_str());
+ return error;
}
- ret = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_VSYNC_PERIOD,
- &out_metrics->vsync_period_ns);
- if (ret != HWC2_ERROR_NONE) {
- ALOGE("HardwareComposer: Failed to get display height");
- return ret;
+ error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_VSYNC_PERIOD,
+ &out_metrics->vsync_period_ns);
+ if (error != HWC::Error::None) {
+ ALOGE(
+ "HardwareComposer::GetDisplayMetrics: Failed to get display height: %s",
+ error.to_string().c_str());
+ return error;
}
- ret = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_X,
- &out_metrics->dpi.x);
- if (ret != HWC2_ERROR_NONE) {
- ALOGE("HardwareComposer: Failed to get display DPI X");
- return ret;
+ error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_X,
+ &out_metrics->dpi.x);
+ if (error != HWC::Error::None) {
+ ALOGE(
+ "HardwareComposer::GetDisplayMetrics: Failed to get display DPI X: %s",
+ error.to_string().c_str());
+ return error;
}
- ret = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_Y,
- &out_metrics->dpi.y);
- if (ret != HWC2_ERROR_NONE) {
- ALOGE("HardwareComposer: Failed to get display DPI Y");
- return ret;
+ error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_Y,
+ &out_metrics->dpi.y);
+ if (error != HWC::Error::None) {
+ ALOGE(
+ "HardwareComposer::GetDisplayMetrics: Failed to get display DPI Y: %s",
+ error.to_string().c_str());
+ return error;
}
- return HWC2_ERROR_NONE;
+ return HWC::Error::None;
}
-void HardwareComposer::Dump(char* buffer, uint32_t* out_size) {
- std::string debug_str = hwc2_hidl_->dumpDebugInfo();
- ALOGI("%s", debug_str.c_str());
+std::string HardwareComposer::Dump() { return hwc2_hidl_->dumpDebugInfo(); }
- if (buffer == nullptr) {
- *out_size = debug_str.size();
- } else {
- std::copy(debug_str.begin(), debug_str.begin() + *out_size, buffer);
- }
-}
-
-// TODO(skiazyk): Figure out what to do with `is_geometry_changed`. There does
-// not seem to be any equivalent in the HWC2 API, but that doesn't mean its not
-// there.
-void HardwareComposer::PostLayers(bool /*is_geometry_changed*/) {
+void HardwareComposer::PostLayers() {
ATRACE_NAME("HardwareComposer::PostLayers");
// Setup the hardware composer layers with current buffers.
for (size_t i = 0; i < active_layer_count_; i++) {
- layers_[i]->Prepare();
+ layers_[i].Prepare();
}
- int32_t ret = Validate(HWC_DISPLAY_PRIMARY);
- if (ret) {
- ALOGE("HardwareComposer::Validate failed; ret=%d", ret);
+ HWC::Error error = Validate(HWC_DISPLAY_PRIMARY);
+ if (error != HWC::Error::None) {
+ ALOGE("HardwareComposer::PostLayers: Validate failed: %s",
+ error.to_string().c_str());
return;
}
@@ -462,7 +440,7 @@
retire_fence_fds_.size());
for (size_t i = 0; i < active_layer_count_; i++) {
- layers_[i]->Drop();
+ layers_[i].Drop();
}
return;
} else {
@@ -473,55 +451,71 @@
#if TRACE
for (size_t i = 0; i < active_layer_count_; i++)
- ALOGI("HardwareComposer::PostLayers: dl[%zu] ctype=0x%08x", i,
- layers_[i]->GetCompositionType());
+ ALOGI("HardwareComposer::PostLayers: layer=%zu composition=%s", i,
+ layers_[i].GetCompositionType().to_string().c_str());
#endif
- ret = Present(HWC_DISPLAY_PRIMARY);
- if (ret) {
- ALOGE("HardwareComposer::Present failed; ret=%d", ret);
+ error = Present(HWC_DISPLAY_PRIMARY);
+ if (error != HWC::Error::None) {
+ ALOGE("HardwareComposer::PostLayers: Present failed: %s",
+ error.to_string().c_str());
return;
}
std::vector<Hwc2::Layer> out_layers;
std::vector<int> out_fences;
- ret = (int32_t)hwc2_hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
- &out_fences);
- uint32_t num_elements = out_layers.size();
-
- ALOGE_IF(ret, "HardwareComposer: GetReleaseFences failed; ret=%d", ret);
+ error = hwc2_hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
+ &out_fences);
+ ALOGE_IF(error != HWC::Error::None,
+ "HardwareComposer::PostLayers: Failed to get release fences: %s",
+ error.to_string().c_str());
// Perform post-frame bookkeeping. Unused layers are a no-op.
+ uint32_t num_elements = out_layers.size();
for (size_t i = 0; i < num_elements; ++i) {
for (size_t j = 0; j < active_layer_count_; ++j) {
- if (layers_[j]->GetLayerHandle() == out_layers[i]) {
- layers_[j]->Finish(out_fences[i]);
+ if (layers_[j].GetLayerHandle() == out_layers[i]) {
+ layers_[j].Finish(out_fences[i]);
}
}
}
}
void HardwareComposer::SetDisplaySurfaces(
- std::vector<std::shared_ptr<DisplaySurface>> surfaces) {
+ std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces) {
ALOGI("HardwareComposer::SetDisplaySurfaces: surface count=%zd",
surfaces.size());
- std::unique_lock<std::mutex> lock(post_thread_mutex_);
- active_surfaces_ = std::move(surfaces);
- active_surfaces_updated_ = true;
- if (post_thread_enabled_)
- post_thread_cond_var_.notify_all();
+ const bool display_idle = surfaces.size() == 0;
+ {
+ std::unique_lock<std::mutex> lock(post_thread_mutex_);
+ pending_surfaces_ = std::move(surfaces);
+ }
+
+ // Set idle state based on whether there are any surfaces to handle.
+ UpdatePostThreadState(PostThreadState::Idle, display_idle);
+
+ // XXX: TEMPORARY
+ // Request control of the display based on whether there are any surfaces to
+ // handle. This callback sets the post thread active state once the transition
+ // is complete in SurfaceFlinger.
+ // TODO(eieio): Unify the control signal used to move SurfaceFlinger into VR
+ // mode. Currently this is hooked up to persistent VR mode, but perhaps this
+ // makes more sense to control it from VrCore, which could in turn base its
+ // decision on persistent VR mode.
+ if (request_display_callback_)
+ request_display_callback_(!display_idle);
}
-int HardwareComposer::PostThreadPollInterruptible(int event_fd,
- int requested_events) {
+int HardwareComposer::PostThreadPollInterruptible(
+ const pdx::LocalHandle& event_fd, int requested_events) {
pollfd pfd[2] = {
{
- .fd = event_fd,
+ .fd = event_fd.Get(),
.events = static_cast<short>(requested_events),
.revents = 0,
},
{
- .fd = post_thread_interrupt_event_fd_.Get(),
+ .fd = post_thread_event_fd_.Get(),
.events = POLLPRI | POLLIN,
.revents = 0,
},
@@ -642,9 +636,8 @@
// TODO(eieio): This is pretty driver specific, this should be moved to a
// separate class eventually.
int HardwareComposer::BlockUntilVSync() {
- return PostThreadPollInterruptible(primary_display_vsync_event_fd_.Get(),
- // There will be a POLLPRI event on vsync
- POLLPRI);
+ // Vsync is signaled by POLLPRI on the fb vsync node.
+ return PostThreadPollInterruptible(primary_display_vsync_event_fd_, POLLPRI);
}
// Waits for the next vsync and returns the timestamp of the vsync event. If
@@ -683,7 +676,7 @@
// See how close we are to the next expected vsync. If we're within 1ms,
// sleep for 1ms and try again.
const int64_t ns_per_frame = display_metrics_.vsync_period_ns;
- const int64_t threshold_ns = 1000000;
+ const int64_t threshold_ns = 1000000; // 1ms
const int64_t next_vsync_est = last_vsync_timestamp_ + ns_per_frame;
const int64_t distance_to_vsync_est = next_vsync_est - GetSystemClockNs();
@@ -695,7 +688,7 @@
return error;
} else {
// Sleep for a short time (1 millisecond) before retrying.
- error = SleepUntil(GetSystemClockNs() + 1000000);
+ error = SleepUntil(GetSystemClockNs() + threshold_ns);
if (error < 0 || error == kPostThreadInterrupted)
return error;
}
@@ -717,24 +710,18 @@
return -error;
}
- return PostThreadPollInterruptible(timer_fd, POLLIN);
+ return PostThreadPollInterruptible(vsync_sleep_timer_fd_, POLLIN);
}
void HardwareComposer::PostThread() {
// NOLINTNEXTLINE(runtime/int)
prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrHwcPost"), 0, 0, 0);
- // Set the scheduler to SCHED_FIFO with high priority.
- int error = dvrSetSchedulerClass(0, "graphics:high");
- LOG_ALWAYS_FATAL_IF(
- error < 0,
- "HardwareComposer::PostThread: Failed to set scheduler class: %s",
- strerror(-error));
- error = dvrSetCpuPartition(0, "/system/performance");
- LOG_ALWAYS_FATAL_IF(
- error < 0,
- "HardwareComposer::PostThread: Failed to set cpu partition: %s",
- strerror(-error));
+ // Set the scheduler to SCHED_FIFO with high priority. If this fails here
+ // there may have been a startup timing issue between this thread and
+ // performanced. Try again later when this thread becomes active.
+ bool thread_policy_setup =
+ SetThreadPolicy("graphics:high", "/system/performance");
#if ENABLE_BACKLIGHT_BRIGHTNESS
// TODO(hendrikw): This isn't required at the moment. It's possible that there
@@ -744,7 +731,7 @@
ALOGW_IF(!backlight_brightness_fd_,
"HardwareComposer: Failed to open backlight brightness control: %s",
strerror(errno));
-#endif // ENABLE_BACKLIGHT_BRIGHTNESS
+#endif // ENABLE_BACKLIGHT_BRIGHTNESS
// Open the vsync event node for the primary display.
// TODO(eieio): Move this into a platform-specific class.
@@ -783,11 +770,6 @@
right_eye_photon_offset_ns =
property_get_int64(kRightEyeOffsetProperty, right_eye_photon_offset_ns);
- compositor_surfaces_.reserve(2);
-
- constexpr int kFrameTimeBacklogMax = 2;
- frame_time_backlog_.reserve(kFrameTimeBacklogMax);
-
// Storage for retrieving fence info.
FenceInfoBuffer fence_info_buffer;
@@ -796,35 +778,42 @@
while (1) {
ATRACE_NAME("HardwareComposer::PostThread");
- {
+ while (post_thread_quiescent_) {
std::unique_lock<std::mutex> lock(post_thread_mutex_);
- while (!post_thread_enabled_ || post_thread_quit_requested_ ||
- !PostThreadHasWork()) {
- if (was_running) {
- const char* pause_reason = "unknown";
- if (!post_thread_enabled_)
- pause_reason = "disabled";
- else if (post_thread_quit_requested_)
- pause_reason = "quit requested";
- else if (!PostThreadHasWork())
- pause_reason = "no work";
- ALOGI("VrHwcPost thread paused. Reason: %s.", pause_reason);
- OnPostThreadPaused();
- was_running = false;
- }
- post_thread_running_ = false;
- post_thread_cond_var_.notify_all();
- if (post_thread_quit_requested_)
- return;
- post_thread_cond_var_.wait(lock);
+ ALOGI("HardwareComposer::PostThread: Entering quiescent state.");
+
+ // Tear down resources.
+ OnPostThreadPaused();
+
+ was_running = false;
+ post_thread_resumed_ = false;
+ post_thread_ready_.notify_all();
+
+ if (post_thread_state_ & PostThreadState::Quit) {
+ ALOGI("HardwareComposer::PostThread: Quitting.");
+ return;
}
- post_thread_running_ = true;
+
+ post_thread_wait_.wait(lock, [this] { return !post_thread_quiescent_; });
+
+ post_thread_resumed_ = true;
+ post_thread_ready_.notify_all();
+
+ ALOGI("HardwareComposer::PostThread: Exiting quiescent state.");
}
if (!was_running) {
- ALOGI("VrHwcPost thread resumed");
+ // Setup resources.
OnPostThreadResumed();
was_running = true;
+
+ // Try to setup the scheduler policy if it failed during startup. Only
+ // attempt to do this on transitions from inactive to active to avoid
+ // spamming the system with RPCs and log messages.
+ if (!thread_policy_setup) {
+ thread_policy_setup =
+ SetThreadPolicy("graphics:high", "/system/performance");
+ }
}
int64_t vsync_timestamp = 0;
@@ -834,7 +823,7 @@
vsync_count_ + 1);
ATRACE_NAME(buf.data());
- error = WaitForVSync(&vsync_timestamp);
+ const int error = WaitForVSync(&vsync_timestamp);
ALOGE_IF(
error < 0,
"HardwareComposer::PostThread: Failed to wait for vsync event: %s",
@@ -854,74 +843,27 @@
ns_per_frame, right_eye_photon_offset_ns);
}
- bool layer_config_changed = UpdateLayerConfig();
-
- if (!was_running || layer_config_changed) {
- frame_time_history_.ResetWithSeed(
- GuessFrameTime(compositor_surfaces_.size()));
- frame_time_backlog_.clear();
- } else {
- UpdateFrameTimeHistory(&frame_time_backlog_, kFrameTimeBacklogMax,
- &fence_info_buffer, &frame_time_history_);
- }
-
- // Get our current best estimate at how long the next frame will take to
- // render, based on how long previous frames took to render. Use this
- // estimate to decide when to wake up for EDS.
- int64_t frame_time_estimate =
- frame_time_history_.GetSampleCount() == 0
- ? GuessFrameTime(compositor_surfaces_.size())
- : frame_time_history_.GetAverage();
- frame_time_estimate = std::max(frame_time_estimate, kFrameTimeEstimateMin);
- DebugHudData::data.hwc_latency = frame_time_estimate;
+ const bool layer_config_changed = UpdateLayerConfig();
// Signal all of the vsync clients. Because absolute time is used for the
// wakeup time below, this can take a little time if necessary.
if (vsync_callback_)
- vsync_callback_(HWC_DISPLAY_PRIMARY, vsync_timestamp, frame_time_estimate,
- vsync_count_);
+ vsync_callback_(HWC_DISPLAY_PRIMARY, vsync_timestamp,
+ /*frame_time_estimate*/ 0, vsync_count_);
{
- // Sleep until async EDS wakeup time.
+ // Sleep until shortly before vsync.
ATRACE_NAME("sleep");
- int64_t display_time_est = vsync_timestamp + ns_per_frame;
- int64_t now = GetSystemClockNs();
- int64_t frame_finish_time_est = now + frame_time_estimate;
- int64_t sleep_time_ns = display_time_est - now - frame_time_estimate;
+ const int64_t display_time_est_ns = vsync_timestamp + ns_per_frame;
+ const int64_t now_ns = GetSystemClockNs();
+ const int64_t sleep_time_ns =
+ display_time_est_ns - now_ns - kFramePostOffsetNs;
+ const int64_t wakeup_time_ns = display_time_est_ns - kFramePostOffsetNs;
ATRACE_INT64("sleep_time_ns", sleep_time_ns);
- if (frame_finish_time_est - display_time_est >= kFrameSkipThresholdNs) {
- ATRACE_INT("frame_skip_count", ++frame_skip_count_);
- ALOGE(
- "HardwareComposer::PostThread: Missed frame schedule, drop "
- "frame. Expected frame miss: %.1fms",
- static_cast<double>(frame_finish_time_est - display_time_est) /
- 1000000);
-
- // There are several reasons we might skip a frame, but one possibility
- // is we mispredicted the frame time. Clear out the frame time history.
- frame_time_history_.ResetWithSeed(
- GuessFrameTime(compositor_surfaces_.size()));
- frame_time_backlog_.clear();
- DebugHudData::data.hwc_frame_stats.SkipFrame();
-
- if (layer_config_changed) {
- // If the layer config changed we need to validateDisplay() even if
- // we're going to drop the frame, to flush the Composer object's
- // internal command buffer and apply our layer changes.
- Validate(HWC_DISPLAY_PRIMARY);
- }
-
- continue;
- } else {
- // Make the transition more obvious in systrace when the frame skip
- // happens above.
- ATRACE_INT("frame_skip_count", 0);
- }
-
if (sleep_time_ns > 0) {
- error = SleepUntil(display_time_est - frame_time_estimate);
+ int error = SleepUntil(wakeup_time_ns);
ALOGE_IF(error < 0, "HardwareComposer::PostThread: Failed to sleep: %s",
strerror(-error));
if (error == kPostThreadInterrupted) {
@@ -936,314 +878,58 @@
}
}
- DebugHudData::data.hwc_frame_stats.AddFrame();
-
- int64_t frame_start_time = GetSystemClockNs();
-
- // Setup the output buffer for the compositor. This needs to happen before
- // you draw with the compositor.
- if (gpu_layer_ != nullptr) {
- gpu_layer_->UpdateDirectBuffer(compositor_.GetBuffer());
- }
-
- // Call PostLayers now before performing the GL code for the compositor to
- // avoid missing the deadline that can cause the lower-level hwc to get
- // permanently backed up.
- PostLayers(layer_config_changed);
-
- PostCompositorBuffers();
-
- if (gpu_layer_ != nullptr) {
- // Note, with scanline racing, this draw is timed along with the post
- // layers to finish just in time.
- LocalHandle frame_fence_fd;
- compositor_.DrawFrame(vsync_count_ + 1, &frame_fence_fd);
- if (frame_fence_fd) {
- LOG_ALWAYS_FATAL_IF(frame_time_backlog_.size() >= kFrameTimeBacklogMax,
- "Frame time backlog exceeds capacity");
- frame_time_backlog_.push_back(
- {frame_start_time, std::move(frame_fence_fd)});
- }
- } else if (!layer_config_changed) {
- frame_time_history_.AddSample(GetSystemClockNs() - frame_start_time);
- }
-
- HandlePendingScreenshots();
+ PostLayers();
}
}
+// Checks for changes in the surface stack and updates the layer config to
+// accomodate the new stack.
bool HardwareComposer::UpdateLayerConfig() {
- std::vector<std::shared_ptr<DisplaySurface>> old_display_surfaces;
+ std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces;
{
- std::lock_guard<std::mutex> lock(post_thread_mutex_);
- if (!active_surfaces_updated_)
+ std::unique_lock<std::mutex> lock(post_thread_mutex_);
+ if (pending_surfaces_.empty())
return false;
- old_display_surfaces = display_surfaces_;
- display_surfaces_ = active_surfaces_;
- active_surfaces_updated_ = false;
+
+ surfaces = std::move(pending_surfaces_);
}
- DebugHudData::data.ResetLayers();
-
- // Figure out whether we need to update hardware layers. If this surface
- // change does not add or remove hardware layers we can avoid display hiccups
- // by gracefully updating only the GPU compositor layers.
- int old_gpu_layer_count = 0;
- int new_gpu_layer_count = 0;
- bool hardware_layers_need_update = false;
- // Look for new hardware layers and count new GPU layers.
- for (const auto& surface : display_surfaces_) {
- if (!(surface->flags() &
- DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION))
- ++new_gpu_layer_count;
- else if (std::find(old_display_surfaces.begin(), old_display_surfaces.end(),
- surface) == old_display_surfaces.end())
- // This is a new hardware layer, we need to update.
- hardware_layers_need_update = true;
- }
- // Look for deleted hardware layers or compositor layers.
- for (const auto& surface : old_display_surfaces) {
- if (!(surface->flags() &
- DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION))
- ++old_gpu_layer_count;
- else if (std::find(display_surfaces_.begin(), display_surfaces_.end(),
- surface) == display_surfaces_.end())
- // This is a deleted hardware layer, we need to update.
- hardware_layers_need_update = true;
- }
- // Check for compositor hardware layer transition.
- if ((!old_gpu_layer_count && new_gpu_layer_count) ||
- (old_gpu_layer_count && !new_gpu_layer_count))
- hardware_layers_need_update = true;
-
- // Set the chosen layer order for all surfaces.
- for (size_t i = 0; i < display_surfaces_.size(); ++i) {
- display_surfaces_[i]->SetLayerOrder(static_cast<int>(i));
- }
-
- // Update compositor layers.
- {
- ATRACE_NAME("UpdateLayerConfig_GpuLayers");
- compositor_.UpdateSurfaces(display_surfaces_);
- compositor_surfaces_.clear();
- for (size_t i = 0; i < display_surfaces_.size(); ++i) {
- const auto& surface = display_surfaces_[i];
- if (!(surface->flags() &
- DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION)) {
- compositor_surfaces_.push_back(surface);
- }
- }
- }
-
- if (!hardware_layers_need_update)
- return true;
-
- // Update hardware layers.
-
ATRACE_NAME("UpdateLayerConfig_HwLayers");
- // Update the display layers in a non-destructive fashion.
+ display_surfaces_.clear();
- // Create a map from surface id to hardware layer
- std::map<int, Layer*> display_surface_layers;
-
- for (size_t i = 0; i < active_layer_count_; ++i) {
- auto layer = layers_[i];
- int surface_id = layer->GetSurfaceId();
-
- auto found =
- std::find_if(display_surfaces_.begin(), display_surfaces_.end(),
- [surface_id](const auto& surface) {
- return surface->surface_id() == surface_id;
- });
-
- if (found != display_surfaces_.end()) {
- display_surface_layers[surface_id] = layer;
- }
+ Layer* target_layer;
+ size_t layer_index;
+ for (layer_index = 0;
+ layer_index < std::min(surfaces.size(), kMaxHardwareLayers);
+ layer_index++) {
+ // The bottom layer is opaque, other layers blend.
+ HWC::BlendMode blending =
+ layer_index == 0 ? HWC::BlendMode::None : HWC::BlendMode::Coverage;
+ layers_[layer_index].Setup(surfaces[layer_index], blending,
+ display_transform_, HWC::Composition::Device,
+ layer_index);
+ display_surfaces_.push_back(surfaces[layer_index]);
}
- bool has_gpu_layer = std::any_of(
- display_surfaces_.begin(), display_surfaces_.end(),
- [](const auto& surface) {
- return !(surface->flags() &
- DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION);
- });
+ // Clear unused layers.
+ for (size_t i = layer_index; i < kMaxHardwareLayers; i++)
+ layers_[i].Reset();
- if (!has_gpu_layer) {
- gpu_layer_ = nullptr;
- }
-
- auto is_layer_active = [&display_surface_layers, has_gpu_layer](auto layer) {
- int surface_id = layer->GetSurfaceId();
- if (surface_id >= 0) {
- return display_surface_layers.count(surface_id) > 0;
- } else {
- return has_gpu_layer;
- }
- };
-
- // Compress the in-use layers to the top of the list
- auto part = std::partition(
- layers_.begin(), layers_.begin() + active_layer_count_, is_layer_active);
-
- size_t new_active_layer_count = part - layers_.begin();
-
- // Clear any unused layers
- for (size_t i = new_active_layer_count; i < active_layer_count_; ++i) {
- layers_[i]->Reset();
- }
-
- active_layer_count_ = new_active_layer_count;
-
- bool gpu_layer_applied = false;
-
- // Create/update all of the hardware layers
- for (size_t i = 0; i < display_surfaces_.size(); ++i) {
- const auto& surface = display_surfaces_[i];
- bool is_hw_surface =
- surface->flags() & DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION;
- hwc2_blend_mode_t blending =
- i == 0 ? HWC2_BLEND_MODE_NONE : HWC2_BLEND_MODE_COVERAGE;
-
- DebugHudData::data.SetLayerInfo(
- i, surface->width(), surface->height(),
- !!(surface->flags() & DVR_DISPLAY_SURFACE_FLAGS_GEOMETRY_SEPARATE_2));
-
- if (!is_hw_surface && gpu_layer_applied) {
- continue;
- }
-
- Layer* target_layer;
- bool existing_layer = false;
-
- if (is_hw_surface) {
- auto it = display_surface_layers.find(surface->surface_id());
-
- if (it != display_surface_layers.end()) {
- target_layer = it->second;
- existing_layer = true;
- }
- } else if (gpu_layer_ != nullptr) {
- target_layer = gpu_layer_;
- existing_layer = true;
- }
-
- if (!existing_layer) {
- if (active_layer_count_ >= kMaxHardwareLayers) {
- ALOGI("HardwareComposer: More than %d hardware layers requested.",
- kMaxHardwareLayers);
- break;
- } else {
- target_layer = layers_[active_layer_count_];
- ++active_layer_count_;
- }
-
- ALOGD_IF(TRACE,
- "HardwareComposer::UpdateLayerConfig: (new) surface_id=%d -> "
- "layer=%zd",
- surface->surface_id(), i);
-
- if (is_hw_surface) {
- target_layer->Setup(surface, blending, display_transform_,
- HWC2_COMPOSITION_DEVICE, i);
- } else {
- gpu_layer_ = target_layer;
- target_layer->Setup(compositor_.GetBuffer(), blending,
- display_transform_, HWC2_COMPOSITION_DEVICE, i);
- }
- } else {
- ALOGD_IF(TRACE,
- "HardwareComposer::UpdateLayerConfig: (retained) surface_id=%d "
- "-> layer=%zd",
- surface->surface_id(), i);
-
- target_layer->SetBlending(blending);
- target_layer->SetZOrderIndex(i);
- target_layer->UpdateLayerSettings();
- }
-
- gpu_layer_applied = !is_hw_surface;
- }
-
+ active_layer_count_ = layer_index;
ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers",
active_layer_count_);
+ // Any surfaces left over could not be assigned a hardware layer and will
+ // not be displayed.
+ ALOGW_IF(surfaces.size() != display_surfaces_.size(),
+ "HardwareComposer::UpdateLayerConfig: More surfaces than layers: "
+ "pending_surfaces=%zu display_surfaces=%zu",
+ surfaces.size(), display_surfaces_.size());
+
return true;
}
-void HardwareComposer::PostCompositorBuffers() {
- ATRACE_NAME("PostCompositorBuffers");
- for (const auto& surface : compositor_surfaces_) {
- compositor_.PostBuffer(surface);
- }
-}
-
-void HardwareComposer::UpdateFrameTimeHistory(
- std::vector<FrameTimeMeasurementRecord>* backlog, int backlog_max,
- FenceInfoBuffer* fence_info_buffer, FrameTimeHistory* history) {
- while (!backlog->empty()) {
- const auto& frame_time_record = backlog->front();
- int64_t end_time = 0;
- bool frame_finished = CheckFrameFinished(frame_time_record.fence.Get(),
- fence_info_buffer, &end_time);
- if (frame_finished) {
- int64_t frame_duration = end_time - frame_time_record.start_time;
- history->AddSample(frame_duration);
- // Our backlog is tiny (2 elements), so erasing from the front is ok
- backlog->erase(backlog->begin());
- } else {
- break;
- }
- }
-
- if (backlog->size() == static_cast<size_t>(backlog_max)) {
- // Yikes, something must've gone wrong if our oldest frame hasn't finished
- // yet. Give up on waiting for it.
- const auto& stale_frame_time_record = backlog->front();
- int64_t frame_duration =
- GetSystemClockNs() - stale_frame_time_record.start_time;
- backlog->erase(backlog->begin());
- history->AddSample(frame_duration);
- ALOGW("Frame didn't finish after %.1fms",
- static_cast<double>(frame_duration) / 1000000);
- }
-}
-
-bool HardwareComposer::CheckFrameFinished(int frame_fence_fd,
- FenceInfoBuffer* fence_info_buffer,
- int64_t* timestamp) {
- int result = -1;
- int sync_result = sync_wait(frame_fence_fd, 0);
- if (sync_result == 0) {
- result =
- GetFenceSignaledTimestamp(frame_fence_fd, fence_info_buffer, timestamp);
- if (result < 0) {
- ALOGE("Failed getting signaled timestamp from fence");
- }
- } else if (errno != ETIME) {
- ALOGE("sync_wait on frame fence failed");
- }
- return result >= 0;
-}
-
-void HardwareComposer::HandlePendingScreenshots() {
- // Take a screenshot of the requested layer, if available.
- // TODO(eieio): Look into using virtual displays to composite the layer stack
- // into a single output buffer that can be returned to the screenshot clients.
- if (active_layer_count_ > 0) {
- if (auto screenshot_service = ScreenshotService::GetInstance()) {
- if (screenshot_service->IsScreenshotRequestPending()) {
- ATRACE_NAME("screenshot");
- screenshot_service->TakeIfNeeded(layers_, compositor_);
- }
- } else {
- ALOGW(
- "HardwareComposer::HandlePendingScreenshots: Failed to get "
- "screenshot service!");
- }
- }
-}
-
void HardwareComposer::SetVSyncCallback(VSyncCallback callback) {
vsync_callback_ = callback;
}
@@ -1280,145 +966,133 @@
}
}
-Layer::Layer()
- : hwc2_hidl_(nullptr),
- surface_index_(-1),
- hardware_composer_layer_(0),
- display_metrics_(nullptr),
- blending_(HWC2_BLEND_MODE_NONE),
- transform_(HWC_TRANSFORM_NONE),
- composition_type_(HWC2_COMPOSITION_DEVICE),
- surface_rect_functions_applied_(false) {}
-
-void Layer::Initialize(Hwc2::Composer* hwc2_hidl, HWCDisplayMetrics* metrics) {
+void Layer::InitializeGlobals(Hwc2::Composer* hwc2_hidl,
+ const HWCDisplayMetrics* metrics) {
hwc2_hidl_ = hwc2_hidl;
display_metrics_ = metrics;
}
void Layer::Reset() {
- const int ret = acquired_buffer_.Release(std::move(release_fence_));
- ALOGE_IF(ret < 0, "Layer::Reset: failed to release buffer: %s",
- strerror(-ret));
-
if (hwc2_hidl_ != nullptr && hardware_composer_layer_) {
hwc2_hidl_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
hardware_composer_layer_ = 0;
}
- surface_index_ = static_cast<size_t>(-1);
- blending_ = HWC2_BLEND_MODE_NONE;
- transform_ = HWC_TRANSFORM_NONE;
- composition_type_ = HWC2_COMPOSITION_DEVICE;
- direct_buffer_ = nullptr;
- surface_ = nullptr;
- acquire_fence_fd_.Close();
+ z_order_ = 0;
+ blending_ = HWC::BlendMode::None;
+ transform_ = HWC::Transform::None;
+ composition_type_ = HWC::Composition::Invalid;
+ target_composition_type_ = composition_type_;
+ source_ = EmptyVariant{};
+ acquire_fence_.Close();
surface_rect_functions_applied_ = false;
}
-void Layer::Setup(const std::shared_ptr<DisplaySurface>& surface,
- hwc2_blend_mode_t blending, hwc_transform_t transform,
- hwc2_composition_t composition_type, size_t index) {
+void Layer::Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
+ HWC::BlendMode blending, HWC::Transform transform,
+ HWC::Composition composition_type, size_t z_order) {
Reset();
- surface_index_ = index;
- surface_ = surface;
+ z_order_ = z_order;
blending_ = blending;
transform_ = transform;
- composition_type_ = composition_type;
+ composition_type_ = HWC::Composition::Invalid;
+ target_composition_type_ = composition_type;
+ source_ = SourceSurface{surface};
CommonLayerSetup();
}
void Layer::Setup(const std::shared_ptr<IonBuffer>& buffer,
- hwc2_blend_mode_t blending, hwc_transform_t transform,
- hwc2_composition_t composition_type, size_t z_order) {
+ HWC::BlendMode blending, HWC::Transform transform,
+ HWC::Composition composition_type, size_t z_order) {
Reset();
- surface_index_ = z_order;
- direct_buffer_ = buffer;
+ z_order_ = z_order;
blending_ = blending;
transform_ = transform;
- composition_type_ = composition_type;
+ composition_type_ = HWC::Composition::Invalid;
+ target_composition_type_ = composition_type;
+ source_ = SourceBuffer{buffer};
CommonLayerSetup();
}
-void Layer::UpdateDirectBuffer(const std::shared_ptr<IonBuffer>& buffer) {
- direct_buffer_ = buffer;
+void Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) {
+ if (source_.is<SourceBuffer>())
+ std::get<SourceBuffer>(source_) = {buffer};
}
-void Layer::SetBlending(hwc2_blend_mode_t blending) { blending_ = blending; }
-
-void Layer::SetZOrderIndex(int z_index) { surface_index_ = z_index; }
+void Layer::SetBlending(HWC::BlendMode blending) { blending_ = blending; }
+void Layer::SetZOrder(size_t z_order) { z_order_ = z_order; }
IonBuffer* Layer::GetBuffer() {
- if (direct_buffer_)
- return direct_buffer_.get();
- else if (acquired_buffer_.IsAvailable())
- return acquired_buffer_.buffer()->buffer();
- else
- return nullptr;
+ struct Visitor {
+ IonBuffer* operator()(SourceSurface& source) { return source.GetBuffer(); }
+ IonBuffer* operator()(SourceBuffer& source) { return source.GetBuffer(); }
+ IonBuffer* operator()(EmptyVariant) { return nullptr; }
+ };
+ return source_.Visit(Visitor{});
}
void Layer::UpdateLayerSettings() {
if (!IsLayerSetup()) {
- ALOGE("HardwareComposer: Trying to update layers data on an unused layer.");
+ ALOGE(
+ "HardwareComposer::Layer::UpdateLayerSettings: Attempt to update "
+ "unused Layer!");
return;
}
- int32_t ret = HWC2_ERROR_NONE;
-
+ HWC::Error error;
hwc2_display_t display = HWC_DISPLAY_PRIMARY;
- ret = (int32_t)hwc2_hidl_->setLayerCompositionType(
+ error = hwc2_hidl_->setLayerCompositionType(
display, hardware_composer_layer_,
- (Hwc2::IComposerClient::Composition)composition_type_);
- ALOGE_IF(ret, "HardwareComposer: Error setting layer composition type : %d",
- ret);
- // ret = (int32_t) hwc2_hidl_->setLayerTransform(display,
- // hardware_composer_layer_,
- // (Hwc2::IComposerClient::Transform)
- // transform_);
- // ALOGE_IF(ret, "HardwareComposer: Error setting layer transform : %d", ret);
+ composition_type_.cast<Hwc2::IComposerClient::Composition>());
+ ALOGE_IF(
+ error != HWC::Error::None,
+ "Layer::UpdateLayerSettings: Error setting layer composition type: %s",
+ error.to_string().c_str());
- // ret = hwc2_funcs_->set_layer_blend_mode_fn_(
- // hardware_composer_device_, display, hardware_composer_layer_,
- // blending_);
- ret = (int32_t)hwc2_hidl_->setLayerBlendMode(
+ error = hwc2_hidl_->setLayerBlendMode(
display, hardware_composer_layer_,
- (Hwc2::IComposerClient::BlendMode)blending_);
- ALOGE_IF(ret, "HardwareComposer: Error setting layer blend mode : %d", ret);
+ blending_.cast<Hwc2::IComposerClient::BlendMode>());
+ ALOGE_IF(error != HWC::Error::None,
+ "Layer::UpdateLayerSettings: Error setting layer blend mode: %s",
+ error.to_string().c_str());
- Hwc2::IComposerClient::Rect display_frame;
- display_frame.left = 0;
- display_frame.top = 0;
- display_frame.right = display_metrics_->width;
- display_frame.bottom = display_metrics_->height;
- ret = (int32_t)hwc2_hidl_->setLayerDisplayFrame(
- display, hardware_composer_layer_, display_frame);
- ALOGE_IF(ret, "HardwareComposer: Error setting layer display frame : %d",
- ret);
+ // TODO(eieio): Use surface attributes or some other mechanism to control
+ // the layer display frame.
+ error = hwc2_hidl_->setLayerDisplayFrame(
+ display, hardware_composer_layer_,
+ {0, 0, display_metrics_->width, display_metrics_->height});
+ ALOGE_IF(error != HWC::Error::None,
+ "Layer::UpdateLayerSettings: Error setting layer display frame: %s",
+ error.to_string().c_str());
- std::vector<Hwc2::IComposerClient::Rect> visible_region(1);
- visible_region[0] = display_frame;
- ret = (int32_t)hwc2_hidl_->setLayerVisibleRegion(
- display, hardware_composer_layer_, visible_region);
- ALOGE_IF(ret, "HardwareComposer: Error setting layer visible region : %d",
- ret);
+ error = hwc2_hidl_->setLayerVisibleRegion(
+ display, hardware_composer_layer_,
+ {{0, 0, display_metrics_->width, display_metrics_->height}});
+ ALOGE_IF(error != HWC::Error::None,
+ "Layer::UpdateLayerSettings: Error setting layer visible region: %s",
+ error.to_string().c_str());
- ret = (int32_t)hwc2_hidl_->setLayerPlaneAlpha(display,
- hardware_composer_layer_, 1.0f);
- ALOGE_IF(ret, "HardwareComposer: Error setting layer plane alpha : %d", ret);
+ error =
+ hwc2_hidl_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
+ ALOGE_IF(error != HWC::Error::None,
+ "Layer::UpdateLayerSettings: Error setting layer plane alpha: %s",
+ error.to_string().c_str());
- ret = (int32_t)hwc2_hidl_->setLayerZOrder(display, hardware_composer_layer_,
- surface_index_);
- ALOGE_IF(ret, "HardwareComposer: Error, setting z order index : %d", ret);
+ error =
+ hwc2_hidl_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
+ ALOGE_IF(error != HWC::Error::None,
+ "Layer::UpdateLayerSettings: Error setting z_ order: %s",
+ error.to_string().c_str());
}
void Layer::CommonLayerSetup() {
- int32_t ret = (int32_t)hwc2_hidl_->createLayer(HWC_DISPLAY_PRIMARY,
- &hardware_composer_layer_);
-
- ALOGE_IF(ret,
- "HardwareComposer: Failed to create layer on primary display : %d",
- ret);
-
+ HWC::Error error =
+ hwc2_hidl_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
+ ALOGE_IF(
+ error != HWC::Error::None,
+ "Layer::CommonLayerSetup: Failed to create layer on primary display: %s",
+ error.to_string().c_str());
UpdateLayerSettings();
}
@@ -1426,114 +1100,69 @@
int right, bottom;
sp<GraphicBuffer> handle;
- if (surface_) {
- // Only update the acquired buffer when one is either available or this is
- // the first time through.
- if (surface_->IsBufferAvailable()) {
- // If we previously set this to a solid color layer to stall for time,
- // revert it to a device layer.
- if (acquired_buffer_.IsEmpty() &&
- composition_type_ != HWC2_COMPOSITION_DEVICE) {
- composition_type_ = HWC2_COMPOSITION_DEVICE;
- hwc2_hidl_->setLayerCompositionType(
- HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
- (Hwc2::IComposerClient::Composition)HWC2_COMPOSITION_DEVICE);
- }
+ // Acquire the next buffer according to the type of source.
+ IfAnyOf<SourceSurface, SourceBuffer>::Call(&source_, [&](auto& source) {
+ std::tie(right, bottom, handle, acquire_fence_) = source.Acquire();
+ });
- DebugHudData::data.AddLayerFrame(surface_index_);
- acquired_buffer_.Release(std::move(release_fence_));
- acquired_buffer_ = surface_->AcquireCurrentBuffer();
-
- // Basic latency stopgap for when the application misses a frame:
- // If the application recovers on the 2nd or 3rd (etc) frame after
- // missing, this code will skip a frame to catch up by checking if
- // the next frame is also available.
- if (surface_->IsBufferAvailable()) {
- DebugHudData::data.SkipLayerFrame(surface_index_);
- ATRACE_NAME("DropToCatchUp");
- ATRACE_ASYNC_END("BufferPost", acquired_buffer_.buffer()->id());
- acquired_buffer_ = surface_->AcquireCurrentBuffer();
- }
- ATRACE_ASYNC_END("BufferPost", acquired_buffer_.buffer()->id());
- } else if (acquired_buffer_.IsEmpty()) {
- // While we are waiting for a buffer, set this to be an empty layer
- if (composition_type_ != HWC2_COMPOSITION_SOLID_COLOR) {
- composition_type_ = HWC2_COMPOSITION_SOLID_COLOR;
- hwc2_hidl_->setLayerCompositionType(
- HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
- (Hwc2::IComposerClient::Composition)HWC2_COMPOSITION_SOLID_COLOR);
-
- Hwc2::IComposerClient::Color layer_color = {
- 0, 0, 0, 0,
- };
- hwc2_hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
- layer_color);
- }
- return;
+ // When a layer is first setup there may be some time before the first buffer
+ // arrives. Setup the HWC layer as a solid color to stall for time until the
+ // first buffer arrives. Once the first buffer arrives there will always be a
+ // buffer for the frame even if it is old.
+ if (!handle.get()) {
+ if (composition_type_ == HWC::Composition::Invalid) {
+ composition_type_ = HWC::Composition::SolidColor;
+ hwc2_hidl_->setLayerCompositionType(
+ HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+ composition_type_.cast<Hwc2::IComposerClient::Composition>());
+ Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0};
+ hwc2_hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+ layer_color);
+ } else {
+ // The composition type is already set. Nothing else to do until a
+ // buffer arrives.
}
- right = acquired_buffer_.buffer()->width();
- bottom = acquired_buffer_.buffer()->height();
- handle = acquired_buffer_.buffer()->buffer()->buffer();
- acquire_fence_fd_.Reset(acquired_buffer_.ClaimAcquireFence().Release());
} else {
- // TODO(jwcai) Note: this is the GPU compositor's layer, and we need the
- // mechanism to accept distorted layers from VrCore.
- right = direct_buffer_->width();
- bottom = direct_buffer_->height();
- handle = direct_buffer_->buffer();
- acquire_fence_fd_.Close();
- }
+ if (composition_type_ != target_composition_type_) {
+ composition_type_ = target_composition_type_;
+ hwc2_hidl_->setLayerCompositionType(
+ HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+ composition_type_.cast<Hwc2::IComposerClient::Composition>());
+ }
- int32_t ret = HWC2_ERROR_NONE;
+ HWC::Error error{HWC::Error::None};
+ error = hwc2_hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY,
+ hardware_composer_layer_, 0, handle,
+ acquire_fence_.Get());
- if (composition_type_ == HWC2_COMPOSITION_DEVICE) {
- ret = (int32_t)hwc2_hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY,
- hardware_composer_layer_, 0,
- handle,
- acquire_fence_fd_.Get());
+ ALOGE_IF(error != HWC::Error::None,
+ "Layer::Prepare: Error setting layer buffer: %s",
+ error.to_string().c_str());
- ALOGE_IF(ret, "HardwareComposer: Error setting layer buffer : %d", ret);
- }
+ if (!surface_rect_functions_applied_) {
+ const float float_right = right;
+ const float float_bottom = bottom;
+ error = hwc2_hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
+ hardware_composer_layer_,
+ {0, 0, float_right, float_bottom});
- if (!surface_rect_functions_applied_) {
- Hwc2::IComposerClient::FRect crop_rect = {
- 0, 0, static_cast<float>(right), static_cast<float>(bottom),
- };
- hwc2_hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
- hardware_composer_layer_, crop_rect);
+ ALOGE_IF(error != HWC::Error::None,
+ "Layer::Prepare: Error setting layer source crop: %s",
+ error.to_string().c_str());
- ALOGE_IF(ret, "HardwareComposer: Error setting layer source crop : %d",
- ret);
-
-// TODO(skiazyk): why is this ifdef'd out. Is if a driver-specific issue where
-// it must/cannot be called?
-#ifdef QCOM_BSP
- hwc_rect_t damage_rect = {
- 0, 0, right, bottom,
- };
- hwc_region_t damage = {
- 1, &damage_rect,
- };
- // ret = hwc2_funcs_->set_layer_surface_damage(
- // hardware_composer_device_, HWC_DISPLAY_PRIMARY,
- // hardware_composer_layer_, damage);
- // uses a std::vector as the listing
- // hwc2_hidl_->setLayerSurfaceDamage(HWC_DISPLAY_PRIMARY,
- // hardware_composer_layer_, vector here);
-
- ALOGE_IF(ret, "HardwareComposer: Error settings layer surface damage : %d",
- ret);
-#endif
-
- surface_rect_functions_applied_ = true;
+ surface_rect_functions_applied_ = true;
+ }
}
}
void Layer::Finish(int release_fence_fd) {
- release_fence_.Reset(release_fence_fd);
+ IfAnyOf<SourceSurface, SourceBuffer>::Call(
+ &source_, [release_fence_fd](auto& source) {
+ source.Finish(LocalHandle(release_fence_fd));
+ });
}
-void Layer::Drop() { acquire_fence_fd_.Close(); }
+void Layer::Drop() { acquire_fence_.Close(); }
} // namespace dvr
} // namespace android
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index e570cb6..5a75f42 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -1,13 +1,12 @@
#ifndef ANDROID_DVR_SERVICES_DISPLAYD_HARDWARE_COMPOSER_H_
#define ANDROID_DVR_SERVICES_DISPLAYD_HARDWARE_COMPOSER_H_
-#include <log/log.h>
-#include <hardware/gralloc.h>
-#include <hardware/hardware.h>
-#include <hardware/hwcomposer2.h>
+#include <ui/GraphicBuffer.h>
+#include "DisplayHardware/ComposerHal.h"
+#include "hwc_types.h"
-#include <private/dvr/buffer_hub_client.h>
-#include <private/dvr/sync_util.h>
+#include <hardware/gralloc.h>
+#include <log/log.h>
#include <array>
#include <condition_variable>
@@ -17,17 +16,16 @@
#include <tuple>
#include <vector>
+#include <dvr/pose_client.h>
#include <pdx/file_handle.h>
+#include <pdx/rpc/variant.h>
#include <private/dvr/buffer_hub_client.h>
#include <private/dvr/frame_time_history.h>
#include <private/dvr/sync_util.h>
#include "acquired_buffer.h"
-#include "compositor.h"
#include "display_surface.h"
-#include "DisplayHardware/ComposerHal.h"
-
// Hardware composer HAL doesn't define HWC_TRANSFORM_NONE as of this writing.
#ifndef HWC_TRANSFORM_NONE
#define HWC_TRANSFORM_NONE static_cast<hwc_transform_t>(0)
@@ -53,29 +51,28 @@
// source supplying buffers for the layer's contents.
class Layer {
public:
- Layer();
+ Layer() {}
- // Sets the hardware composer layer and display metrics that this Layer should
- // use each Prepare cycle. This class does not own either of these pointers,
- // which MUST remain valid for its lifetime. This method MUST be called once
- // in the life of the instance before any other method is valid to call.
- void Initialize(Hwc2::Composer* hwc2_hidl, HWCDisplayMetrics* metrics);
+ // Sets up the global state used by all Layer instances. This must be called
+ // before using any Layer methods.
+ static void InitializeGlobals(Hwc2::Composer* hwc2_hidl,
+ const HWCDisplayMetrics* metrics);
// Releases any shared pointers and fence handles held by this instance.
void Reset();
// Sets up the layer to use a display surface as its content source. The Layer
- // will automatically handle ACQUIRE/RELEASE phases for the surface's buffer
- // train every frame.
+ // automatically handles ACQUIRE/RELEASE phases for the surface's buffer train
+ // every frame.
//
// |blending| receives HWC_BLENDING_* values.
// |transform| receives HWC_TRANSFORM_* values.
// |composition_type| receives either HWC_FRAMEBUFFER for most layers or
// HWC_FRAMEBUFFER_TARGET (unless you know what you are doing).
- // |index| is the index of this surface in the DisplaySurface array.
- void Setup(const std::shared_ptr<DisplaySurface>& surface,
- hwc2_blend_mode_t blending, hwc_transform_t transform,
- hwc2_composition_t composition_type, size_t index);
+ // |index| is the index of this surface in the DirectDisplaySurface array.
+ void Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
+ HWC::BlendMode blending, HWC::Transform transform,
+ HWC::Composition composition_type, size_t z_roder);
// Sets up the layer to use a direct buffer as its content source. No special
// handling of the buffer is performed; responsibility for updating or
@@ -85,13 +82,13 @@
// |transform| receives HWC_TRANSFORM_* values.
// |composition_type| receives either HWC_FRAMEBUFFER for most layers or
// HWC_FRAMEBUFFER_TARGET (unless you know what you are doing).
- void Setup(const std::shared_ptr<IonBuffer>& buffer,
- hwc2_blend_mode_t blending, hwc_transform_t transform,
- hwc2_composition_t composition_type, size_t z_order);
+ void Setup(const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
+ HWC::Transform transform, HWC::Composition composition_type,
+ size_t z_order);
// Layers that use a direct IonBuffer should call this each frame to update
// which buffer will be used for the next PostLayers.
- void UpdateDirectBuffer(const std::shared_ptr<IonBuffer>& buffer);
+ void UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer);
// Sets up the hardware composer layer for the next frame. When the layer is
// associated with a display surface, this method automatically ACQUIRES a new
@@ -107,10 +104,10 @@
void Finish(int release_fence_fd);
// Sets the blending for the layer. |blending| receives HWC_BLENDING_* values.
- void SetBlending(hwc2_blend_mode_t blending);
+ void SetBlending(HWC::BlendMode blending);
- // Sets the Z-order of this layer
- void SetZOrderIndex(int surface_index);
+ // Sets the z-order of this layer
+ void SetZOrder(size_t z_order);
// Gets the current IonBuffer associated with this layer. Ownership of the
// buffer DOES NOT pass to the caller and the pointer is not guaranteed to
@@ -118,57 +115,111 @@
// Layer::Reset(). YOU HAVE BEEN WARNED.
IonBuffer* GetBuffer();
- hwc2_composition_t GetCompositionType() const { return composition_type_; }
-
- hwc2_layer_t GetLayerHandle() const { return hardware_composer_layer_; }
-
- bool UsesDirectBuffer() const { return direct_buffer_ != nullptr; }
-
- bool IsLayerSetup() const {
- return direct_buffer_ != nullptr || surface_ != nullptr;
- }
+ HWC::Composition GetCompositionType() const { return composition_type_; }
+ HWC::Layer GetLayerHandle() const { return hardware_composer_layer_; }
+ bool IsLayerSetup() const { return !source_.empty(); }
// Applies all of the settings to this layer using the hwc functions
void UpdateLayerSettings();
int GetSurfaceId() const {
- if (surface_ != nullptr) {
- return surface_->surface_id();
- } else {
- return -1;
- }
+ int surface_id = -1;
+ pdx::rpc::IfAnyOf<SourceSurface>::Call(
+ &source_, [&surface_id](const SourceSurface& surface_source) {
+ surface_id = surface_source.surface->surface_id();
+ });
+ return surface_id;
}
private:
void CommonLayerSetup();
- Hwc2::Composer* hwc2_hidl_;
-
- // Original display surface array index for tracking purposes.
- size_t surface_index_;
+ static Hwc2::Composer* hwc2_hidl_;
+ static const HWCDisplayMetrics* display_metrics_;
// The hardware composer layer and metrics to use during the prepare cycle.
- hwc2_layer_t hardware_composer_layer_;
- HWCDisplayMetrics* display_metrics_;
+ hwc2_layer_t hardware_composer_layer_ = 0;
// Layer properties used to setup the hardware composer layer during the
// Prepare phase.
- hwc2_blend_mode_t blending_;
- hwc_transform_t transform_;
- hwc2_composition_t composition_type_;
+ size_t z_order_ = 0;
+ HWC::BlendMode blending_ = HWC::BlendMode::None;
+ HWC::Transform transform_ = HWC::Transform::None;
+ HWC::Composition composition_type_ = HWC::Composition::Invalid;
+ HWC::Composition target_composition_type_ = HWC::Composition::Device;
- // These two members are mutually exclusive. When direct_buffer_ is set the
- // Layer gets its contents directly from that buffer; when surface_ is set the
- // Layer gets it contents from the surface's buffer train.
- std::shared_ptr<IonBuffer> direct_buffer_;
- std::shared_ptr<DisplaySurface> surface_;
+ // State when the layer is connected to a surface. Provides the same interface
+ // as SourceBuffer to simplify internal use by Layer.
+ struct SourceSurface {
+ std::shared_ptr<DirectDisplaySurface> surface;
+ AcquiredBuffer acquired_buffer;
+ pdx::LocalHandle release_fence;
- // State when associated with a display surface.
- AcquiredBuffer acquired_buffer_;
- pdx::LocalHandle release_fence_;
+ SourceSurface(const std::shared_ptr<DirectDisplaySurface>& surface)
+ : surface(surface) {}
- pdx::LocalHandle acquire_fence_fd_;
- bool surface_rect_functions_applied_;
+ // Attempts to acquire a new buffer from the surface and return a tuple with
+ // width, height, buffer handle, and fence. If a new buffer is not available
+ // the previous buffer is returned or an empty value if no buffer has ever
+ // been posted. When a new buffer is acquired the previous buffer's release
+ // fence is passed out automatically.
+ std::tuple<int, int, sp<GraphicBuffer>, pdx::LocalHandle> Acquire() {
+ if (surface->IsBufferAvailable()) {
+ acquired_buffer.Release(std::move(release_fence));
+ acquired_buffer = surface->AcquireCurrentBuffer();
+ ATRACE_ASYNC_END("BufferPost", acquired_buffer.buffer()->id());
+ }
+ if (!acquired_buffer.IsEmpty()) {
+ return std::make_tuple(acquired_buffer.buffer()->width(),
+ acquired_buffer.buffer()->height(),
+ acquired_buffer.buffer()->buffer()->buffer(),
+ acquired_buffer.ClaimAcquireFence());
+ } else {
+ return std::make_tuple(0, 0, nullptr, pdx::LocalHandle{});
+ }
+ }
+
+ void Finish(pdx::LocalHandle fence) { release_fence = std::move(fence); }
+
+ // Gets a pointer to the current acquired buffer or returns nullptr if there
+ // isn't one.
+ IonBuffer* GetBuffer() {
+ if (acquired_buffer.IsAvailable())
+ return acquired_buffer.buffer()->buffer();
+ else
+ return nullptr;
+ }
+
+ // Returns the surface id of the surface.
+ int GetSurfaceId() { return surface->surface_id(); }
+ };
+
+ // State when the layer is connected to a buffer. Provides the same interface
+ // as SourceSurface to simplify internal use by Layer.
+ struct SourceBuffer {
+ std::shared_ptr<IonBuffer> buffer;
+
+ std::tuple<int, int, sp<GraphicBuffer>, pdx::LocalHandle> Acquire() {
+ if (buffer)
+ return std::make_tuple(buffer->width(), buffer->height(),
+ buffer->buffer(), pdx::LocalHandle{});
+ else
+ return std::make_tuple(0, 0, nullptr, pdx::LocalHandle{});
+ }
+
+ void Finish(pdx::LocalHandle /*fence*/) {}
+
+ IonBuffer* GetBuffer() { return buffer.get(); }
+
+ int GetSurfaceId() const { return -1; }
+ };
+
+ // The underlying hardware composer layer is supplied buffers either from a
+ // surface buffer train or from a buffer directly.
+ pdx::rpc::Variant<SourceSurface, SourceBuffer> source_;
+
+ pdx::LocalHandle acquire_fence_;
+ bool surface_rect_functions_applied_ = false;
Layer(const Layer&) = delete;
void operator=(const Layer&) = delete;
@@ -186,13 +237,15 @@
public:
// Type for vsync callback.
using VSyncCallback = std::function<void(int, int64_t, int64_t, uint32_t)>;
+ using RequestDisplayCallback = std::function<void(bool)>;
// Since there is no universal way to query the number of hardware layers,
// just set it to 4 for now.
- static constexpr int kMaxHardwareLayers = 4;
+ static constexpr size_t kMaxHardwareLayers = 4;
HardwareComposer();
- HardwareComposer(Hwc2::Composer* hidl);
+ HardwareComposer(Hwc2::Composer* hidl,
+ RequestDisplayCallback request_display_callback);
~HardwareComposer();
bool Initialize();
@@ -207,14 +260,14 @@
void Disable();
// Get the HMD display metrics for the current display.
- DisplayMetrics GetHmdDisplayMetrics() const;
+ display::Metrics GetHmdDisplayMetrics() const;
- int32_t GetDisplayAttribute(hwc2_display_t display, hwc2_config_t config,
- hwc2_attribute_t attributes,
- int32_t* out_value) const;
- int32_t GetDisplayMetrics(hwc2_display_t display, hwc2_config_t config,
- HWCDisplayMetrics* out_metrics) const;
- void Dump(char* buffer, uint32_t* out_size);
+ HWC::Error GetDisplayAttribute(hwc2_display_t display, hwc2_config_t config,
+ hwc2_attribute_t attributes,
+ int32_t* out_value) const;
+ HWC::Error GetDisplayMetrics(hwc2_display_t display, hwc2_config_t config,
+ HWCDisplayMetrics* out_metrics) const;
+ std::string Dump();
void SetVSyncCallback(VSyncCallback callback);
@@ -229,11 +282,9 @@
return native_display_metrics_;
}
- // Set the display surface stack to compose to the display each frame.
+ // Sets the display surfaces to compose the hardware layer stack.
void SetDisplaySurfaces(
- std::vector<std::shared_ptr<DisplaySurface>> surfaces);
-
- Compositor* GetCompositor() { return &compositor_; }
+ std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces);
void OnHardwareComposerRefresh();
@@ -265,23 +316,36 @@
}
};
- int32_t Validate(hwc2_display_t display);
- int32_t Present(hwc2_display_t display);
+ HWC::Error Validate(hwc2_display_t display);
+ HWC::Error Present(hwc2_display_t display);
void SetBacklightBrightness(int brightness);
- void PostLayers(bool is_geometry_changed);
+ void PostLayers();
void PostThread();
- // Check to see if we have a value written to post_thread_interrupt_event_fd_,
- // indicating a control thread interrupted the post thread. This clears the
- // post_thread_interrupt_event_fd_ state in the process. Returns true if an
- // interrupt was requested.
- bool CheckPostThreadInterruptEventFd();
+ // The post thread has two controlling states:
+ // 1. Idle: no work to do (no visible surfaces).
+ // 2. Suspended: explicitly halted (system is not in VR mode).
+ // When either #1 or #2 is true then the post thread is quiescent, otherwise
+ // it is active.
+ using PostThreadStateType = uint32_t;
+ struct PostThreadState {
+ enum : PostThreadStateType {
+ Active = 0,
+ Idle = (1 << 0),
+ Suspended = (1 << 1),
+ Quit = (1 << 2),
+ };
+ };
+
+ void UpdatePostThreadState(uint32_t state, bool suspend);
+
// Blocks until either event_fd becomes readable, or we're interrupted by a
// control thread. Any errors are returned as negative errno values. If we're
// interrupted, kPostThreadInterrupted will be returned.
- int PostThreadPollInterruptible(int event_fd, int requested_events);
+ int PostThreadPollInterruptible(const pdx::LocalHandle& event_fd,
+ int requested_events);
// BlockUntilVSync, WaitForVSync, and SleepUntil are all blocking calls made
// on the post thread that can be interrupted by a control thread. If
@@ -294,49 +358,21 @@
bool IsFramePendingInDriver() { return ReadWaitPPState() == 1; }
- // Returns true if the layer config changed, false otherwise
+ // Reconfigures the layer stack if the display surfaces changed since the last
+ // frame. Called only from the post thread.
bool UpdateLayerConfig();
- void PostCompositorBuffers();
-
- // Return true if the post thread has work to do (i.e. there are visible
- // surfaces to post to the screen). Must be called with post_thread_mutex_
- // locked. Called only from the post thread.
- bool PostThreadHasWork();
// Called on the post thread when the post thread is resumed.
void OnPostThreadResumed();
// Called on the post thread when the post thread is paused or quits.
void OnPostThreadPaused();
- struct FrameTimeMeasurementRecord {
- int64_t start_time;
- pdx::LocalHandle fence;
-
- FrameTimeMeasurementRecord(FrameTimeMeasurementRecord&&) = default;
- FrameTimeMeasurementRecord& operator=(FrameTimeMeasurementRecord&&) =
- default;
- FrameTimeMeasurementRecord(const FrameTimeMeasurementRecord&) = delete;
- FrameTimeMeasurementRecord& operator=(const FrameTimeMeasurementRecord&) =
- delete;
- };
-
- void UpdateFrameTimeHistory(std::vector<FrameTimeMeasurementRecord>* backlog,
- int backlog_max,
- FenceInfoBuffer* fence_info_buffer,
- FrameTimeHistory* history);
-
- // Returns true if the frame finished rendering, false otherwise. If the frame
- // finished the frame end time is stored in timestamp. Doesn't block.
- bool CheckFrameFinished(int frame_fence_fd,
- FenceInfoBuffer* fence_info_buffer,
- int64_t* timestamp);
-
- void HandlePendingScreenshots();
-
bool initialized_;
- // Hardware composer HAL device.
- std::unique_ptr<Hwc2::Composer> hwc2_hidl_;
+ // Hardware composer HAL device from SurfaceFlinger. VrFlinger does not own
+ // this pointer.
+ Hwc2::Composer* hwc2_hidl_;
+ RequestDisplayCallback request_display_callback_;
sp<ComposerCallback> callbacks_;
// Display metrics of the physical display.
@@ -345,69 +381,39 @@
// landscape.
HWCDisplayMetrics display_metrics_;
// Transform required to get from native to logical display orientation.
- hwc_transform_t display_transform_;
+ HWC::Transform display_transform_ = HWC::Transform::None;
// Buffer for the background layer required by hardware composer.
std::shared_ptr<IonBuffer> framebuffer_target_;
- // Protects access to variables used by the post thread and one of the control
- // threads (either the vr flinger dispatcher thread or the surface flinger
- // main thread). This includes active_surfaces_, active_surfaces_updated_,
- // post_thread_enabled_, post_thread_running_, and
- // post_thread_quit_requested_.
- std::mutex post_thread_mutex_;
-
- // Surfaces configured by the display manager. Written by the vr flinger
- // dispatcher thread, read by the post thread.
- std::vector<std::shared_ptr<DisplaySurface>> active_surfaces_;
- // active_surfaces_updated_ is set to true by the vr flinger dispatcher thread
- // when the list of active surfaces changes. active_surfaces_updated_ will be
- // set back to false by the post thread when it processes the update.
- bool active_surfaces_updated_;
+ // Pending surface list. Set by the display service when DirectSurfaces are
+ // added, removed, or change visibility. Written by the message dispatch
+ // thread and read by the post thread.
+ std::vector<std::shared_ptr<DirectDisplaySurface>> pending_surfaces_;
// The surfaces displayed by the post thread. Used exclusively by the post
// thread.
- std::vector<std::shared_ptr<DisplaySurface>> display_surfaces_;
-
- // The surfaces rendered by the compositor. Used exclusively by the post
- // thread.
- std::vector<std::shared_ptr<DisplaySurface>> compositor_surfaces_;
+ std::vector<std::shared_ptr<DirectDisplaySurface>> display_surfaces_;
// Layer array for handling buffer flow into hardware composer layers.
- // Note that the first array is the actual storage for the layer objects,
- // and the latter is an array of pointers, which can be freely re-arranged
- // without messing up the underlying objects.
- std::array<Layer, kMaxHardwareLayers> layer_storage_;
- std::array<Layer*, kMaxHardwareLayers> layers_;
- size_t active_layer_count_;
-
- // Set by the Post thread to the index of the GPU compositing output
- // buffer in the layers_ array.
- Layer* gpu_layer_;
+ std::array<Layer, kMaxHardwareLayers> layers_;
+ size_t active_layer_count_ = 0;
// Handler to hook vsync events outside of this class.
VSyncCallback vsync_callback_;
// The layer posting thread. This thread wakes up a short time before vsync to
- // hand buffers to post processing and the results to hardware composer.
+ // hand buffers to hardware composer.
std::thread post_thread_;
- // Set to true if the post thread is allowed to run. Surface flinger and vr
- // flinger share access to the display, and vr flinger shouldn't use the
- // display while surface flinger is using it. While surface flinger owns the
- // display, post_thread_enabled_ will be set to false to indicate the post
- // thread shouldn't run.
- bool post_thread_enabled_;
- // Set to true by the post thread if it's currently running.
- bool post_thread_running_;
- // Set to true if the post thread should quit. Only set when destroying the
- // HardwareComposer instance.
- bool post_thread_quit_requested_;
- // Used to wake the post thread up while it's waiting for vsync or sleeping
- // until EDS preemption, for faster transition to the paused state.
- pdx::LocalHandle post_thread_interrupt_event_fd_;
- // Used to communicate between the control thread and the post thread.
- std::condition_variable post_thread_cond_var_;
+ // Post thread state machine and synchronization primitives.
+ PostThreadStateType post_thread_state_{PostThreadState::Idle};
+ std::atomic<bool> post_thread_quiescent_{true};
+ bool post_thread_resumed_{false};
+ pdx::LocalHandle post_thread_event_fd_;
+ std::mutex post_thread_mutex_;
+ std::condition_variable post_thread_wait_;
+ std::condition_variable post_thread_ready_;
// Backlight LED brightness sysfs node.
pdx::LocalHandle backlight_brightness_fd_;
@@ -422,16 +428,13 @@
pdx::LocalHandle vsync_sleep_timer_fd_;
// The timestamp of the last vsync.
- int64_t last_vsync_timestamp_;
+ int64_t last_vsync_timestamp_ = 0;
// Vsync count since display on.
- uint32_t vsync_count_;
+ uint32_t vsync_count_ = 0;
// Counter tracking the number of skipped frames.
- int frame_skip_count_;
-
- // After construction, only accessed on post_thread_.
- Compositor compositor_;
+ int frame_skip_count_ = 0;
// Fd array for tracking retire fences that are returned by hwc. This allows
// us to detect when the display driver begins queuing frames.
@@ -439,16 +442,7 @@
// Pose client for frame count notifications. Pose client predicts poses
// out to display frame boundaries, so we need to tell it about vsyncs.
- DvrPose* pose_client_;
-
- // Our history of frame times. This is used to get a better estimate of how
- // long the next frame will take, to set a schedule for EDS.
- FrameTimeHistory frame_time_history_;
-
- // The backlog is used to allow us to start rendering the next frame before
- // the previous frame has finished, and still get an accurate measurement of
- // frame duration.
- std::vector<FrameTimeMeasurementRecord> frame_time_backlog_;
+ DvrPose* pose_client_ = nullptr;
static constexpr int kPostThreadInterrupted = 1;
diff --git a/libs/vr/libvrflinger/hwc_types.h b/libs/vr/libvrflinger/hwc_types.h
new file mode 100644
index 0000000..cbf636c
--- /dev/null
+++ b/libs/vr/libvrflinger/hwc_types.h
@@ -0,0 +1,300 @@
+#ifndef ANDROID_LIBVRFLINGER_HWCTYPES_H
+#define ANDROID_LIBVRFLINGER_HWCTYPES_H
+
+// General HWC type support. Hardware composer type support is a bit of a mess
+// between HWC1, HWC2 C/C++11, and HIDL types. Particularly bothersome is the
+// use of enum classes, which make analogous types between versions much
+// harder to deal with in a uniform way.
+//
+// These utilities help address some of these pains by providing a type-safe,
+// flexible interface to translate between different type spaces.
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include <string>
+#include <type_traits>
+
+namespace HWC {
+
+// Value types derived from HWC HAL types. Some of these are stand-alone,
+// while others are also wrapped in translator classes below.
+using ColorMode = int32_t; // android_color_mode_t;
+using Config = hwc2_config_t;
+using ColorTransform =
+ std::underlying_type<android_color_transform_t>::type; // int32_t;
+using Dataspace = std::underlying_type<android_dataspace_t>::type; // int32_t;
+using DisplayId = hwc2_display_t;
+using DisplayRequest = std::underlying_type<HWC2::DisplayRequest>::type;
+using Hdr = std::underlying_type<android_hdr_t>::type; // int32_t;
+using Layer = hwc2_layer_t;
+using PixelFormat =
+ std::underlying_type<android_pixel_format_t>::type; // int32_t;
+
+// Type traits and casting utilities.
+
+// SFINAE utility to evaluate type expressions.
+template <typename...>
+using TestTypeExpression = void;
+
+// Traits type to determine the underlying type of an enum, integer,
+// or wrapper class.
+template <typename T, typename = typename std::is_enum<T>::type,
+ typename = typename std::is_integral<T>::type, typename = void>
+struct UnderlyingType {
+ using Type = T;
+};
+// Partial specialization that matches enum types. Captures the underlying type
+// of the enum in member type Type.
+template <typename T>
+struct UnderlyingType<T, std::true_type, std::false_type> {
+ using Type = typename std::underlying_type<T>::type;
+};
+// Partial specialization that matches integral types. Captures the type of the
+// integer in member type Type.
+template <typename T>
+struct UnderlyingType<T, std::false_type, std::true_type> {
+ using Type = T;
+};
+// Partial specialization that matches the wrapper types below. Captures
+// wrapper member type ValueType in member type Type.
+template <typename T>
+struct UnderlyingType<T, std::false_type, std::false_type,
+ TestTypeExpression<typename T::ValueType>> {
+ using Type = typename T::ValueType;
+};
+
+// Enable if T is an enum with underlying type U.
+template <typename T, typename U, typename ReturnType = void>
+using EnableIfMatchingEnum = typename std::enable_if<
+ std::is_enum<T>::value &&
+ std::is_same<U, typename UnderlyingType<T>::Type>::value,
+ ReturnType>::type;
+
+// Enable if T and U are the same size/alignment and have the same underlying
+// type. Handles enum, integral, and wrapper classes below.
+template <typename T, typename U, typename Return = void>
+using EnableIfSafeCast = typename std::enable_if<
+ sizeof(T) == sizeof(U) && alignof(T) == alignof(U) &&
+ std::is_same<typename UnderlyingType<T>::Type,
+ typename UnderlyingType<U>::Type>::value,
+ Return>::type;
+
+// Safely cast between std::vectors of matching enum/integer/wraper types.
+// Normally this is not possible with pendantic compiler type checks. However,
+// given the same size, alignment, and underlying type this is safe due to
+// allocator requirements and array-like element access guarantees.
+template <typename T, typename U>
+EnableIfSafeCast<T, U, std::vector<T>*> VectorCast(std::vector<U>* in) {
+ return reinterpret_cast<std::vector<T>*>(in);
+}
+
+// Translator classes that wrap specific HWC types to make translating
+// between different types (especially enum class) in code cleaner.
+
+// Base type for the enum wrappers below. This type provides type definitions
+// and implicit conversion logic common to each wrapper type.
+template <typename EnumType>
+struct Wrapper {
+ // Alias type of this instantiantion of Wrapper. Useful for inheriting
+ // constructors in subclasses via "using Base::Base;" statements.
+ using Base = Wrapper<EnumType>;
+
+ // The enum type wrapped by this instantiation of Wrapper.
+ using BaseType = EnumType;
+
+ // The underlying type of the base enum type.
+ using ValueType = typename UnderlyingType<BaseType>::Type;
+
+ // A default constructor is not defined here. Subclasses should define one
+ // as appropriate to define the correct inital value for the enum type.
+
+ // Default copy constructor.
+ Wrapper(const Wrapper&) = default;
+
+ // Implicit conversion from ValueType.
+ Wrapper(ValueType value) : value(value) {}
+
+ // Implicit conversion from BaseType.
+ Wrapper(BaseType value) : value(static_cast<ValueType>(value)) {}
+
+ // Implicit conversion from an enum type of the same underlying type.
+ template <typename T, typename = EnableIfMatchingEnum<T, ValueType>>
+ Wrapper(const T& value) : value(static_cast<ValueType>(value)) {}
+
+ // Implicit conversion to BaseType.
+ operator BaseType() const { return static_cast<BaseType>(value); }
+
+ // Implicit conversion to ValueType.
+ operator ValueType() const { return value; }
+
+ template <typename T, typename = EnableIfMatchingEnum<T, ValueType>>
+ T cast() const {
+ return static_cast<T>(value);
+ }
+
+ // Converts to string using HWC2 stringification of BaseType.
+ std::string to_string() const {
+ return HWC2::to_string(static_cast<BaseType>(value));
+ }
+
+ bool operator!=(const Wrapper& other) const { return value != other.value; }
+ bool operator!=(ValueType other_value) const { return value != other_value; }
+ bool operator!=(BaseType other_value) const {
+ return static_cast<BaseType>(value) != other_value;
+ }
+ bool operator==(const Wrapper& other) const { return value == other.value; }
+ bool operator==(ValueType other_value) const { return value == other_value; }
+ bool operator==(BaseType other_value) const {
+ return static_cast<BaseType>(value) == other_value;
+ }
+
+ ValueType value;
+};
+
+struct Attribute final : public Wrapper<HWC2::Attribute> {
+ enum : ValueType {
+ Invalid = HWC2_ATTRIBUTE_INVALID,
+ Width = HWC2_ATTRIBUTE_WIDTH,
+ Height = HWC2_ATTRIBUTE_HEIGHT,
+ VsyncPeriod = HWC2_ATTRIBUTE_VSYNC_PERIOD,
+ DpiX = HWC2_ATTRIBUTE_DPI_X,
+ DpiY = HWC2_ATTRIBUTE_DPI_Y,
+ };
+
+ Attribute() : Base(Invalid) {}
+ using Base::Base;
+};
+
+struct BlendMode final : public Wrapper<HWC2::BlendMode> {
+ enum : ValueType {
+ Invalid = HWC2_BLEND_MODE_INVALID,
+ None = HWC2_BLEND_MODE_NONE,
+ Premultiplied = HWC2_BLEND_MODE_PREMULTIPLIED,
+ Coverage = HWC2_BLEND_MODE_COVERAGE,
+ };
+
+ BlendMode() : Base(Invalid) {}
+ using Base::Base;
+};
+
+struct Composition final : public Wrapper<HWC2::Composition> {
+ enum : ValueType {
+ Invalid = HWC2_COMPOSITION_INVALID,
+ Client = HWC2_COMPOSITION_CLIENT,
+ Device = HWC2_COMPOSITION_DEVICE,
+ SolidColor = HWC2_COMPOSITION_SOLID_COLOR,
+ Cursor = HWC2_COMPOSITION_CURSOR,
+ Sideband = HWC2_COMPOSITION_SIDEBAND,
+ };
+
+ Composition() : Base(Invalid) {}
+ using Base::Base;
+};
+
+struct DisplayType final : public Wrapper<HWC2::DisplayType> {
+ enum : ValueType {
+ Invalid = HWC2_DISPLAY_TYPE_INVALID,
+ Physical = HWC2_DISPLAY_TYPE_PHYSICAL,
+ Virtual = HWC2_DISPLAY_TYPE_VIRTUAL,
+ };
+
+ DisplayType() : Base(Invalid) {}
+ using Base::Base;
+};
+
+struct Error final : public Wrapper<HWC2::Error> {
+ enum : ValueType {
+ None = HWC2_ERROR_NONE,
+ BadConfig = HWC2_ERROR_BAD_CONFIG,
+ BadDisplay = HWC2_ERROR_BAD_DISPLAY,
+ BadLayer = HWC2_ERROR_BAD_LAYER,
+ BadParameter = HWC2_ERROR_BAD_PARAMETER,
+ HasChanges = HWC2_ERROR_HAS_CHANGES,
+ NoResources = HWC2_ERROR_NO_RESOURCES,
+ NotValidated = HWC2_ERROR_NOT_VALIDATED,
+ Unsupported = HWC2_ERROR_UNSUPPORTED,
+ };
+
+ Error() : Base(None) {}
+ using Base::Base;
+};
+
+struct LayerRequest final : public Wrapper<HWC2::LayerRequest> {
+ enum : ValueType {
+ ClearClientTarget = HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET,
+ };
+
+ LayerRequest() : Base(0) {}
+ using Base::Base;
+};
+
+struct PowerMode final : public Wrapper<HWC2::PowerMode> {
+ enum : ValueType {
+ Off = HWC2_POWER_MODE_OFF,
+ DozeSuspend = HWC2_POWER_MODE_DOZE_SUSPEND,
+ Doze = HWC2_POWER_MODE_DOZE,
+ On = HWC2_POWER_MODE_ON,
+ };
+
+ PowerMode() : Base(Off) {}
+ using Base::Base;
+};
+
+struct Transform final : public Wrapper<HWC2::Transform> {
+ enum : ValueType {
+ None = 0,
+ FlipH = HWC_TRANSFORM_FLIP_H,
+ FlipV = HWC_TRANSFORM_FLIP_V,
+ Rotate90 = HWC_TRANSFORM_ROT_90,
+ Rotate180 = HWC_TRANSFORM_ROT_180,
+ Rotate270 = HWC_TRANSFORM_ROT_270,
+ FlipHRotate90 = HWC_TRANSFORM_FLIP_H_ROT_90,
+ FlipVRotate90 = HWC_TRANSFORM_FLIP_V_ROT_90,
+ };
+
+ Transform() : Base(None) {}
+ using Base::Base;
+};
+
+struct Vsync final : public Wrapper<HWC2::Vsync> {
+ enum : ValueType {
+ Invalid = HWC2_VSYNC_INVALID,
+ Enable = HWC2_VSYNC_ENABLE,
+ Disable = HWC2_VSYNC_DISABLE,
+ };
+
+ Vsync() : Base(Invalid) {}
+ using Base::Base;
+};
+
+// Utility color type.
+struct Color final {
+ Color(const Color&) = default;
+ Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : r(r), g(g), b(b), a(a) {}
+ Color(hwc_color_t color) : r(color.r), g(color.g), b(color.b), a(color.a) {}
+
+ operator hwc_color_t() const { return {r, g, b, a}; }
+
+ uint8_t r __attribute__((aligned(1)));
+ uint8_t g __attribute__((aligned(1)));
+ uint8_t b __attribute__((aligned(1)));
+ uint8_t a __attribute__((aligned(1)));
+};
+
+// Utility rectangle type.
+struct Rect final {
+ // TODO(eieio): Implicit conversion to/from Android rect types.
+
+ int32_t left __attribute__((aligned(4)));
+ int32_t top __attribute__((aligned(4)));
+ int32_t right __attribute__((aligned(4)));
+ int32_t bottom __attribute__((aligned(4)));
+};
+
+} // namespace HWC
+
+#endif // ANDROID_LIBVRFLINGER_HWCTYPES_H
diff --git a/libs/vr/libvrflinger/screenshot_service.cpp b/libs/vr/libvrflinger/screenshot_service.cpp
deleted file mode 100644
index d14d588..0000000
--- a/libs/vr/libvrflinger/screenshot_service.cpp
+++ /dev/null
@@ -1,189 +0,0 @@
-#include "screenshot_service.h"
-
-#include <utils/Trace.h>
-
-#include <pdx/default_transport/service_endpoint.h>
-#include <private/android_filesystem_config.h>
-#include <private/dvr/display_types.h>
-#include <private/dvr/trusted_uids.h>
-
-using android::pdx::Message;
-using android::pdx::MessageInfo;
-using android::pdx::default_transport::Endpoint;
-using android::pdx::rpc::DispatchRemoteMethod;
-using android::pdx::rpc::RemoteMethodError;
-using android::pdx::rpc::RemoteMethodReturn;
-
-namespace android {
-namespace dvr {
-
-ScreenshotService::~ScreenshotService() { instance_ = nullptr; }
-
-pdx::Status<void> ScreenshotService::HandleMessage(pdx::Message& message) {
- switch (message.GetOp()) {
- case DisplayScreenshotRPC::GetFormat::Opcode:
- DispatchRemoteMethod<DisplayScreenshotRPC::GetFormat>(
- *this, &ScreenshotService::OnGetFormat, message);
- return {};
-
- case DisplayScreenshotRPC::TakeScreenshot::Opcode:
- DispatchRemoteMethod<DisplayScreenshotRPC::TakeScreenshot>(
- *this, &ScreenshotService::OnTakeScreenshot, message);
- return {};
-
- default:
- return Service::HandleMessage(message);
- }
-}
-
-int ScreenshotService::OnGetFormat(pdx::Message&) {
- return HAL_PIXEL_FORMAT_RGB_888;
-}
-
-ScreenshotData ScreenshotService::OnTakeScreenshot(pdx::Message& message,
- int layer_index) {
- // Also allow AID_SHELL to support vrscreencap commands.
- if (message.GetEffectiveUserId() != AID_SHELL &&
- !IsTrustedUid(message.GetEffectiveUserId())) {
- REPLY_ERROR_RETURN(message, EACCES, {});
- }
-
- AddWaiter(std::move(message), layer_index);
- return {};
-}
-
-void ScreenshotService::AddWaiter(pdx::Message&& message, int layer_index) {
- std::lock_guard<std::mutex> lock(mutex_);
- waiters_.emplace_back(std::move(message), layer_index);
-}
-
-void ScreenshotService::TakeIfNeeded(
- std::array<Layer*, HardwareComposer::kMaxHardwareLayers>& hw_layers,
- Compositor& compositor) {
- std::lock_guard<std::mutex> lock(mutex_);
-
- // Send the buffer contents to all of our waiting clients.
- for (auto& waiter : waiters_) {
- if (waiter.IsDone())
- continue;
-
- if (waiter.layer_index() == 0) {
- ALOGE(
- "ScreenshotService::TakeIfNeeded: Capturing the composited display "
- "output is not yet supported.");
-
- waiter.Error(EINVAL);
- continue;
- }
-
- if (waiter.layer_index() > 0) {
- // Check for hardware layer screenshot requests.
- // Hardware layers are requested with positive indices starting at 1.
- const size_t layer_index = static_cast<size_t>(waiter.layer_index() - 1);
-
- if (layer_index >= hw_layers.size()) {
- waiter.Error(EINVAL);
- continue;
- }
-
- auto buffer = hw_layers[layer_index]->GetBuffer();
- if (!buffer) {
- waiter.Error(ENOBUFS);
- continue;
- }
-
- auto data = compositor.ReadBufferPixels(buffer);
- if (data.empty()) {
- waiter.Error(ENOBUFS);
- continue;
- }
-
- Take(&waiter, data.data(), buffer->width(), buffer->height(),
- buffer->width());
- } else {
- // Check for compositor input layer screenshot requests.
- // Prewarp surfaces are requested with negative indices starting at -1.
- const size_t layer_index = static_cast<size_t>(-waiter.layer_index() - 1);
-
- if (layer_index >= compositor.GetLayerCount()) {
- waiter.Error(EINVAL);
- continue;
- }
-
- int width = 0;
- int height = 0;
- auto data = compositor.ReadLayerPixels(layer_index, &width, &height);
- if (data.empty()) {
- waiter.Error(ENOBUFS);
- continue;
- }
-
- Take(&waiter, data.data(), width, height, width);
- }
- }
-
- // Reply with error to requests that did not match up with a source layer.
- for (auto& waiter : waiters_) {
- if (!waiter.IsDone())
- waiter.Error(EAGAIN);
- }
- waiters_.clear();
-}
-
-void ScreenshotWaiter::Reply(const ScreenshotData& screenshot) {
- ALOGI("Returning screenshot: size=%zu recv_size=%zu",
- screenshot.buffer.size(), message_.GetReceiveLength());
- RemoteMethodReturn<DisplayScreenshotRPC::TakeScreenshot>(message_,
- screenshot);
-}
-
-void ScreenshotWaiter::Error(int error) { RemoteMethodError(message_, error); }
-
-void ScreenshotService::Take(ScreenshotWaiter* waiter, const void* rgba_data,
- int32_t width, int32_t height, int buffer_stride) {
- ATRACE_NAME(__PRETTY_FUNCTION__);
-
- bool is_portrait = height > width;
- if (is_portrait) {
- std::swap(width, height);
- }
- int response_stride = width;
-
- // Convert from RGBA to RGB and if in portrait, rotates to landscape; store
- // the result in the response buffer.
- ScreenshotData screenshot{width, height,
- std::vector<uint8_t>(width * height * 3)};
-
- const auto rgba_bytes = static_cast<const uint8_t*>(rgba_data);
- for (int j = 0; j < height; ++j) {
- for (int i = 0; i < width; ++i) {
- // If the screenshot is in portrait mode, rotate into landscape mode.
- const int response_index = is_portrait
- ? (height - j - 1) * response_stride + i
- : j * response_stride + i;
- const int buffer_index =
- is_portrait ? i * buffer_stride + j : j * buffer_stride + i;
- screenshot.buffer[response_index * 3 + 0] =
- rgba_bytes[buffer_index * 4 + 0];
- screenshot.buffer[response_index * 3 + 1] =
- rgba_bytes[buffer_index * 4 + 1];
- screenshot.buffer[response_index * 3 + 2] =
- rgba_bytes[buffer_index * 4 + 2];
- }
- }
-
- waiter->Reply(screenshot);
-}
-
-ScreenshotService::ScreenshotService()
- : BASE("ScreenshotService",
- Endpoint::Create(DisplayScreenshotRPC::kClientPath)) {
- instance_ = this;
-}
-
-ScreenshotService* ScreenshotService::GetInstance() { return instance_; }
-
-ScreenshotService* ScreenshotService::instance_ = nullptr;
-
-} // namespace dvr
-} // namespace android
diff --git a/libs/vr/libvrflinger/screenshot_service.h b/libs/vr/libvrflinger/screenshot_service.h
deleted file mode 100644
index f59e872..0000000
--- a/libs/vr/libvrflinger/screenshot_service.h
+++ /dev/null
@@ -1,82 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_SCREENSHOT_SERVICE_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_SCREENSHOT_SERVICE_H_
-
-#include <pdx/rpc/pointer_wrapper.h>
-#include <pdx/service.h>
-#include <private/dvr/ion_buffer.h>
-
-#include <mutex>
-#include <vector>
-
-#include "hardware_composer.h"
-
-namespace android {
-namespace dvr {
-
-class ScreenshotWaiter {
- public:
- explicit ScreenshotWaiter(pdx::Message&& message, int layer_index)
- : message_(std::move(message)), layer_index_(layer_index) {}
- ScreenshotWaiter(ScreenshotWaiter&&) = default;
-
- void Reply(const ScreenshotData& screenshot);
- void Error(int error);
-
- bool IsDone() const { return message_.replied(); }
- int layer_index() const { return layer_index_; }
-
- private:
- pdx::Message message_;
- int layer_index_;
-
- ScreenshotWaiter(const ScreenshotWaiter&) = delete;
- void operator=(const ScreenshotWaiter&) = delete;
-};
-
-// The screenshot service allows clients to obtain screenshots from displayd.
-class ScreenshotService : public pdx::ServiceBase<ScreenshotService> {
- public:
- ~ScreenshotService();
-
- pdx::Status<void> HandleMessage(pdx::Message& message) override;
-
- // Returns true if there is a pending screenshot request.
- bool IsScreenshotRequestPending() const {
- std::lock_guard<std::mutex> lock(mutex_);
- return !waiters_.empty();
- }
-
- // If any clients are currently waiting for a screenshot, read back the
- // contents of requested layers and send the resulting
- // image to the clients.
- void TakeIfNeeded(
- std::array<Layer*, HardwareComposer::kMaxHardwareLayers>& hw_layers,
- Compositor& compositor);
-
- static ScreenshotService* GetInstance();
-
- private:
- friend BASE;
-
- ScreenshotService();
-
- void AddWaiter(pdx::Message&& message, int layer_index);
-
- ScreenshotData OnTakeScreenshot(pdx::Message& message, int index);
- int OnGetFormat(pdx::Message& message);
-
- // Copy the given screenshot data into the message reply.
- void Take(ScreenshotWaiter* waiter, const void* rgba_data, int32_t width,
- int32_t height, int buffer_stride);
-
- static ScreenshotService* instance_;
-
- // Protects access to subsequent member variables.
- mutable std::mutex mutex_;
- std::vector<ScreenshotWaiter> waiters_;
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_SERVICES_DISPLAYD_SCREENSHOT_SERVICE_H_
diff --git a/libs/vr/libvrflinger/surface_channel.cpp b/libs/vr/libvrflinger/surface_channel.cpp
deleted file mode 100644
index 263b382..0000000
--- a/libs/vr/libvrflinger/surface_channel.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "surface_channel.h"
-
-using android::pdx::BorrowedChannelHandle;
-using android::pdx::Message;
-using android::pdx::rpc::DispatchRemoteMethod;
-
-namespace android {
-namespace dvr {
-
-pdx::Status<void> SurfaceChannel::HandleMessage(Message& message) {
- switch (message.GetOp()) {
- case DisplayRPC::GetMetadataBuffer::Opcode:
- DispatchRemoteMethod<DisplayRPC::GetMetadataBuffer>(
- *this, &SurfaceChannel::OnGetMetadataBuffer, message);
- break;
- }
-
- return {};
-}
-
-BorrowedChannelHandle SurfaceChannel::OnGetMetadataBuffer(Message& message) {
- if (EnsureMetadataBuffer()) {
- return metadata_buffer_->GetChannelHandle().Borrow();
- } else {
- REPLY_ERROR_RETURN(message, -ENOMEM, {});
- }
-}
-
-bool SurfaceChannel::EnsureMetadataBuffer() {
- if (!metadata_buffer_) {
- metadata_buffer_ =
- BufferProducer::CreateUncachedBlob(metadata_size());
- if (!metadata_buffer_) {
- ALOGE(
- "DisplaySurface::EnsureMetadataBuffer: could not allocate metadata "
- "buffer");
- return false;
- }
- }
- return true;
-}
-
-} // namespace dvr
-} // namespace android
diff --git a/libs/vr/libvrflinger/surface_channel.h b/libs/vr/libvrflinger/surface_channel.h
deleted file mode 100644
index bb6b1c5..0000000
--- a/libs/vr/libvrflinger/surface_channel.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_SURFACE_CHANNEL_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_SURFACE_CHANNEL_H_
-
-#include <pdx/service.h>
-#include <private/dvr/buffer_hub_client.h>
-#include <private/dvr/display_rpc.h>
-
-namespace android {
-namespace dvr {
-
-class DisplayService;
-
-class SurfaceChannel : public pdx::Channel {
- public:
- SurfaceChannel(DisplayService* service, int channel_id, SurfaceType type,
- size_t metadata_size)
- : service_(service),
- surface_id_(channel_id),
- type_(type),
- metadata_size_(metadata_size) {}
-
- ~SurfaceChannel() override = default;
-
- DisplayService* service() const { return service_; }
- int surface_id() const { return surface_id_; }
- SurfaceType type() const { return type_; }
- size_t metadata_size() const { return metadata_size_; }
-
- pdx::LocalHandle GetMetadataBufferFd() {
- return EnsureMetadataBuffer() ? metadata_buffer_->GetBlobFd()
- : pdx::LocalHandle{};
- }
-
- // Dispatches surface channel messages to the appropriate handlers. This
- // handler runs on the displayd message dispatch thread.
- virtual pdx::Status<void> HandleMessage(pdx::Message& message);
-
- protected:
- // Contains the surface metadata.
- std::shared_ptr<BufferProducer> metadata_buffer_;
-
- // Returns the metadata buffer for this surface. The first call allocates the
- // buffer, while subsequent calls return the same buffer.
- pdx::BorrowedChannelHandle OnGetMetadataBuffer(pdx::Message& message);
-
- // Allocates the single metadata buffer for this surface unless it is already
- // allocated. Idempotent when called multiple times.
- bool EnsureMetadataBuffer();
-
- private:
- DisplayService* service_;
- int surface_id_;
- SurfaceType type_;
- size_t metadata_size_;
-
- SurfaceChannel(const SurfaceChannel&) = delete;
- void operator=(const SurfaceChannel&) = delete;
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_SERVICES_DISPLAYD_SURFACE_CHANNEL_H_
diff --git a/libs/vr/libvrflinger/video_compositor.cpp b/libs/vr/libvrflinger/video_compositor.cpp
deleted file mode 100644
index c5a5b64..0000000
--- a/libs/vr/libvrflinger/video_compositor.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-#include "video_compositor.h"
-
-#include <EGL/eglext.h>
-#include <GLES2/gl2ext.h>
-
-#include <private/dvr/debug.h>
-#include <private/dvr/display_rpc.h>
-
-namespace android {
-namespace dvr {
-
-VideoCompositor::Texture::Texture(
- EGLDisplay display, const std::shared_ptr<BufferConsumer>& buffer_consumer)
- : display_(display),
- image_(EGL_NO_IMAGE_KHR),
- texture_id_(0),
- buffer_consumer_(buffer_consumer) {}
-
-VideoCompositor::Texture::~Texture() {
- if (image_ != EGL_NO_IMAGE_KHR)
- eglDestroyImageKHR(display_, image_);
- if (texture_id_ != 0)
- glDeleteTextures(1, &texture_id_);
-}
-
-GLuint VideoCompositor::Texture::EnsureTextureReady() {
- if (!image_) {
- native_buffer_ = new NativeBuffer(buffer_consumer_);
- CHECK_GL();
-
- image_ = eglCreateImageKHR(
- display_, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
- static_cast<ANativeWindowBuffer*>(native_buffer_.get()), nullptr);
- if (!image_) {
- ALOGE("Failed to create EGLImage.");
- return 0;
- }
-
- glGenTextures(1, &texture_id_);
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id_);
- glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image_);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S,
- GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T,
- GL_CLAMP_TO_EDGE);
- CHECK_GL();
- }
-
- return texture_id_;
-}
-
-void VideoCompositor::Texture::Release() {
- const int ret = buffer_consumer_->Release({});
- if (ret < 0) {
- ALOGE(
- "VideoCompositor::Texture::Release: Failed to release buffer, error: "
- "%s",
- strerror(-ret));
- }
-}
-
-VideoCompositor::VideoCompositor(
- const std::shared_ptr<VideoMeshSurface>& surface,
- const volatile DisplaySurfaceMetadata* display_surface_metadata)
- : surface_(surface),
- consumer_queue_(surface->GetConsumerQueue()),
- transform_metadata_(display_surface_metadata),
- active_texture_slot_(-1) {}
-
-GLuint VideoCompositor::GetActiveTextureId(EGLDisplay display) {
- size_t slot;
- BufferHubQueueCore::NativeBufferMetadata metadata;
-
- while (true) {
- // A native way to pick the active texture: always dequeue all buffers from
- // the queue until it's empty. This works well as long as video frames are
- // queued in order from the producer side.
- // TODO(jwcai) Use |metadata.timestamp_ns| to schedule video frames
- // accurately.
- LocalHandle acquire_fence;
- auto buffer_consumer =
- consumer_queue_->Dequeue(0, &slot, &metadata, &acquire_fence);
-
- if (buffer_consumer) {
- // Create a new texture if it hasn't been created yet, or the same slot
- // has a new |buffer_consumer|.
- if (textures_[slot] == nullptr ||
- textures_[slot]->event_fd() != buffer_consumer->event_fd()) {
- textures_[slot] =
- std::unique_ptr<Texture>(new Texture(display, buffer_consumer));
- }
-
- if (active_texture_slot_ != static_cast<int>(slot)) {
- if (active_texture_slot_ >= 0) {
- // Release the last active texture and move on to use the new one.
- textures_[active_texture_slot_]->Release();
- }
- active_texture_slot_ = slot;
- }
- } else {
- break;
- }
- }
-
- if (active_texture_slot_ < 0) {
- // No texture is active yet.
- return 0;
- }
-
- return textures_[active_texture_slot_]->EnsureTextureReady();
-}
-
-mat4 VideoCompositor::GetTransform(int eye, size_t render_buffer_index) {
- volatile const VideoMeshSurfaceMetadata* transform_metadata =
- surface_->GetMetadataBufferPtr();
-
- mat4 screen_transform;
- for (int i = 0; i < 4; ++i) {
- for (int j = 0; j < 4; ++j) {
- screen_transform(i, j) =
- transform_metadata->transform[render_buffer_index][eye].val[i][j];
- }
- }
-
- return screen_transform;
-}
-
-} // namespace dvr
-} // namespace android
diff --git a/libs/vr/libvrflinger/video_compositor.h b/libs/vr/libvrflinger/video_compositor.h
deleted file mode 100644
index d0e72e1..0000000
--- a/libs/vr/libvrflinger/video_compositor.h
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_VIDEO_COMPOSITOR_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_VIDEO_COMPOSITOR_H_
-
-#include <EGL/egl.h>
-#include <GLES2/gl2.h>
-#include <private/dvr/buffer_hub_queue_core.h>
-#include <private/dvr/types.h>
-
-#include <vector>
-
-#include "display_surface.h"
-#include "video_mesh_surface.h"
-
-namespace android {
-namespace dvr {
-
-using pdx::LocalHandle;
-
-// Manages video buffer consumers, texture mapping, and playback timing.
-class VideoCompositor {
- public:
- VideoCompositor(
- const std::shared_ptr<VideoMeshSurface>& surface,
- const volatile DisplaySurfaceMetadata* display_surface_metadata);
-
- int surface_id() const { return surface_ ? surface_->surface_id() : -1; }
-
- // Returns a GL texture id that should be composited by displayd during the
- // current rendering loop. Note that this function must be called in
- // displayd's GL context.
- GLuint GetActiveTextureId(EGLDisplay display);
-
- // Returns a basic video mesh tranform.
- mat4 GetTransform(int eye, size_t render_buffer_index);
-
- private:
- class Texture {
- public:
- Texture(EGLDisplay display,
- const std::shared_ptr<BufferConsumer>& buffer_consumer);
- ~Texture();
-
- // Returns the |event_fd| of the underlying buffer consumer. Caller can use
- // this to decided whether the Texture need to be recreated for a different
- // buffer consumer.
- int event_fd() const { return buffer_consumer_->event_fd(); }
-
- // Method to map a dvr::BufferConsumer to a GL texture within the current GL
- // context. If the current Texture object's |image_| hasn't been
- // initialized, the method will do so based on the |buffer_consumer| and a
- // new GL texture will be generated, cached, and returned. Otherwise, the
- // cached |texture_id_| will be returned directly.
- GLuint EnsureTextureReady();
-
- // Signal bufferhub that the texture is done rendering so that the buffer
- // can be re-gained by the producer for future use.
- void Release();
-
- private:
- using NativeBuffer = BufferHubQueueCore::NativeBuffer;
-
- EGLDisplay display_;
- EGLImageKHR image_;
- GLuint texture_id_;
- sp<NativeBuffer> native_buffer_;
- std::shared_ptr<BufferConsumer> buffer_consumer_;
- };
-
- std::shared_ptr<VideoMeshSurface> surface_;
- std::shared_ptr<ConsumerQueue> consumer_queue_;
- std::array<std::unique_ptr<Texture>, BufferHubQueue::kMaxQueueCapacity>
- textures_;
-
- const volatile DisplaySurfaceMetadata* transform_metadata_;
- int active_texture_slot_;
-
- VideoCompositor(const VideoCompositor&) = delete;
- void operator=(const VideoCompositor&) = delete;
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_SERVICES_DISPLAYD_VIDEO_COMPOSITOR_H_
diff --git a/libs/vr/libvrflinger/video_mesh_surface.cpp b/libs/vr/libvrflinger/video_mesh_surface.cpp
deleted file mode 100644
index ce0dfca..0000000
--- a/libs/vr/libvrflinger/video_mesh_surface.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-#include "video_mesh_surface.h"
-
-#include <private/dvr/buffer_hub_queue_core.h>
-#include <private/dvr/display_rpc.h>
-
-using android::pdx::LocalChannelHandle;
-using android::pdx::rpc::DispatchRemoteMethod;
-
-namespace android {
-namespace dvr {
-
-VideoMeshSurface::VideoMeshSurface(DisplayService* service, int surface_id)
- : SurfaceChannel(service, surface_id, SurfaceTypeEnum::VideoMesh,
- sizeof(VideoMeshSurfaceMetadata)) {}
-
-VideoMeshSurface::~VideoMeshSurface() {}
-
-pdx::Status<void> VideoMeshSurface::HandleMessage(Message& message) {
- ATRACE_NAME("VideoMeshSurface::HandleMessage");
-
- switch (message.GetOp()) {
- case DisplayRPC::VideoMeshSurfaceCreateProducerQueue::Opcode:
- DispatchRemoteMethod<DisplayRPC::VideoMeshSurfaceCreateProducerQueue>(
- *this, &VideoMeshSurface::OnCreateProducerQueue, message);
- break;
-
- default:
- return SurfaceChannel::HandleMessage(message);
- }
-
- return {};
-}
-
-std::shared_ptr<ConsumerQueue> VideoMeshSurface::GetConsumerQueue() {
- if (!consumer_queue_) {
- ALOGE(
- "VideoMeshSurface::GetConsumerQueue: consumer_queue is uninitialized.");
- }
-
- return consumer_queue_;
-}
-
-LocalChannelHandle VideoMeshSurface::OnCreateProducerQueue(Message& message) {
- ATRACE_NAME("VideoMeshSurface::OnCreateProducerQueue");
-
- if (consumer_queue_ != nullptr) {
- ALOGE(
- "VideoMeshSurface::OnCreateProducerQueue: A ProdcuerQueue has already "
- "been created and transported to VideoMeshSurfaceClient.");
- REPLY_ERROR_RETURN(message, EALREADY, {});
- }
-
- auto producer =
- ProducerQueue::Create<BufferHubQueueCore::NativeBufferMetadata>();
- consumer_queue_ = producer->CreateConsumerQueue();
-
- return std::move(producer->GetChannelHandle());
-}
-
-} // namespace dvr
-} // namespace android
diff --git a/libs/vr/libvrflinger/video_mesh_surface.h b/libs/vr/libvrflinger/video_mesh_surface.h
deleted file mode 100644
index 2c9f3e8..0000000
--- a/libs/vr/libvrflinger/video_mesh_surface.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_VIDEO_MESH_SURFACE_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_VIDEO_MESH_SURFACE_H_
-
-#include <private/dvr/buffer_hub_queue_client.h>
-
-#include "surface_channel.h"
-
-namespace android {
-namespace dvr {
-
-class DisplayService;
-
-// VideoMeshSurface takes three inputs: 1) buffers filled by Android system
-// components (e.g. MediaCodec or camera stack) other than applications' GL
-// context; 2) a 3D mesh chosen by application to define the shape of the
-// surface; 3) a transformation matrix from application to define the rotation,
-// position, and scaling of the video surface.
-class VideoMeshSurface : public SurfaceChannel {
- public:
- using Message = pdx::Message;
- using LocalChannelHandle = pdx::LocalChannelHandle;
-
- VideoMeshSurface(DisplayService* service, int channel_id);
- ~VideoMeshSurface() override;
-
- volatile const VideoMeshSurfaceMetadata* GetMetadataBufferPtr() {
- if (EnsureMetadataBuffer()) {
- void* addr = nullptr;
- metadata_buffer_->GetBlobReadWritePointer(metadata_size(), &addr);
- return static_cast<const volatile VideoMeshSurfaceMetadata*>(addr);
- } else {
- return nullptr;
- }
- }
-
- pdx::Status<void> HandleMessage(Message& message) override;
-
- std::shared_ptr<ConsumerQueue> GetConsumerQueue();
-
- private:
- LocalChannelHandle OnCreateProducerQueue(Message& message);
-
- std::shared_ptr<ConsumerQueue> consumer_queue_;
-
- VideoMeshSurface(const VideoMeshSurface&) = delete;
- void operator=(const VideoMeshSurface&) = delete;
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_SERVICES_DISPLAYD_VIDEO_MESH_SURFACE_H_
diff --git a/libs/vr/libvrflinger/vr_flinger.cpp b/libs/vr/libvrflinger/vr_flinger.cpp
index 21226db..b2dc1d8 100644
--- a/libs/vr/libvrflinger/vr_flinger.cpp
+++ b/libs/vr/libvrflinger/vr_flinger.cpp
@@ -11,9 +11,9 @@
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
-#include <log/log.h>
#include <cutils/properties.h>
#include <cutils/sched_policy.h>
+#include <log/log.h>
#include <private/dvr/display_client.h>
#include <sys/prctl.h>
#include <sys/resource.h>
@@ -25,7 +25,6 @@
#include "DisplayHardware/ComposerHal.h"
#include "display_manager_service.h"
#include "display_service.h"
-#include "screenshot_service.h"
#include "vsync_service.h"
namespace android {
@@ -77,11 +76,11 @@
request_display_callback_ = request_display_callback;
- dispatcher_ =
- android::pdx::default_transport::ServiceDispatcher::Create();
+ dispatcher_ = android::pdx::default_transport::ServiceDispatcher::Create();
CHECK_ERROR(!dispatcher_, error, "Failed to create service dispatcher.");
- display_service_ = android::dvr::DisplayService::Create(hidl);
+ display_service_ =
+ android::dvr::DisplayService::Create(hidl, request_display_callback);
CHECK_ERROR(!display_service_, error, "Failed to create display service.");
dispatcher_->AddService(display_service_);
@@ -89,10 +88,6 @@
CHECK_ERROR(!service, error, "Failed to create display manager service.");
dispatcher_->AddService(service);
- service = android::dvr::ScreenshotService::Create();
- CHECK_ERROR(!service, error, "Failed to create screenshot service.");
- dispatcher_->AddService(service);
-
service = android::dvr::VSyncService::Create();
CHECK_ERROR(!service, error, "Failed to create vsync service.");
dispatcher_->AddService(service);
@@ -147,7 +142,9 @@
void VrFlinger::PersistentVrStateCallback::onPersistentVrStateChanged(
bool enabled) {
ALOGV("Notified persistent vr mode is %s", enabled ? "on" : "off");
- request_display_callback_(enabled);
+ // TODO(eieio): Determine the correct signal to request display control.
+ // Persistent VR mode is not enough.
+ // request_display_callback_(enabled);
}
} // namespace dvr
diff --git a/libs/vr/libvrflinger/vsync_service.cpp b/libs/vr/libvrflinger/vsync_service.cpp
index 612b9b2..2a83933 100644
--- a/libs/vr/libvrflinger/vsync_service.cpp
+++ b/libs/vr/libvrflinger/vsync_service.cpp
@@ -1,17 +1,19 @@
#include "vsync_service.h"
-#include <log/log.h>
#include <hardware/hwcomposer.h>
+#include <log/log.h>
#include <poll.h>
#include <sys/prctl.h>
#include <time.h>
#include <utils/Trace.h>
+#include <dvr/dvr_display_types.h>
#include <pdx/default_transport/service_endpoint.h>
#include <private/dvr/clock_ns.h>
-#include <private/dvr/display_rpc.h>
-#include <private/dvr/display_types.h>
+#include <private/dvr/display_protocol.h>
+using android::dvr::display::VSyncProtocol;
+using android::dvr::display::VSyncSchedInfo;
using android::pdx::Channel;
using android::pdx::Message;
using android::pdx::MessageInfo;
@@ -22,7 +24,7 @@
namespace dvr {
VSyncService::VSyncService()
- : BASE("VSyncService", Endpoint::Create(DisplayVSyncRPC::kClientPath)),
+ : BASE("VSyncService", Endpoint::Create(VSyncProtocol::kClientPath)),
last_vsync_(0),
current_vsync_(0),
compositor_time_ns_(0),
@@ -109,22 +111,22 @@
pdx::Status<void> VSyncService::HandleMessage(pdx::Message& message) {
switch (message.GetOp()) {
- case DisplayVSyncRPC::Wait::Opcode:
+ case VSyncProtocol::Wait::Opcode:
AddWaiter(message);
return {};
- case DisplayVSyncRPC::GetLastTimestamp::Opcode:
- DispatchRemoteMethod<DisplayVSyncRPC::GetLastTimestamp>(
+ case VSyncProtocol::GetLastTimestamp::Opcode:
+ DispatchRemoteMethod<VSyncProtocol::GetLastTimestamp>(
*this, &VSyncService::OnGetLastTimestamp, message);
return {};
- case DisplayVSyncRPC::GetSchedInfo::Opcode:
- DispatchRemoteMethod<DisplayVSyncRPC::GetSchedInfo>(
+ case VSyncProtocol::GetSchedInfo::Opcode:
+ DispatchRemoteMethod<VSyncProtocol::GetSchedInfo>(
*this, &VSyncService::OnGetSchedInfo, message);
return {};
- case DisplayVSyncRPC::Acknowledge::Opcode:
- DispatchRemoteMethod<DisplayVSyncRPC::Acknowledge>(
+ case VSyncProtocol::Acknowledge::Opcode:
+ DispatchRemoteMethod<VSyncProtocol::Acknowledge>(
*this, &VSyncService::OnAcknowledge, message);
return {};
@@ -133,16 +135,17 @@
}
}
-int64_t VSyncService::OnGetLastTimestamp(pdx::Message& message) {
+pdx::Status<int64_t> VSyncService::OnGetLastTimestamp(pdx::Message& message) {
auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel());
std::lock_guard<std::mutex> autolock(mutex_);
// Getting the timestamp has the side effect of ACKing.
client->Ack();
- return current_vsync_;
+ return {current_vsync_};
}
-VSyncSchedInfo VSyncService::OnGetSchedInfo(pdx::Message& message) {
+pdx::Status<VSyncSchedInfo> VSyncService::OnGetSchedInfo(
+ pdx::Message& message) {
auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel());
std::lock_guard<std::mutex> autolock(mutex_);
@@ -176,23 +179,25 @@
}
}
- return {vsync_period_ns, next_warp, next_vsync_count};
+ return {{vsync_period_ns, next_warp, next_vsync_count}};
}
-int VSyncService::OnAcknowledge(pdx::Message& message) {
+pdx::Status<void> VSyncService::OnAcknowledge(pdx::Message& message) {
auto client = std::static_pointer_cast<VSyncChannel>(message.GetChannel());
std::lock_guard<std::mutex> autolock(mutex_);
client->Ack();
- return 0;
+ return {};
}
void VSyncWaiter::Notify(int64_t timestamp) {
timestamp_ = timestamp;
- DispatchRemoteMethod<DisplayVSyncRPC::Wait>(*this, &VSyncWaiter::OnWait,
- message_);
+ DispatchRemoteMethod<VSyncProtocol::Wait>(*this, &VSyncWaiter::OnWait,
+ message_);
}
-int64_t VSyncWaiter::OnWait(pdx::Message& /*message*/) { return timestamp_; }
+pdx::Status<int64_t> VSyncWaiter::OnWait(pdx::Message& /*message*/) {
+ return {timestamp_};
+}
void VSyncChannel::Ack() {
ALOGD_IF(TRACE, "VSyncChannel::Ack: pid=%d cid=%d\n", pid_, cid_);
diff --git a/libs/vr/libvrflinger/vsync_service.h b/libs/vr/libvrflinger/vsync_service.h
index 1c86d42..215948e 100644
--- a/libs/vr/libvrflinger/vsync_service.h
+++ b/libs/vr/libvrflinger/vsync_service.h
@@ -23,7 +23,7 @@
void Notify(int64_t timestamp);
private:
- int64_t OnWait(pdx::Message& message);
+ pdx::Status<int64_t> OnWait(pdx::Message& message);
pdx::Message message_;
int64_t timestamp_ = 0;
@@ -62,10 +62,9 @@
void OnChannelClose(pdx::Message& message,
const std::shared_ptr<pdx::Channel>& channel) override;
- // Called by the hardware composer HAL, or similar,
- // whenever a vsync event occurs.
- // |compositor_time_ns| is the number of ns before the next vsync when the
- // compositor will preempt the GPU to do EDS and lens warp.
+ // Called by the hardware composer HAL, or similar, whenever a vsync event
+ // occurs. |compositor_time_ns| is the number of ns before the next vsync when
+ // the compositor will preempt the GPU to do EDS and lens warp.
void VSyncEvent(int display, int64_t timestamp_ns, int64_t compositor_time_ns,
uint32_t vsync_count);
@@ -74,9 +73,9 @@
VSyncService();
- int64_t OnGetLastTimestamp(pdx::Message& message);
- VSyncSchedInfo OnGetSchedInfo(pdx::Message& message);
- int OnAcknowledge(pdx::Message& message);
+ pdx::Status<int64_t> OnGetLastTimestamp(pdx::Message& message);
+ pdx::Status<display::VSyncSchedInfo> OnGetSchedInfo(pdx::Message& message);
+ pdx::Status<void> OnAcknowledge(pdx::Message& message);
void NotifierThreadFunction();
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 22a4616..2efb340 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -1172,10 +1172,11 @@
bool wrongDevice = false;
if (newGesture) {
bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
- if (switchedDevice && mTempTouchState.down && !down) {
+ if (switchedDevice && mTempTouchState.down && !down && !isHoverAction) {
#if DEBUG_FOCUS
ALOGD("Dropping event because a pointer for a different device is already down.");
#endif
+ // TODO: test multiple simultaneous input streams.
injectionResult = INPUT_EVENT_INJECTION_FAILED;
switchedDevice = false;
wrongDevice = true;
@@ -1187,6 +1188,15 @@
mTempTouchState.source = entry->source;
mTempTouchState.displayId = displayId;
isSplit = false;
+ } else if (switchedDevice && maskedAction == AMOTION_EVENT_ACTION_MOVE) {
+#if DEBUG_FOCUS
+ ALOGI("Dropping move event because a pointer for a different device is already active.");
+#endif
+ // TODO: test multiple simultaneous input streams.
+ injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
+ switchedDevice = false;
+ wrongDevice = true;
+ goto Failed;
}
if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index cd1d1b0..c5bbeee 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -1070,7 +1070,7 @@
for (sensors_event_t* i = event; i < event + 3; i++) {
*i = (sensors_event_t) {
.version = sizeof(sensors_event_t),
- .sensor = 0,
+ .sensor = SENSORS_HANDLE_BASE - 1, // sensor that never exists
.type = SENSOR_TYPE_ADDITIONAL_INFO,
.timestamp = timestamp++,
.additional_info = (additional_info_event_t) {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index bc4e6c5..45cac6f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -548,12 +548,15 @@
mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
mEventQueue.setEventThread(mSFEventThread);
- // set SFEventThread to SCHED_FIFO to minimize jitter
+ // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter
struct sched_param param = {0};
param.sched_priority = 2;
if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
}
+ if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, ¶m) != 0) {
+ ALOGE("Couldn't set SCHED_FIFO for EventThread");
+ }
// Get a RenderEngine for the given display / config (can't fail)
mRenderEngine = RenderEngine::create(mEGLDisplay,
@@ -581,6 +584,7 @@
if (useVrFlinger) {
auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) {
+ ALOGI("VR request display mode: requestDisplay=%d", requestDisplay);
mVrFlingerRequestsDisplay = requestDisplay;
signalTransaction();
};
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 019c8e3..7070b97 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -520,13 +520,15 @@
mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
mEventQueue.setEventThread(mSFEventThread);
- // set SFEventThread to SCHED_FIFO to minimize jitter
+ // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter
struct sched_param param = {0};
param.sched_priority = 2;
if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
}
-
+ if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, ¶m) != 0) {
+ ALOGE("Couldn't set SCHED_FIFO for EventThread");
+ }
// Initialize the H/W composer object. There may or may not be an
// actual hardware composer underneath.
diff --git a/services/surfaceflinger/surfaceflinger.rc b/services/surfaceflinger/surfaceflinger.rc
index 1c0427d..ff6be81 100644
--- a/services/surfaceflinger/surfaceflinger.rc
+++ b/services/surfaceflinger/surfaceflinger.rc
@@ -6,5 +6,4 @@
writepid /dev/stune/foreground/tasks
socket pdx/system/vr/display/client stream 0666 system graphics
socket pdx/system/vr/display/manager stream 0666 system graphics
- socket pdx/system/vr/display/screenshot stream 0660 system graphics
socket pdx/system/vr/display/vsync stream 0666 system graphics
diff --git a/services/vr/bufferhubd/buffer_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp
index 4b1a522..debcc73 100644
--- a/services/vr/bufferhubd/buffer_hub.cpp
+++ b/services/vr/bufferhubd/buffer_hub.cpp
@@ -53,7 +53,7 @@
stream << " ";
stream << std::setw(6) << "Format";
stream << " ";
- stream << std::setw(21) << "Usage";
+ stream << std::setw(11) << "Usage";
stream << " ";
stream << "Name";
stream << std::endl;
@@ -80,9 +80,7 @@
stream << std::setw(6) << info.format;
stream << " ";
stream << "0x" << std::hex << std::setfill('0');
- stream << std::setw(8) << info.producer_usage;
- stream << "0x";
- stream << std::setw(8) << info.consumer_usage;
+ stream << std::setw(8) << info.usage;
stream << std::dec << std::setfill(' ');
stream << " ";
stream << info.name;
@@ -134,16 +132,12 @@
stream << std::endl;
stream << "Active Producer Queues:\n";
stream << std::right << std::setw(6) << "Id";
- stream << std::right << std::setw(12) << " Allocated";
+ stream << std::right << std::setw(12) << " Capacity";
stream << std::right << std::setw(12) << " Consumers";
stream << " UsageSetMask";
stream << " UsageClearMask";
stream << " UsageDenySetMask";
stream << " UsageDenyClearMask";
- stream << " UsageSetMask";
- stream << " UsageClearMask";
- stream << " UsageDenySetMask";
- stream << " UsageDenyClearMask";
stream << " ";
stream << std::endl;
@@ -157,28 +151,16 @@
stream << std::right << std::setw(12) << info.consumer_count;
stream << std::setw(5) << std::setfill(' ') << "0x";
stream << std::hex << std::setfill('0');
- stream << std::setw(8) << info.usage_policy.producer_set_mask;
+ stream << std::setw(8) << info.usage_policy.usage_set_mask;
stream << std::setw(7) << std::setfill(' ') << "0x";
stream << std::hex << std::setfill('0');
- stream << std::setw(8) << info.usage_policy.producer_clear_mask;
+ stream << std::setw(8) << info.usage_policy.usage_clear_mask;
stream << std::setw(9) << std::setfill(' ') << "0x";
stream << std::hex << std::setfill('0');
- stream << std::setw(8) << info.usage_policy.producer_deny_set_mask;
+ stream << std::setw(8) << info.usage_policy.usage_deny_set_mask;
stream << std::setw(11) << std::setfill(' ') << "0x";
stream << std::hex << std::setfill('0');
- stream << std::setw(8) << info.usage_policy.producer_deny_clear_mask;
- stream << std::setw(5) << std::setfill(' ') << "0x";
- stream << std::hex << std::setfill('0');
- stream << std::setw(8) << info.usage_policy.consumer_set_mask;
- stream << std::setw(7) << std::setfill(' ') << "0x";
- stream << std::hex << std::setfill('0');
- stream << std::setw(8) << info.usage_policy.consumer_clear_mask;
- stream << std::setw(9) << std::setfill(' ') << "0x";
- stream << std::hex << std::setfill('0');
- stream << std::setw(8) << info.usage_policy.consumer_deny_set_mask;
- stream << std::setw(11) << std::setfill(' ') << "0x";
- stream << std::hex << std::setfill('0');
- stream << std::setw(8) << info.usage_policy.consumer_deny_clear_mask;
+ stream << std::setw(8) << info.usage_policy.usage_deny_clear_mask;
stream << std::hex << std::setfill('0');
stream << std::endl;
}
@@ -259,18 +241,16 @@
Status<void> BufferHubService::OnCreateBuffer(Message& message, uint32_t width,
uint32_t height, uint32_t format,
- uint64_t producer_usage,
- uint64_t consumer_usage,
+ uint64_t usage,
size_t meta_size_bytes,
size_t slice_count) {
// Use the producer channel id as the global buffer id.
const int buffer_id = message.GetChannelId();
ALOGD_IF(TRACE,
"BufferHubService::OnCreateBuffer: buffer_id=%d width=%u height=%u "
- "format=%u producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
- " meta_size_bytes=%zu slice_count=%zu",
- buffer_id, width, height, format, producer_usage, consumer_usage,
- meta_size_bytes, slice_count);
+ "format=%u usage=%" PRIx64 " meta_size_bytes=%zu slice_count=%zu",
+ buffer_id, width, height, format, usage, meta_size_bytes,
+ slice_count);
// See if this channel is already attached to a buffer.
if (const auto channel = message.GetChannel<BufferHubChannel>()) {
@@ -280,8 +260,7 @@
}
auto status = ProducerChannel::Create(this, buffer_id, width, height, format,
- producer_usage, consumer_usage,
- meta_size_bytes, slice_count);
+ usage, meta_size_bytes, slice_count);
if (status) {
message.SetChannel(status.take());
return {};
@@ -294,16 +273,15 @@
Status<void> BufferHubService::OnCreatePersistentBuffer(
Message& message, const std::string& name, int user_id, int group_id,
- uint32_t width, uint32_t height, uint32_t format, uint64_t producer_usage,
- uint64_t consumer_usage, size_t meta_size_bytes, size_t slice_count) {
+ uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
+ size_t meta_size_bytes, size_t slice_count) {
const int channel_id = message.GetChannelId();
ALOGD_IF(TRACE,
"BufferHubService::OnCreatePersistentBuffer: channel_id=%d name=%s "
"user_id=%d group_id=%d width=%u height=%u format=%u "
- "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
- " meta_size_bytes=%zu slice_count=%zu",
+ "usage=%" PRIx64 " meta_size_bytes=%zu slice_count=%zu",
channel_id, name.c_str(), user_id, group_id, width, height, format,
- producer_usage, consumer_usage, meta_size_bytes, slice_count);
+ usage, meta_size_bytes, slice_count);
// See if this channel is already attached to a buffer.
if (const auto channel = message.GetChannel<BufferHubChannel>()) {
@@ -324,9 +302,8 @@
"not have permission to access named buffer: name=%s euid=%d egid=%d",
name.c_str(), euid, euid);
return ErrorStatus(EPERM);
- } else if (!buffer->CheckParameters(width, height, format, producer_usage,
- consumer_usage, meta_size_bytes,
- slice_count)) {
+ } else if (!buffer->CheckParameters(width, height, format, usage,
+ meta_size_bytes, slice_count)) {
ALOGE(
"BufferHubService::OnCreatePersistentBuffer: Requested an existing "
"buffer with different parameters: name=%s",
@@ -344,9 +321,9 @@
return {};
}
} else {
- auto status = ProducerChannel::Create(
- this, channel_id, width, height, format, producer_usage, consumer_usage,
- meta_size_bytes, slice_count);
+ auto status =
+ ProducerChannel::Create(this, channel_id, width, height, format, usage,
+ meta_size_bytes, slice_count);
if (!status) {
ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
return status.error_status();
diff --git a/services/vr/bufferhubd/buffer_hub.h b/services/vr/bufferhubd/buffer_hub.h
index 4cb1eb9..817b01e 100644
--- a/services/vr/bufferhubd/buffer_hub.h
+++ b/services/vr/bufferhubd/buffer_hub.h
@@ -51,18 +51,16 @@
uint32_t width = 0;
uint32_t height = 0;
uint32_t format = 0;
- uint64_t producer_usage = 0;
- uint64_t consumer_usage = 0;
+ uint64_t usage = 0;
size_t slice_count = 0;
std::string name;
// Data filed for producer queue.
size_t capacity = 0;
- UsagePolicy usage_policy{0, 0, 0, 0, 0, 0, 0, 0};
+ UsagePolicy usage_policy{0, 0, 0, 0};
BufferInfo(int id, size_t consumer_count, uint32_t width, uint32_t height,
- uint32_t format, uint64_t producer_usage,
- uint64_t consumer_usage, size_t slice_count,
+ uint32_t format, uint64_t usage, size_t slice_count,
const std::string& name)
: id(id),
type(kProducerType),
@@ -70,8 +68,7 @@
width(width),
height(height),
format(format),
- producer_usage(producer_usage),
- consumer_usage(consumer_usage),
+ usage(usage),
slice_count(slice_count),
name(name) {}
@@ -159,16 +156,16 @@
std::unordered_map<std::string, std::shared_ptr<ProducerChannel>>
named_buffers_;
- pdx::Status<void> OnCreateBuffer(pdx::Message& message, uint32_t width, uint32_t height,
- uint32_t format, uint64_t producer_usage,
- uint64_t consumer_usage, size_t meta_size_bytes,
- size_t slice_count);
- pdx::Status<void> OnCreatePersistentBuffer(pdx::Message& message, const std::string& name,
- int user_id, int group_id, uint32_t width,
- uint32_t height, uint32_t format,
- uint64_t producer_usage, uint64_t consumer_usage,
- size_t meta_size_bytes, size_t slice_count);
- pdx::Status<void> OnGetPersistentBuffer(pdx::Message& message, const std::string& name);
+ pdx::Status<void> OnCreateBuffer(pdx::Message& message, uint32_t width,
+ uint32_t height, uint32_t format,
+ uint64_t usage, size_t meta_size_bytes,
+ size_t slice_count);
+ pdx::Status<void> OnCreatePersistentBuffer(
+ pdx::Message& message, const std::string& name, int user_id, int group_id,
+ uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
+ size_t meta_size_bytes, size_t slice_count);
+ pdx::Status<void> OnGetPersistentBuffer(pdx::Message& message,
+ const std::string& name);
pdx::Status<QueueInfo> OnCreateProducerQueue(pdx::Message& message,
size_t meta_size_bytes,
const UsagePolicy& usage_policy);
diff --git a/services/vr/bufferhubd/consumer_queue_channel.cpp b/services/vr/bufferhubd/consumer_queue_channel.cpp
index 7422751..f447e00 100644
--- a/services/vr/bufferhubd/consumer_queue_channel.cpp
+++ b/services/vr/bufferhubd/consumer_queue_channel.cpp
@@ -8,6 +8,7 @@
using android::pdx::RemoteChannelHandle;
using android::pdx::Status;
using android::pdx::rpc::DispatchRemoteMethod;
+using android::pdx::rpc::RemoteMethodError;
namespace android {
namespace dvr {
@@ -33,8 +34,10 @@
bool ConsumerQueueChannel::HandleMessage(Message& message) {
ATRACE_NAME("ConsumerQueueChannel::HandleMessage");
auto producer = GetProducer();
- if (!producer)
- REPLY_ERROR_RETURN(message, EPIPE, true);
+ if (!producer) {
+ RemoteMethodError(message, EPIPE);
+ return true;
+ }
switch (message.GetOp()) {
case BufferHubRPC::CreateConsumerQueue::Opcode:
@@ -79,6 +82,9 @@
void ConsumerQueueChannel::RegisterNewBuffer(
const std::shared_ptr<ProducerChannel>& producer_channel, size_t slot) {
+ ALOGD_IF(TRACE,
+ "ConsumerQueueChannel::RegisterNewBuffer: buffer_id=%d slot=%zu",
+ producer_channel->buffer_id(), slot);
pending_buffer_slots_.emplace(producer_channel, slot);
// Signal the client that there is new buffer available throught POLLIN.
@@ -89,7 +95,8 @@
ConsumerQueueChannel::OnConsumerQueueImportBuffers(Message& message) {
std::vector<std::pair<RemoteChannelHandle, size_t>> buffer_handles;
ATRACE_NAME("ConsumerQueueChannel::OnConsumerQueueImportBuffers");
- ALOGD(
+ ALOGD_IF(
+ TRACE,
"ConsumerQueueChannel::OnConsumerQueueImportBuffers number of buffers to "
"import: %zu",
pending_buffer_slots_.size());
@@ -134,5 +141,12 @@
return {std::move(buffer_handles)};
}
+void ConsumerQueueChannel::OnProducerClosed() {
+ ALOGD_IF(TRACE, "ConsumerQueueChannel::OnProducerClosed: queue_id=%d",
+ buffer_id());
+ producer_.reset();
+ Hangup();
+}
+
} // namespace dvr
} // namespace android
diff --git a/services/vr/bufferhubd/consumer_queue_channel.h b/services/vr/bufferhubd/consumer_queue_channel.h
index e1005e4..aa3f531 100644
--- a/services/vr/bufferhubd/consumer_queue_channel.h
+++ b/services/vr/bufferhubd/consumer_queue_channel.h
@@ -39,6 +39,8 @@
pdx::Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
OnConsumerQueueImportBuffers(Message& message);
+ void OnProducerClosed();
+
private:
std::shared_ptr<ProducerQueueChannel> GetProducer() const;
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index c4b1319..398aa12 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -26,8 +26,7 @@
ProducerChannel::ProducerChannel(BufferHubService* service, int channel_id,
uint32_t width, uint32_t height,
- uint32_t format, uint64_t producer_usage,
- uint64_t consumer_usage,
+ uint32_t format, uint64_t usage,
size_t meta_size_bytes, size_t slice_count,
int* error)
: BufferHubChannel(service, channel_id, channel_id, kProducerType),
@@ -37,8 +36,7 @@
meta_size_bytes_(meta_size_bytes),
meta_(meta_size_bytes ? new uint8_t[meta_size_bytes] : nullptr) {
for (auto& ion_buffer : slices_) {
- const int ret = ion_buffer.Alloc(width, height, format,
- (producer_usage | consumer_usage));
+ const int ret = ion_buffer.Alloc(width, height, format, usage);
if (ret < 0) {
ALOGE("ProducerChannel::ProducerChannel: Failed to allocate buffer: %s",
strerror(-ret));
@@ -53,12 +51,12 @@
Status<std::shared_ptr<ProducerChannel>> ProducerChannel::Create(
BufferHubService* service, int channel_id, uint32_t width, uint32_t height,
- uint32_t format, uint64_t producer_usage, uint64_t consumer_usage,
- size_t meta_size_bytes, size_t slice_count) {
+ uint32_t format, uint64_t usage, size_t meta_size_bytes,
+ size_t slice_count) {
int error;
- std::shared_ptr<ProducerChannel> producer(new ProducerChannel(
- service, channel_id, width, height, format, producer_usage,
- consumer_usage, meta_size_bytes, slice_count, &error));
+ std::shared_ptr<ProducerChannel> producer(
+ new ProducerChannel(service, channel_id, width, height, format, usage,
+ meta_size_bytes, slice_count, &error));
if (error < 0)
return ErrorStatus(-error);
else
@@ -76,8 +74,7 @@
BufferHubChannel::BufferInfo ProducerChannel::GetBufferInfo() const {
return BufferInfo(buffer_id(), consumer_channels_.size(), slices_[0].width(),
slices_[0].height(), slices_[0].format(),
- slices_[0].usage(), slices_[0].usage(),
- slices_.size(), name_);
+ slices_[0].usage(), slices_.size(), name_);
}
void ProducerChannel::HandleImpulse(Message& message) {
@@ -202,10 +199,15 @@
return ErrorStatus(EBUSY);
}
- if (meta_size_bytes_ != metadata.size())
+ if (meta_size_bytes_ != metadata.size()) {
+ ALOGD_IF(TRACE,
+ "ProducerChannel::OnProducerPost: Expected meta_size_bytes=%zu "
+ "got size=%zu",
+ meta_size_bytes_, metadata.size());
return ErrorStatus(EINVAL);
- std::copy(metadata.begin(), metadata.end(), meta_.get());
+ }
+ std::copy(metadata.begin(), metadata.end(), meta_.get());
post_fence_ = std::move(acquire_fence);
producer_owns_ = false;
@@ -369,14 +371,12 @@
// Returns true if the given parameters match the underlying buffer parameters.
bool ProducerChannel::CheckParameters(uint32_t width, uint32_t height,
- uint32_t format, uint64_t producer_usage,
- uint64_t consumer_usage,
+ uint32_t format, uint64_t usage,
size_t meta_size_bytes,
size_t slice_count) {
return slices_.size() == slice_count && meta_size_bytes == meta_size_bytes_ &&
slices_[0].width() == width && slices_[0].height() == height &&
- slices_[0].format() == format &&
- slices_[0].usage() == (producer_usage | consumer_usage);
+ slices_[0].format() == format && slices_[0].usage() == usage;
}
} // namespace dvr
diff --git a/services/vr/bufferhubd/producer_channel.h b/services/vr/bufferhubd/producer_channel.h
index f04c8a5..6de619d 100644
--- a/services/vr/bufferhubd/producer_channel.h
+++ b/services/vr/bufferhubd/producer_channel.h
@@ -32,8 +32,8 @@
static pdx::Status<std::shared_ptr<ProducerChannel>> Create(
BufferHubService* service, int channel_id, uint32_t width,
- uint32_t height, uint32_t format, uint64_t producer_usage,
- uint64_t consumer_usage, size_t meta_size_bytes, size_t slice_count);
+ uint32_t height, uint32_t format, uint64_t usage, size_t meta_size_bytes,
+ size_t slice_count);
~ProducerChannel() override;
@@ -62,8 +62,8 @@
bool CheckAccess(int euid, int egid);
bool CheckParameters(uint32_t width, uint32_t height, uint32_t format,
- uint64_t producer_usage, uint64_t consumer_usage,
- size_t meta_size_bytes, size_t slice_count);
+ uint64_t usage, size_t meta_size_bytes,
+ size_t slice_count);
pdx::Status<void> OnProducerMakePersistent(Message& message,
const std::string& name,
@@ -95,9 +95,8 @@
std::string name_;
ProducerChannel(BufferHubService* service, int channel, uint32_t width,
- uint32_t height, uint32_t format, uint64_t producer_usage,
- uint64_t consumer_usage, size_t meta_size_bytes,
- size_t slice_count, int* error);
+ uint32_t height, uint32_t format, uint64_t usage,
+ size_t meta_size_bytes, size_t slice_count, int* error);
pdx::Status<void> OnProducerPost(
Message& message, LocalFence acquire_fence,
diff --git a/services/vr/bufferhubd/producer_queue_channel.cpp b/services/vr/bufferhubd/producer_queue_channel.cpp
index dc2a47e..843277e 100644
--- a/services/vr/bufferhubd/producer_queue_channel.cpp
+++ b/services/vr/bufferhubd/producer_queue_channel.cpp
@@ -26,7 +26,12 @@
*error = 0;
}
-ProducerQueueChannel::~ProducerQueueChannel() {}
+ProducerQueueChannel::~ProducerQueueChannel() {
+ ALOGD_IF(TRACE, "ProducerQueueChannel::~ProducerQueueChannel: queue_id=%d",
+ buffer_id());
+ for (auto* consumer : consumer_channels_)
+ consumer->OnProducerClosed();
+}
/* static */
Status<std::shared_ptr<ProducerQueueChannel>> ProducerQueueChannel::Create(
@@ -34,19 +39,14 @@
const UsagePolicy& usage_policy) {
// Configuration between |usage_deny_set_mask| and |usage_deny_clear_mask|
// should be mutually exclusive.
- if ((usage_policy.producer_deny_set_mask &
- usage_policy.producer_deny_clear_mask) ||
- (usage_policy.consumer_deny_set_mask &
- usage_policy.consumer_deny_clear_mask)) {
+ if ((usage_policy.usage_deny_set_mask &
+ usage_policy.usage_deny_clear_mask)) {
ALOGE(
"BufferHubService::OnCreateProducerQueue: illegal usage mask "
- "configuration: producer_deny_set_mask=%" PRIx64
- " producer_deny_clear_mask=%" PRIx64 " consumer_deny_set_mask=%" PRIx64
- " consumer_deny_clear_mask=%" PRIx64,
- usage_policy.producer_deny_set_mask,
- usage_policy.producer_deny_clear_mask,
- usage_policy.consumer_deny_set_mask,
- usage_policy.consumer_deny_clear_mask);
+ "configuration: usage_deny_set_mask=%" PRIx64
+ " usage_deny_clear_mask=%" PRIx64,
+ usage_policy.usage_deny_set_mask,
+ usage_policy.usage_deny_clear_mask);
return ErrorStatus(EINVAL);
}
@@ -113,13 +113,21 @@
return ErrorStatus(ENOMEM);
}
- const auto channel_status = service()->SetChannel(
- channel_id, std::make_shared<ConsumerQueueChannel>(
- service(), buffer_id(), channel_id, shared_from_this()));
+ auto consumer_queue_channel = std::make_shared<ConsumerQueueChannel>(
+ service(), buffer_id(), channel_id, shared_from_this());
+
+ // Register the existing buffers with the new consumer queue.
+ for (size_t slot = 0; slot < BufferHubRPC::kMaxQueueCapacity; slot++) {
+ if (auto buffer = buffers_[slot].lock())
+ consumer_queue_channel->RegisterNewBuffer(buffer, slot);
+ }
+
+ const auto channel_status =
+ service()->SetChannel(channel_id, consumer_queue_channel);
if (!channel_status) {
ALOGE(
- "ProducerQueueChannel::OnCreateConsumerQueue: failed to set new "
- "consumer channel: %s",
+ "ProducerQueueChannel::OnCreateConsumerQueue: Failed to set channel: "
+ "%s",
channel_status.GetErrorMessage().c_str());
return ErrorStatus(ENOMEM);
}
@@ -134,8 +142,7 @@
Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
ProducerQueueChannel::OnProducerQueueAllocateBuffers(
Message& message, uint32_t width, uint32_t height, uint32_t format,
- uint64_t producer_usage, uint64_t consumer_usage, size_t slice_count,
- size_t buffer_count) {
+ uint64_t usage, size_t slice_count, size_t buffer_count) {
ATRACE_NAME("ProducerQueueChannel::OnProducerQueueAllocateBuffers");
ALOGD_IF(TRACE,
"ProducerQueueChannel::OnProducerQueueAllocateBuffers: "
@@ -145,58 +152,32 @@
std::vector<std::pair<RemoteChannelHandle, size_t>> buffer_handles;
// Deny buffer allocation violating preset rules.
- if (producer_usage & usage_policy_.producer_deny_set_mask) {
+ if (usage & usage_policy_.usage_deny_set_mask) {
ALOGE(
- "ProducerQueueChannel::OnProducerQueueAllocateBuffers: producer_usage: "
- "%" PRIx64
- " is not permitted. Violating producer_deny_set_mask, the following "
- "bits shall not be set: %" PRIx64 ".",
- producer_usage, usage_policy_.producer_deny_set_mask);
+ "ProducerQueueChannel::OnProducerQueueAllocateBuffers: usage: %" PRIx64
+ " is not permitted. Violating usage_deny_set_mask, the following bits "
+ "shall not be set: %" PRIx64 ".",
+ usage, usage_policy_.usage_deny_set_mask);
return ErrorStatus(EINVAL);
}
- if (consumer_usage & usage_policy_.consumer_deny_set_mask) {
+ if (~usage & usage_policy_.usage_deny_clear_mask) {
ALOGE(
- "ProducerQueueChannel::OnProducerQueueAllocateBuffers: consumer_usage: "
- "%" PRIx64
- " is not permitted. Violating consumer_deny_set_mask, the following "
- "bits shall not be set: %" PRIx64 ".",
- consumer_usage, usage_policy_.consumer_deny_set_mask);
- return ErrorStatus(EINVAL);
- }
-
- if (~producer_usage & usage_policy_.producer_deny_clear_mask) {
- ALOGE(
- "ProducerQueueChannel::OnProducerQueueAllocateBuffers: producer_usage: "
- "%" PRIx64
- " is not permitted. Violating producer_deny_clear_mask, the following "
+ "ProducerQueueChannel::OnProducerQueueAllocateBuffers: usage: %" PRIx64
+ " is not permitted. Violating usage_deny_clear_mask, the following "
"bits must be set: %" PRIx64 ".",
- producer_usage, usage_policy_.producer_deny_clear_mask);
+ usage, usage_policy_.usage_deny_clear_mask);
return ErrorStatus(EINVAL);
}
- if (~consumer_usage & usage_policy_.consumer_deny_clear_mask) {
- ALOGE(
- "ProducerQueueChannel::OnProducerQueueAllocateBuffers: consumer_usage: "
- "%" PRIx64
- " is not permitted. Violating consumer_deny_clear_mask, the following "
- "bits must be set: %" PRIx64 ".",
- consumer_usage, usage_policy_.consumer_deny_clear_mask);
- return ErrorStatus(EINVAL);
- }
- // Force set mask and clear mask. Note that |usage_policy_.X_set_mask_| takes
- // precedence and will overwrite |usage_policy_.X_clear_mask|.
- uint64_t effective_producer_usage =
- (producer_usage & ~usage_policy_.producer_clear_mask) |
- usage_policy_.producer_set_mask;
- uint64_t effective_consumer_usage =
- (consumer_usage & ~usage_policy_.consumer_clear_mask) |
- usage_policy_.consumer_set_mask;
+ // Force set mask and clear mask. Note that |usage_policy_.usage_set_mask_|
+ // takes precedence and will overwrite |usage_policy_.usage_clear_mask|.
+ uint64_t effective_usage =
+ (usage & ~usage_policy_.usage_clear_mask) | usage_policy_.usage_set_mask;
for (size_t i = 0; i < buffer_count; i++) {
- auto status =
- AllocateBuffer(message, width, height, format, effective_producer_usage,
- effective_consumer_usage, slice_count);
+ auto status = AllocateBuffer(message, width, height, format,
+ effective_usage, slice_count);
if (!status) {
ALOGE(
"ProducerQueueChannel::OnProducerQueueAllocateBuffers: Failed to "
@@ -212,9 +193,7 @@
Status<std::pair<RemoteChannelHandle, size_t>>
ProducerQueueChannel::AllocateBuffer(Message& message, uint32_t width,
uint32_t height, uint32_t format,
- uint64_t producer_usage,
- uint64_t consumer_usage,
- size_t slice_count) {
+ uint64_t usage, size_t slice_count) {
ATRACE_NAME("ProducerQueueChannel::AllocateBuffer");
ALOGD_IF(TRACE,
"ProducerQueueChannel::AllocateBuffer: producer_channel_id=%d",
@@ -239,15 +218,13 @@
ALOGD_IF(TRACE,
"ProducerQueueChannel::AllocateBuffer: buffer_id=%d width=%u "
- "height=%u format=%u producer_usage=%" PRIx64
- " consumer_usage=%" PRIx64 " slice_count=%zu",
- buffer_id, width, height, format, producer_usage, consumer_usage,
- slice_count);
+ "height=%u format=%u usage=%" PRIx64 " slice_count=%zu",
+ buffer_id, width, height, format, usage, slice_count);
auto buffer_handle = status.take();
- auto producer_channel_status = ProducerChannel::Create(
- service(), buffer_id, width, height, format, producer_usage,
- consumer_usage, meta_size_bytes_, slice_count);
+ auto producer_channel_status =
+ ProducerChannel::Create(service(), buffer_id, width, height, format,
+ usage, meta_size_bytes_, slice_count);
if (!producer_channel_status) {
ALOGE(
"ProducerQueueChannel::AllocateBuffer: Failed to create producer "
@@ -290,7 +267,7 @@
capacity_++;
// Notify each consumer channel about the new buffer.
- for (auto consumer_channel : consumer_channels_) {
+ for (auto* consumer_channel : consumer_channels_) {
ALOGD(
"ProducerQueueChannel::AllocateBuffer: Notified consumer with new "
"buffer, buffer_id=%d",
diff --git a/services/vr/bufferhubd/producer_queue_channel.h b/services/vr/bufferhubd/producer_queue_channel.h
index 09b0243..13c9ddc 100644
--- a/services/vr/bufferhubd/producer_queue_channel.h
+++ b/services/vr/bufferhubd/producer_queue_channel.h
@@ -35,8 +35,7 @@
pdx::Status<std::vector<std::pair<pdx::RemoteChannelHandle, size_t>>>
OnProducerQueueAllocateBuffers(pdx::Message& message, uint32_t width,
uint32_t height, uint32_t format,
- uint64_t producer_usage,
- uint64_t consumer_usage, size_t slice_count,
+ uint64_t usage, size_t slice_count,
size_t buffer_count);
// Detach a BufferHubProducer indicated by |slot|. Note that the buffer must
@@ -59,7 +58,7 @@
// allocated buffer.
pdx::Status<std::pair<pdx::RemoteChannelHandle, size_t>> AllocateBuffer(
pdx::Message& message, uint32_t width, uint32_t height, uint32_t format,
- uint64_t producer_usage, uint64_t consumer_usage, size_t slice_count);
+ uint64_t usage, size_t slice_count);
// Size of the meta data associated with all the buffers allocated from the
// queue. Now we assume the metadata size is immutable once the queue is
diff --git a/services/vr/hardware_composer/impl/vr_hwc.cpp b/services/vr/hardware_composer/impl/vr_hwc.cpp
index 504b26f..5d51827 100644
--- a/services/vr/hardware_composer/impl/vr_hwc.cpp
+++ b/services/vr/hardware_composer/impl/vr_hwc.cpp
@@ -60,24 +60,22 @@
*height = 1920;
int error = 0;
- auto display_client = DisplayClient::Create(&error);
- SystemDisplayMetrics metrics;
-
- if (error) {
+ auto display_client = display::DisplayClient::Create(&error);
+ if (!display_client) {
ALOGE("Could not connect to display service : %s(%d)", strerror(error),
error);
return;
}
- error = display_client->GetDisplayMetrics(&metrics);
- if (error) {
+ auto status = display_client->GetDisplayMetrics();
+ if (!status) {
ALOGE("Could not get display metrics from display service : %s(%d)",
- strerror(error), error);
+ status.GetErrorMessage().c_str(), status.error());
return;
}
- *width = metrics.display_native_width;
- *height = metrics.display_native_height;
+ *width = status.get().display_width;
+ *height = status.get().display_height;
}
} // namespace
diff --git a/services/vr/vr_window_manager/shell_view.cpp b/services/vr/vr_window_manager/shell_view.cpp
index 2b53cd6..abd0651 100644
--- a/services/vr/vr_window_manager/shell_view.cpp
+++ b/services/vr/vr_window_manager/shell_view.cpp
@@ -196,8 +196,8 @@
result.appendFormat("count = %zu\n", displays_.size());
for (size_t i = 0; i < displays_.size(); ++i) {
result.appendFormat(" display_id = %" PRId32 "\n", displays_[i]->id());
- result.appendFormat(" size=%fx%f\n",
- displays_[i]->size().x(), displays_[i]->size().y());
+ result.appendFormat(" size=%fx%f\n", displays_[i]->size().x(),
+ displays_[i]->size().y());
}
result.append("\n");
@@ -210,7 +210,7 @@
void ShellView::SetRotation(int angle) {
mat4 m(Eigen::AngleAxisf(M_PI * -0.5f * angle, vec3::UnitZ()));
- for (auto& d: displays_)
+ for (auto& d : displays_)
d->set_rotation(m);
}
@@ -300,7 +300,7 @@
// Do this on demand in case vr_flinger crashed and we are reconnecting.
if (!display_client_.get()) {
int error = 0;
- display_client_ = DisplayClient::Create(&error);
+ display_client_ = display::DisplayClient::Create(&error);
if (error) {
ALOGE("Could not connect to display service : %s(%d)", strerror(error),
@@ -310,7 +310,13 @@
}
// TODO(achaulk): change when moved into vrcore.
- bool vr_running = display_client_->IsVrAppRunning();
+ auto status = display_client_->IsVrAppRunning();
+ if (!status) {
+ ALOGE("Failed to check VR running status: %s",
+ status.GetErrorMessage().c_str());
+ return base::unique_fd();
+ }
+ const bool vr_running = status.get();
base::unique_fd fd(
display->OnFrame(std::move(frame), debug_mode_, vr_running, &showing));
@@ -488,8 +494,8 @@
// Device is portrait, but in landscape when in VR.
// Rotate touch input appropriately.
const android::status_t status = dvrVirtualTouchpadTouch(
- virtual_touchpad_.get(), active_display_->touchpad_id(),
- x, y, is_touching_ ? 1.0f : 0.0f);
+ virtual_touchpad_.get(), active_display_->touchpad_id(), x, y,
+ is_touching_ ? 1.0f : 0.0f);
if (status != OK) {
ALOGE("touch failed: %d", status);
}
diff --git a/services/vr/vr_window_manager/shell_view.h b/services/vr/vr_window_manager/shell_view.h
index d90e833..9b51600 100644
--- a/services/vr/vr_window_manager/shell_view.h
+++ b/services/vr/vr_window_manager/shell_view.h
@@ -68,7 +68,7 @@
std::unique_ptr<SurfaceFlingerView> surface_flinger_view_;
std::unique_ptr<Reticle> reticle_;
- std::unique_ptr<DisplayClient> display_client_;
+ std::unique_ptr<display::DisplayClient> display_client_;
struct DvrVirtualTouchpadDeleter {
void operator()(DvrVirtualTouchpad* p) {