Adopt the use of shared buffers.
Bug: 37001948
Test: Make system image
Change-Id: I032574f250e0f0fe7768af649730406e24d853db
diff --git a/libs/vr/libdisplay/Android.bp b/libs/vr/libdisplay/Android.bp
index c0c7e2f..e3ab7fa 100644
--- a/libs/vr/libdisplay/Android.bp
+++ b/libs/vr/libdisplay/Android.bp
@@ -17,6 +17,7 @@
"display_manager_client.cpp",
"display_protocol.cpp",
"vsync_client.cpp",
+ "shared_buffer_helpers.cpp",
]
localIncludeFiles = [
@@ -39,7 +40,7 @@
"libdvrcommon",
"libbufferhubqueue",
"libbufferhub",
- "libvrsensor",
+ "libbroadcastring",
"libpdx_default_transport",
]
diff --git a/libs/vr/libdisplay/include/private/dvr/shared_buffer_helpers.h b/libs/vr/libdisplay/include/private/dvr/shared_buffer_helpers.h
new file mode 100644
index 0000000..249f410
--- /dev/null
+++ b/libs/vr/libdisplay/include/private/dvr/shared_buffer_helpers.h
@@ -0,0 +1,138 @@
+#ifndef ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
+#define ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
+
+#include <assert.h>
+#include <tuple>
+
+#include <libbroadcastring/broadcast_ring.h>
+#include <private/dvr/display_client.h>
+
+namespace android {
+namespace dvr {
+
+// The buffer usage type for mapped shared buffers.
+enum class CPUUsageMode { READ_OFTEN, READ_RARELY, WRITE_OFTEN, WRITE_RARELY };
+
+// Holds the memory for the mapped shared buffer. Unlocks and releases the
+// underlying IonBuffer in destructor.
+class CPUMappedBuffer {
+ public:
+ // This constructor will create a display client and get the buffer from it.
+ CPUMappedBuffer(DvrGlobalBufferKey key, CPUUsageMode mode);
+
+ // If you already have the IonBuffer, use this. It will take ownership.
+ CPUMappedBuffer(std::unique_ptr<IonBuffer> buffer, CPUUsageMode mode);
+
+ // Use this if you do not want to take ownership.
+ CPUMappedBuffer(IonBuffer* buffer, CPUUsageMode mode);
+
+ ~CPUMappedBuffer();
+
+ // Getters.
+ size_t Size() const { return size_; }
+ void* Address() const { return address_; }
+ bool IsMapped() const { return Address() != nullptr; }
+
+ // Attempt mapping this buffer to the CPU addressable space.
+ // This will create a display client and see if the buffer exists.
+ // If the buffer has not been setup yet, you will need to try again later.
+ void TryMapping();
+
+ protected:
+ // The memory area if we managed to map it.
+ size_t size_ = 0;
+ void* address_ = nullptr;
+
+ // If we are polling the display client, the buffer key here.
+ DvrGlobalBufferKey buffer_key_;
+
+ // If we just own the IonBuffer outright, it's here.
+ std::unique_ptr<IonBuffer> owned_buffer_ = nullptr;
+
+ // If we do not own the IonBuffer, it's here
+ IonBuffer* buffer_ = nullptr;
+
+ // The usage mode.
+ CPUUsageMode usage_mode_ = CPUUsageMode::READ_OFTEN;
+};
+
+// Represents a broadcast ring inside a mapped shared memory buffer.
+// If has the same set of constructors as CPUMappedBuffer.
+// The template argument is the concrete BroadcastRing class that this buffer
+// holds.
+template <class RingType>
+class CPUMappedBroadcastRing : public CPUMappedBuffer {
+ public:
+ CPUMappedBroadcastRing(DvrGlobalBufferKey key, CPUUsageMode mode)
+ : CPUMappedBuffer(key, mode) {}
+
+ CPUMappedBroadcastRing(std::unique_ptr<IonBuffer> buffer, CPUUsageMode mode)
+ : CPUMappedBuffer(std::move(buffer), mode) {}
+
+ CPUMappedBroadcastRing(IonBuffer* buffer, CPUUsageMode mode)
+ : CPUMappedBuffer(buffer, mode) {}
+
+ // Helper function for publishing records in the ring.
+ void Publish(const typename RingType::Record& record) {
+ assert((usage_mode_ == CPUUsageMode::WRITE_OFTEN) ||
+ (usage_mode_ == CPUUsageMode::WRITE_RARELY));
+
+ auto ring = Ring();
+ if (ring) {
+ ring->Put(record);
+ }
+ }
+
+ // Helper function for getting records from the ring.
+ // Returns true if we were able to retrieve the latest.
+ bool GetNewest(typename RingType::Record* record) {
+ assert((usage_mode_ == CPUUsageMode::READ_OFTEN) ||
+ (usage_mode_ == CPUUsageMode::READ_RARELY));
+
+ auto ring = Ring();
+ if (ring) {
+ return ring->GetNewest(&sequence_, record);
+ }
+
+ return false;
+ }
+
+ // Try obtaining the ring. If the named buffer has not been created yet, it
+ // will return nullptr.
+ RingType* Ring() {
+ if (IsMapped() == false) {
+ TryMapping();
+
+ if (IsMapped()) {
+ switch (usage_mode_) {
+ case CPUUsageMode::READ_OFTEN:
+ case CPUUsageMode::READ_RARELY: {
+ RingType ring;
+ bool import_ok;
+ std::tie(ring, import_ok) = RingType::Import(address_, size_);
+ if (import_ok) {
+ ring_ = std::make_unique<RingType>(ring);
+ }
+ } break;
+ case CPUUsageMode::WRITE_OFTEN:
+ case CPUUsageMode::WRITE_RARELY:
+ ring_ =
+ std::make_unique<RingType>(RingType::Create(address_, size_));
+ break;
+ }
+ }
+ }
+
+ return ring_.get();
+ }
+
+ protected:
+ std::unique_ptr<RingType> ring_ = nullptr;
+
+ uint32_t sequence_ = 0;
+};
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
diff --git a/libs/vr/libdisplay/shared_buffer_helpers.cpp b/libs/vr/libdisplay/shared_buffer_helpers.cpp
new file mode 100644
index 0000000..00bad88
--- /dev/null
+++ b/libs/vr/libdisplay/shared_buffer_helpers.cpp
@@ -0,0 +1,84 @@
+#include <private/dvr/shared_buffer_helpers.h>
+
+namespace android {
+namespace dvr {
+
+CPUMappedBuffer::CPUMappedBuffer(DvrGlobalBufferKey key, CPUUsageMode mode)
+ : buffer_key_(key), usage_mode_(mode) {
+ TryMapping();
+}
+
+CPUMappedBuffer::CPUMappedBuffer(std::unique_ptr<IonBuffer> buffer,
+ CPUUsageMode mode)
+ : owned_buffer_(std::move(buffer)),
+ buffer_(owned_buffer_.get()),
+ usage_mode_(mode) {
+ TryMapping();
+}
+
+CPUMappedBuffer::CPUMappedBuffer(IonBuffer* buffer, CPUUsageMode mode)
+ : buffer_(buffer), usage_mode_(mode) {
+ TryMapping();
+}
+
+CPUMappedBuffer::~CPUMappedBuffer() {
+ if (IsMapped()) {
+ buffer_->Unlock();
+ }
+}
+
+void CPUMappedBuffer::TryMapping() {
+ // Do we have an IonBuffer for this shared memory object?
+ if (buffer_ == nullptr) {
+ // Create a display client and get the buffer.
+ // TODO(okana): We might want to throttle this.
+ auto display_client = display::DisplayClient::Create();
+ if (display_client) {
+ auto get_result = display_client->GetGlobalBuffer(buffer_key_);
+ if (get_result.ok()) {
+ owned_buffer_ = get_result.take();
+ buffer_ = owned_buffer_.get();
+ } else {
+ ALOGW("Could not get named buffer from pose service : %s(%d)",
+ get_result.GetErrorMessage().c_str(), get_result.error());
+ }
+ } else {
+ ALOGE("Unable to create display client for shared buffer access");
+ }
+ }
+
+ if (buffer_) {
+ auto usage = buffer_->usage() & ~GRALLOC_USAGE_SW_READ_MASK &
+ ~GRALLOC_USAGE_SW_WRITE_MASK;
+
+ // Figure out the usage bits.
+ switch (usage_mode_) {
+ case CPUUsageMode::READ_OFTEN:
+ usage |= GRALLOC_USAGE_SW_READ_OFTEN;
+ break;
+ case CPUUsageMode::READ_RARELY:
+ usage |= GRALLOC_USAGE_SW_READ_RARELY;
+ break;
+ case CPUUsageMode::WRITE_OFTEN:
+ usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
+ break;
+ case CPUUsageMode::WRITE_RARELY:
+ usage |= GRALLOC_USAGE_SW_WRITE_RARELY;
+ break;
+ }
+
+ int width = static_cast<int>(buffer_->width());
+ int height = 1;
+ const auto ret = buffer_->Lock(usage, 0, 0, width, height, &address_);
+
+ if (ret < 0 || !address_) {
+ ALOGE("Pose failed to map ring buffer: ret:%d, addr:%p", ret, address_);
+ buffer_->Unlock();
+ } else {
+ size_ = width;
+ }
+ }
+}
+
+} // namespace dvr
+} // namespace android