Loading libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h +28 −7 Original line number Original line Diff line number Diff line Loading @@ -174,8 +174,6 @@ class BroadcastRing { // // // There must be at least |MemorySize(record_count)| bytes of space already // There must be at least |MemorySize(record_count)| bytes of space already // allocated at |mmap|. The ring does not take ownership. // allocated at |mmap|. The ring does not take ownership. // // Use this function for dynamically sized rings. static BroadcastRing Create(void* mmap, size_t mmap_size, static BroadcastRing Create(void* mmap, size_t mmap_size, uint32_t record_count) { uint32_t record_count) { BroadcastRing ring(mmap); BroadcastRing ring(mmap); Loading @@ -188,12 +186,11 @@ class BroadcastRing { // // // There must be at least |MemorySize()| bytes of space already allocated at // There must be at least |MemorySize()| bytes of space already allocated at // |mmap|. The ring does not take ownership. // |mmap|. The ring does not take ownership. // // Use this function for statically sized rings. static BroadcastRing Create(void* mmap, size_t mmap_size) { static BroadcastRing Create(void* mmap, size_t mmap_size) { static_assert(Traits::kUseStaticRecordCount, return Create(mmap, mmap_size, "Wrong Create() function called for dynamic record count"); Traits::kUseStaticRecordCount return Create(mmap, mmap_size, Traits::kStaticRecordCount); ? Traits::kStaticRecordCount : BroadcastRing::GetRecordCount(mmap_size)); } } // Imports an existing ring at |mmap|. // Imports an existing ring at |mmap|. Loading Loading @@ -233,6 +230,30 @@ class BroadcastRing { return MemorySize(Traits::kStaticRecordCount); return MemorySize(Traits::kStaticRecordCount); } } static uint32_t NextPowerOf2(uint32_t n) { if (n == 0) return 0; n -= 1; n |= n >> 16; n |= n >> 8; n |= n >> 4; n |= n >> 2; n |= n >> 1; return n + 1; } // Gets the biggest power of 2 record count that can fit into this mmap. // // The header size has been taken into account. static uint32_t GetRecordCount(size_t mmap_size) { if (mmap_size <= sizeof(Header)) { return 0; } uint32_t count = static_cast<uint32_t>((mmap_size - sizeof(Header)) / sizeof(Record)); return IsPowerOfTwo(count) ? count : (NextPowerOf2(count) / 2); } // Writes a record to the ring. // Writes a record to the ring. // // // The oldest record is overwritten unless the ring is not already full. // The oldest record is overwritten unless the ring is not already full. Loading libs/vr/libdisplay/Android.bp +2 −1 Original line number Original line Diff line number Diff line Loading @@ -17,6 +17,7 @@ sourceFiles = [ "display_manager_client.cpp", "display_manager_client.cpp", "display_protocol.cpp", "display_protocol.cpp", "vsync_client.cpp", "vsync_client.cpp", "shared_buffer_helpers.cpp", ] ] localIncludeFiles = [ localIncludeFiles = [ Loading @@ -39,7 +40,7 @@ staticLibraries = [ "libdvrcommon", "libdvrcommon", "libbufferhubqueue", "libbufferhubqueue", "libbufferhub", "libbufferhub", "libvrsensor", "libbroadcastring", "libpdx_default_transport", "libpdx_default_transport", ] ] Loading libs/vr/libdisplay/include/private/dvr/shared_buffer_helpers.h 0 → 100644 +138 −0 Original line number Original line Diff line number Diff line #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_ libs/vr/libdisplay/shared_buffer_helpers.cpp 0 → 100644 +84 −0 Original line number Original line Diff line number Diff line #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 libs/vr/libdvr/Android.bp +2 −1 Original line number Original line Diff line number Diff line Loading @@ -34,10 +34,11 @@ srcs = [ ] ] static_libs = [ static_libs = [ "libbroadcastring", "libbufferhub", "libbufferhub", "libbufferhubqueue", "libbufferhubqueue", "libdisplay", "libvrsensor", "libvrsensor", "libdisplay", "libvirtualtouchpadclient", "libvirtualtouchpadclient", "libvr_hwc-impl", "libvr_hwc-impl", "libvr_hwc-binder", "libvr_hwc-binder", Loading Loading
libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h +28 −7 Original line number Original line Diff line number Diff line Loading @@ -174,8 +174,6 @@ class BroadcastRing { // // // There must be at least |MemorySize(record_count)| bytes of space already // There must be at least |MemorySize(record_count)| bytes of space already // allocated at |mmap|. The ring does not take ownership. // allocated at |mmap|. The ring does not take ownership. // // Use this function for dynamically sized rings. static BroadcastRing Create(void* mmap, size_t mmap_size, static BroadcastRing Create(void* mmap, size_t mmap_size, uint32_t record_count) { uint32_t record_count) { BroadcastRing ring(mmap); BroadcastRing ring(mmap); Loading @@ -188,12 +186,11 @@ class BroadcastRing { // // // There must be at least |MemorySize()| bytes of space already allocated at // There must be at least |MemorySize()| bytes of space already allocated at // |mmap|. The ring does not take ownership. // |mmap|. The ring does not take ownership. // // Use this function for statically sized rings. static BroadcastRing Create(void* mmap, size_t mmap_size) { static BroadcastRing Create(void* mmap, size_t mmap_size) { static_assert(Traits::kUseStaticRecordCount, return Create(mmap, mmap_size, "Wrong Create() function called for dynamic record count"); Traits::kUseStaticRecordCount return Create(mmap, mmap_size, Traits::kStaticRecordCount); ? Traits::kStaticRecordCount : BroadcastRing::GetRecordCount(mmap_size)); } } // Imports an existing ring at |mmap|. // Imports an existing ring at |mmap|. Loading Loading @@ -233,6 +230,30 @@ class BroadcastRing { return MemorySize(Traits::kStaticRecordCount); return MemorySize(Traits::kStaticRecordCount); } } static uint32_t NextPowerOf2(uint32_t n) { if (n == 0) return 0; n -= 1; n |= n >> 16; n |= n >> 8; n |= n >> 4; n |= n >> 2; n |= n >> 1; return n + 1; } // Gets the biggest power of 2 record count that can fit into this mmap. // // The header size has been taken into account. static uint32_t GetRecordCount(size_t mmap_size) { if (mmap_size <= sizeof(Header)) { return 0; } uint32_t count = static_cast<uint32_t>((mmap_size - sizeof(Header)) / sizeof(Record)); return IsPowerOfTwo(count) ? count : (NextPowerOf2(count) / 2); } // Writes a record to the ring. // Writes a record to the ring. // // // The oldest record is overwritten unless the ring is not already full. // The oldest record is overwritten unless the ring is not already full. Loading
libs/vr/libdisplay/Android.bp +2 −1 Original line number Original line Diff line number Diff line Loading @@ -17,6 +17,7 @@ sourceFiles = [ "display_manager_client.cpp", "display_manager_client.cpp", "display_protocol.cpp", "display_protocol.cpp", "vsync_client.cpp", "vsync_client.cpp", "shared_buffer_helpers.cpp", ] ] localIncludeFiles = [ localIncludeFiles = [ Loading @@ -39,7 +40,7 @@ staticLibraries = [ "libdvrcommon", "libdvrcommon", "libbufferhubqueue", "libbufferhubqueue", "libbufferhub", "libbufferhub", "libvrsensor", "libbroadcastring", "libpdx_default_transport", "libpdx_default_transport", ] ] Loading
libs/vr/libdisplay/include/private/dvr/shared_buffer_helpers.h 0 → 100644 +138 −0 Original line number Original line Diff line number Diff line #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_
libs/vr/libdisplay/shared_buffer_helpers.cpp 0 → 100644 +84 −0 Original line number Original line Diff line number Diff line #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
libs/vr/libdvr/Android.bp +2 −1 Original line number Original line Diff line number Diff line Loading @@ -34,10 +34,11 @@ srcs = [ ] ] static_libs = [ static_libs = [ "libbroadcastring", "libbufferhub", "libbufferhub", "libbufferhubqueue", "libbufferhubqueue", "libdisplay", "libvrsensor", "libvrsensor", "libdisplay", "libvirtualtouchpadclient", "libvirtualtouchpadclient", "libvr_hwc-impl", "libvr_hwc-impl", "libvr_hwc-binder", "libvr_hwc-binder", Loading