Loading libs/vr/libbufferhub/buffer_hub-test.cpp +32 −0 Original line number Original line Diff line number Diff line Loading @@ -945,3 +945,35 @@ TEST_F(LibBufferHubTest, TestDetachThenPromote) { EXPECT_EQ(b1_id, p2_id); EXPECT_EQ(b1_id, p2_id); EXPECT_TRUE(IsBufferGained(p2->buffer_state())); EXPECT_TRUE(IsBufferGained(p2->buffer_state())); } } TEST_F(LibBufferHubTest, TestDuplicateDetachedBuffer) { auto b1 = DetachedBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize); int b1_id = b1->id(); EXPECT_TRUE(b1->IsValid()); auto status_or_handle = b1->Duplicate(); EXPECT_TRUE(status_or_handle); // The detached buffer should still be valid. EXPECT_TRUE(b1->IsConnected()); EXPECT_TRUE(b1->IsValid()); // Gets the channel handle for the duplicated buffer. LocalChannelHandle h2 = status_or_handle.take(); EXPECT_TRUE(h2.valid()); std::unique_ptr<DetachedBuffer> b2 = DetachedBuffer::Import(std::move(h2)); EXPECT_FALSE(h2.valid()); ASSERT_TRUE(b2 != nullptr); int b2_id = b2->id(); // The duplicated buffer should inherit the same buffer id. EXPECT_EQ(b1_id, b2_id); // Promote the detached buffer should fail as b1 is no longer the exclusive // owner of the buffer.. status_or_handle = b1->Promote(); EXPECT_FALSE(status_or_handle.ok()); EXPECT_EQ(status_or_handle.error(), EINVAL); } libs/vr/libbufferhub/detached_buffer.cpp +14 −0 Original line number Original line Diff line number Diff line Loading @@ -104,6 +104,20 @@ Status<LocalChannelHandle> DetachedBuffer::Promote() { return status_or_handle; return status_or_handle; } } Status<LocalChannelHandle> DetachedBuffer::Duplicate() { ATRACE_NAME("DetachedBuffer::Duplicate"); ALOGD_IF(TRACE, "DetachedBuffer::Duplicate: id=%d.", id_); auto status_or_handle = client_.InvokeRemoteMethod<DetachedBufferRPC::Duplicate>(); if (!status_or_handle.ok()) { ALOGE("DetachedBuffer::Duplicate: Failed to duplicate buffer (id=%d): %s.", id_, status_or_handle.GetErrorMessage().c_str()); } return status_or_handle; } sp<GraphicBuffer> DetachedBuffer::TakeGraphicBuffer() { sp<GraphicBuffer> DetachedBuffer::TakeGraphicBuffer() { if (!client_.IsValid() || !buffer_.buffer()) { if (!client_.IsValid() || !buffer_.buffer()) { ALOGE("DetachedBuffer::TakeGraphicBuffer: Invalid buffer."); ALOGE("DetachedBuffer::TakeGraphicBuffer: Invalid buffer."); Loading libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h 0 → 100644 +89 −0 Original line number Original line Diff line number Diff line #ifndef ANDROID_DVR_BUFFER_HUB_DEFS_H_ #define ANDROID_DVR_BUFFER_HUB_DEFS_H_ #include <dvr/dvr_api.h> #include <hardware/gralloc.h> #include <atomic> namespace android { namespace dvr { namespace BufferHubDefs { static constexpr uint32_t kMetadataFormat = HAL_PIXEL_FORMAT_BLOB; static constexpr uint32_t kMetadataUsage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN; // Single producuer multiple (up to 63) consumers ownership signal. // 64-bit atomic unsigned int. // // MSB LSB // | | // v v // [P|C62|...|C1|C0] // Gain'ed state: [0|..|0|0] -> Exclusively Writable. // Post'ed state: [1|..|0|0] // Acquired'ed state: [1|..|X|X] -> At least one bit is set in lower 63 bits // Released'ed state: [0|..|X|X] -> At least one bit is set in lower 63 bits static constexpr uint64_t kProducerStateBit = 1ULL << 63; static constexpr uint64_t kConsumerStateMask = (1ULL << 63) - 1; static inline void ModifyBufferState(std::atomic<uint64_t>* buffer_state, uint64_t clear_mask, uint64_t set_mask) { uint64_t old_state; uint64_t new_state; do { old_state = buffer_state->load(); new_state = (old_state & ~clear_mask) | set_mask; } while (!buffer_state->compare_exchange_weak(old_state, new_state)); } static inline bool IsBufferGained(uint64_t state) { return state == 0; } static inline bool IsBufferPosted(uint64_t state, uint64_t consumer_bit = kConsumerStateMask) { return (state & kProducerStateBit) && !(state & consumer_bit); } static inline bool IsBufferAcquired(uint64_t state) { return (state & kProducerStateBit) && (state & kConsumerStateMask); } static inline bool IsBufferReleased(uint64_t state) { return !(state & kProducerStateBit) && (state & kConsumerStateMask); } static inline uint64_t FindNextClearedBit(uint64_t bits) { return ~bits - (~bits & (~bits - 1)); } static inline uint64_t FindFirstClearedBit() { return FindNextClearedBit(kProducerStateBit); } struct __attribute__((packed, aligned(8))) MetadataHeader { // Internal data format, which can be updated as long as the size, padding and // field alignment of the struct is consistent within the same ABI. As this // part is subject for future updates, it's not stable cross Android version, // so don't have it visible from outside of the Android platform (include Apps // and vendor HAL). std::atomic<uint64_t> buffer_state; std::atomic<uint64_t> fence_state; uint64_t queue_index; // Public data format, which should be updated with caution. See more details // in dvr_api.h DvrNativeBufferMetadata metadata; }; static_assert(sizeof(MetadataHeader) == 128, "Unexpected MetadataHeader size"); static constexpr size_t kMetadataHeaderSize = sizeof(MetadataHeader); } // namespace BufferHubDefs } // namespace dvr } // namespace android #endif // ANDROID_DVR_BUFFER_HUB_DEFS_H_ libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h +5 −68 Original line number Original line Diff line number Diff line #ifndef ANDROID_DVR_BUFFERHUB_RPC_H_ #ifndef ANDROID_DVR_BUFFERHUB_RPC_H_ #define ANDROID_DVR_BUFFERHUB_RPC_H_ #define ANDROID_DVR_BUFFERHUB_RPC_H_ #include "buffer_hub_defs.h" #include <cutils/native_handle.h> #include <cutils/native_handle.h> #include <sys/types.h> #include <ui/BufferQueueDefs.h> #include <ui/BufferQueueDefs.h> #include <dvr/dvr_api.h> #include <pdx/channel_handle.h> #include <pdx/channel_handle.h> #include <pdx/file_handle.h> #include <pdx/file_handle.h> #include <pdx/rpc/remote_method.h> #include <pdx/rpc/remote_method.h> Loading @@ -15,71 +15,6 @@ namespace android { namespace android { namespace dvr { namespace dvr { namespace BufferHubDefs { static constexpr uint32_t kMetadataFormat = HAL_PIXEL_FORMAT_BLOB; static constexpr uint32_t kMetadataUsage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN; // Single producuer multiple (up to 63) consumers ownership signal. // 64-bit atomic unsigned int. // // MSB LSB // | | // v v // [P|C62|...|C1|C0] // Gain'ed state: [0|..|0|0] -> Exclusively Writable. // Post'ed state: [1|..|0|0] // Acquired'ed state: [1|..|X|X] -> At least one bit is set in lower 63 bits // Released'ed state: [0|..|X|X] -> At least one bit is set in lower 63 bits static constexpr uint64_t kProducerStateBit = 1ULL << 63; static constexpr uint64_t kConsumerStateMask = (1ULL << 63) - 1; static inline void ModifyBufferState(std::atomic<uint64_t>* buffer_state, uint64_t clear_mask, uint64_t set_mask) { uint64_t old_state; uint64_t new_state; do { old_state = buffer_state->load(); new_state = (old_state & ~clear_mask) | set_mask; } while (!buffer_state->compare_exchange_weak(old_state, new_state)); } static inline bool IsBufferGained(uint64_t state) { return state == 0; } static inline bool IsBufferPosted(uint64_t state, uint64_t consumer_bit = kConsumerStateMask) { return (state & kProducerStateBit) && !(state & consumer_bit); } static inline bool IsBufferAcquired(uint64_t state) { return (state & kProducerStateBit) && (state & kConsumerStateMask); } static inline bool IsBufferReleased(uint64_t state) { return !(state & kProducerStateBit) && (state & kConsumerStateMask); } struct __attribute__((packed, aligned(8))) MetadataHeader { // Internal data format, which can be updated as long as the size, padding and // field alignment of the struct is consistent within the same ABI. As this // part is subject for future updates, it's not stable cross Android version, // so don't have it visible from outside of the Android platform (include Apps // and vendor HAL). std::atomic<uint64_t> buffer_state; std::atomic<uint64_t> fence_state; uint64_t queue_index; // Public data format, which should be updated with caution. See more details // in dvr_api.h DvrNativeBufferMetadata metadata; }; static_assert(sizeof(MetadataHeader) == 128, "Unexpected MetadataHeader size"); static constexpr size_t kMetadataHeaderSize = sizeof(MetadataHeader); } // namespace BufferHubDefs template <typename FileHandleType> template <typename FileHandleType> class NativeBufferHandle { class NativeBufferHandle { public: public: Loading Loading @@ -450,6 +385,7 @@ struct DetachedBufferRPC final : public BufferHubRPC { kOpCreate = kOpDetachedBufferBase, kOpCreate = kOpDetachedBufferBase, kOpImport, kOpImport, kOpPromote, kOpPromote, kOpDuplicate, }; }; public: public: Loading @@ -459,8 +395,9 @@ struct DetachedBufferRPC final : public BufferHubRPC { size_t user_metadata_size)); size_t user_metadata_size)); PDX_REMOTE_METHOD(Import, kOpImport, BufferDescription<LocalHandle>(Void)); PDX_REMOTE_METHOD(Import, kOpImport, BufferDescription<LocalHandle>(Void)); PDX_REMOTE_METHOD(Promote, kOpPromote, LocalChannelHandle(Void)); PDX_REMOTE_METHOD(Promote, kOpPromote, LocalChannelHandle(Void)); PDX_REMOTE_METHOD(Duplicate, kOpDuplicate, LocalChannelHandle(Void)); PDX_REMOTE_API(API, Create, Promote); PDX_REMOTE_API(API, Create, Import, Promote, Duplicate); }; }; } // namespace dvr } // namespace dvr Loading libs/vr/libbufferhub/include/private/dvr/detached_buffer.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -57,6 +57,9 @@ class DetachedBuffer { // return. Further IPCs towards this channel will return error. // return. Further IPCs towards this channel will return error. pdx::Status<pdx::LocalChannelHandle> Promote(); pdx::Status<pdx::LocalChannelHandle> Promote(); // Creates a DetachedBuffer from an existing one. pdx::Status<pdx::LocalChannelHandle> Duplicate(); // Takes the underlying graphic buffer out of this DetachedBuffer. This call // Takes the underlying graphic buffer out of this DetachedBuffer. This call // immediately invalidates this DetachedBuffer object and transfers the // immediately invalidates this DetachedBuffer object and transfers the // underlying pdx::LocalChannelHandle into the GraphicBuffer. // underlying pdx::LocalChannelHandle into the GraphicBuffer. Loading Loading
libs/vr/libbufferhub/buffer_hub-test.cpp +32 −0 Original line number Original line Diff line number Diff line Loading @@ -945,3 +945,35 @@ TEST_F(LibBufferHubTest, TestDetachThenPromote) { EXPECT_EQ(b1_id, p2_id); EXPECT_EQ(b1_id, p2_id); EXPECT_TRUE(IsBufferGained(p2->buffer_state())); EXPECT_TRUE(IsBufferGained(p2->buffer_state())); } } TEST_F(LibBufferHubTest, TestDuplicateDetachedBuffer) { auto b1 = DetachedBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize); int b1_id = b1->id(); EXPECT_TRUE(b1->IsValid()); auto status_or_handle = b1->Duplicate(); EXPECT_TRUE(status_or_handle); // The detached buffer should still be valid. EXPECT_TRUE(b1->IsConnected()); EXPECT_TRUE(b1->IsValid()); // Gets the channel handle for the duplicated buffer. LocalChannelHandle h2 = status_or_handle.take(); EXPECT_TRUE(h2.valid()); std::unique_ptr<DetachedBuffer> b2 = DetachedBuffer::Import(std::move(h2)); EXPECT_FALSE(h2.valid()); ASSERT_TRUE(b2 != nullptr); int b2_id = b2->id(); // The duplicated buffer should inherit the same buffer id. EXPECT_EQ(b1_id, b2_id); // Promote the detached buffer should fail as b1 is no longer the exclusive // owner of the buffer.. status_or_handle = b1->Promote(); EXPECT_FALSE(status_or_handle.ok()); EXPECT_EQ(status_or_handle.error(), EINVAL); }
libs/vr/libbufferhub/detached_buffer.cpp +14 −0 Original line number Original line Diff line number Diff line Loading @@ -104,6 +104,20 @@ Status<LocalChannelHandle> DetachedBuffer::Promote() { return status_or_handle; return status_or_handle; } } Status<LocalChannelHandle> DetachedBuffer::Duplicate() { ATRACE_NAME("DetachedBuffer::Duplicate"); ALOGD_IF(TRACE, "DetachedBuffer::Duplicate: id=%d.", id_); auto status_or_handle = client_.InvokeRemoteMethod<DetachedBufferRPC::Duplicate>(); if (!status_or_handle.ok()) { ALOGE("DetachedBuffer::Duplicate: Failed to duplicate buffer (id=%d): %s.", id_, status_or_handle.GetErrorMessage().c_str()); } return status_or_handle; } sp<GraphicBuffer> DetachedBuffer::TakeGraphicBuffer() { sp<GraphicBuffer> DetachedBuffer::TakeGraphicBuffer() { if (!client_.IsValid() || !buffer_.buffer()) { if (!client_.IsValid() || !buffer_.buffer()) { ALOGE("DetachedBuffer::TakeGraphicBuffer: Invalid buffer."); ALOGE("DetachedBuffer::TakeGraphicBuffer: Invalid buffer."); Loading
libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h 0 → 100644 +89 −0 Original line number Original line Diff line number Diff line #ifndef ANDROID_DVR_BUFFER_HUB_DEFS_H_ #define ANDROID_DVR_BUFFER_HUB_DEFS_H_ #include <dvr/dvr_api.h> #include <hardware/gralloc.h> #include <atomic> namespace android { namespace dvr { namespace BufferHubDefs { static constexpr uint32_t kMetadataFormat = HAL_PIXEL_FORMAT_BLOB; static constexpr uint32_t kMetadataUsage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN; // Single producuer multiple (up to 63) consumers ownership signal. // 64-bit atomic unsigned int. // // MSB LSB // | | // v v // [P|C62|...|C1|C0] // Gain'ed state: [0|..|0|0] -> Exclusively Writable. // Post'ed state: [1|..|0|0] // Acquired'ed state: [1|..|X|X] -> At least one bit is set in lower 63 bits // Released'ed state: [0|..|X|X] -> At least one bit is set in lower 63 bits static constexpr uint64_t kProducerStateBit = 1ULL << 63; static constexpr uint64_t kConsumerStateMask = (1ULL << 63) - 1; static inline void ModifyBufferState(std::atomic<uint64_t>* buffer_state, uint64_t clear_mask, uint64_t set_mask) { uint64_t old_state; uint64_t new_state; do { old_state = buffer_state->load(); new_state = (old_state & ~clear_mask) | set_mask; } while (!buffer_state->compare_exchange_weak(old_state, new_state)); } static inline bool IsBufferGained(uint64_t state) { return state == 0; } static inline bool IsBufferPosted(uint64_t state, uint64_t consumer_bit = kConsumerStateMask) { return (state & kProducerStateBit) && !(state & consumer_bit); } static inline bool IsBufferAcquired(uint64_t state) { return (state & kProducerStateBit) && (state & kConsumerStateMask); } static inline bool IsBufferReleased(uint64_t state) { return !(state & kProducerStateBit) && (state & kConsumerStateMask); } static inline uint64_t FindNextClearedBit(uint64_t bits) { return ~bits - (~bits & (~bits - 1)); } static inline uint64_t FindFirstClearedBit() { return FindNextClearedBit(kProducerStateBit); } struct __attribute__((packed, aligned(8))) MetadataHeader { // Internal data format, which can be updated as long as the size, padding and // field alignment of the struct is consistent within the same ABI. As this // part is subject for future updates, it's not stable cross Android version, // so don't have it visible from outside of the Android platform (include Apps // and vendor HAL). std::atomic<uint64_t> buffer_state; std::atomic<uint64_t> fence_state; uint64_t queue_index; // Public data format, which should be updated with caution. See more details // in dvr_api.h DvrNativeBufferMetadata metadata; }; static_assert(sizeof(MetadataHeader) == 128, "Unexpected MetadataHeader size"); static constexpr size_t kMetadataHeaderSize = sizeof(MetadataHeader); } // namespace BufferHubDefs } // namespace dvr } // namespace android #endif // ANDROID_DVR_BUFFER_HUB_DEFS_H_
libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h +5 −68 Original line number Original line Diff line number Diff line #ifndef ANDROID_DVR_BUFFERHUB_RPC_H_ #ifndef ANDROID_DVR_BUFFERHUB_RPC_H_ #define ANDROID_DVR_BUFFERHUB_RPC_H_ #define ANDROID_DVR_BUFFERHUB_RPC_H_ #include "buffer_hub_defs.h" #include <cutils/native_handle.h> #include <cutils/native_handle.h> #include <sys/types.h> #include <ui/BufferQueueDefs.h> #include <ui/BufferQueueDefs.h> #include <dvr/dvr_api.h> #include <pdx/channel_handle.h> #include <pdx/channel_handle.h> #include <pdx/file_handle.h> #include <pdx/file_handle.h> #include <pdx/rpc/remote_method.h> #include <pdx/rpc/remote_method.h> Loading @@ -15,71 +15,6 @@ namespace android { namespace android { namespace dvr { namespace dvr { namespace BufferHubDefs { static constexpr uint32_t kMetadataFormat = HAL_PIXEL_FORMAT_BLOB; static constexpr uint32_t kMetadataUsage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN; // Single producuer multiple (up to 63) consumers ownership signal. // 64-bit atomic unsigned int. // // MSB LSB // | | // v v // [P|C62|...|C1|C0] // Gain'ed state: [0|..|0|0] -> Exclusively Writable. // Post'ed state: [1|..|0|0] // Acquired'ed state: [1|..|X|X] -> At least one bit is set in lower 63 bits // Released'ed state: [0|..|X|X] -> At least one bit is set in lower 63 bits static constexpr uint64_t kProducerStateBit = 1ULL << 63; static constexpr uint64_t kConsumerStateMask = (1ULL << 63) - 1; static inline void ModifyBufferState(std::atomic<uint64_t>* buffer_state, uint64_t clear_mask, uint64_t set_mask) { uint64_t old_state; uint64_t new_state; do { old_state = buffer_state->load(); new_state = (old_state & ~clear_mask) | set_mask; } while (!buffer_state->compare_exchange_weak(old_state, new_state)); } static inline bool IsBufferGained(uint64_t state) { return state == 0; } static inline bool IsBufferPosted(uint64_t state, uint64_t consumer_bit = kConsumerStateMask) { return (state & kProducerStateBit) && !(state & consumer_bit); } static inline bool IsBufferAcquired(uint64_t state) { return (state & kProducerStateBit) && (state & kConsumerStateMask); } static inline bool IsBufferReleased(uint64_t state) { return !(state & kProducerStateBit) && (state & kConsumerStateMask); } struct __attribute__((packed, aligned(8))) MetadataHeader { // Internal data format, which can be updated as long as the size, padding and // field alignment of the struct is consistent within the same ABI. As this // part is subject for future updates, it's not stable cross Android version, // so don't have it visible from outside of the Android platform (include Apps // and vendor HAL). std::atomic<uint64_t> buffer_state; std::atomic<uint64_t> fence_state; uint64_t queue_index; // Public data format, which should be updated with caution. See more details // in dvr_api.h DvrNativeBufferMetadata metadata; }; static_assert(sizeof(MetadataHeader) == 128, "Unexpected MetadataHeader size"); static constexpr size_t kMetadataHeaderSize = sizeof(MetadataHeader); } // namespace BufferHubDefs template <typename FileHandleType> template <typename FileHandleType> class NativeBufferHandle { class NativeBufferHandle { public: public: Loading Loading @@ -450,6 +385,7 @@ struct DetachedBufferRPC final : public BufferHubRPC { kOpCreate = kOpDetachedBufferBase, kOpCreate = kOpDetachedBufferBase, kOpImport, kOpImport, kOpPromote, kOpPromote, kOpDuplicate, }; }; public: public: Loading @@ -459,8 +395,9 @@ struct DetachedBufferRPC final : public BufferHubRPC { size_t user_metadata_size)); size_t user_metadata_size)); PDX_REMOTE_METHOD(Import, kOpImport, BufferDescription<LocalHandle>(Void)); PDX_REMOTE_METHOD(Import, kOpImport, BufferDescription<LocalHandle>(Void)); PDX_REMOTE_METHOD(Promote, kOpPromote, LocalChannelHandle(Void)); PDX_REMOTE_METHOD(Promote, kOpPromote, LocalChannelHandle(Void)); PDX_REMOTE_METHOD(Duplicate, kOpDuplicate, LocalChannelHandle(Void)); PDX_REMOTE_API(API, Create, Promote); PDX_REMOTE_API(API, Create, Import, Promote, Duplicate); }; }; } // namespace dvr } // namespace dvr Loading
libs/vr/libbufferhub/include/private/dvr/detached_buffer.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -57,6 +57,9 @@ class DetachedBuffer { // return. Further IPCs towards this channel will return error. // return. Further IPCs towards this channel will return error. pdx::Status<pdx::LocalChannelHandle> Promote(); pdx::Status<pdx::LocalChannelHandle> Promote(); // Creates a DetachedBuffer from an existing one. pdx::Status<pdx::LocalChannelHandle> Duplicate(); // Takes the underlying graphic buffer out of this DetachedBuffer. This call // Takes the underlying graphic buffer out of this DetachedBuffer. This call // immediately invalidates this DetachedBuffer object and transfers the // immediately invalidates this DetachedBuffer object and transfers the // underlying pdx::LocalChannelHandle into the GraphicBuffer. // underlying pdx::LocalChannelHandle into the GraphicBuffer. Loading