Move core data structure of DetachedBuffer into BufferNode
1/ Supports mutiple DetachedBuffer(s) to be created from a single
BufferNode.
2/ Separate core data structure and logic (i.e. BufferNode) out of the
IPC layer (i.e. DetachedBufferChannel).
3/ DetachedBufferChannel will be renamed to BufferChannel in future
and becomes the universal backend of GraphicBuffer. Thus we are naming
the new class BufferNode instead of DetachedBufferNode.
4/ Move BufferHubDefs out of bufferhub_rpc.h, as BufferHubDefs is not
directly related to the PDX IPCm echanism.
Bug: 112011098
Bug: 112012812
Bug: 111976433
Bug: 70046255
Test: buffer_hub-test
Change-Id: Ieba19329a0e823c78f21611462dedacdad3aab85
diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
index e247398..2a962b5 100644
--- a/libs/vr/libbufferhub/buffer_hub-test.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -945,3 +945,35 @@
EXPECT_EQ(b1_id, p2_id);
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);
+}
diff --git a/libs/vr/libbufferhub/detached_buffer.cpp b/libs/vr/libbufferhub/detached_buffer.cpp
index 6fae16d..60f11e2 100644
--- a/libs/vr/libbufferhub/detached_buffer.cpp
+++ b/libs/vr/libbufferhub/detached_buffer.cpp
@@ -104,6 +104,20 @@
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() {
if (!client_.IsValid() || !buffer_.buffer()) {
ALOGE("DetachedBuffer::TakeGraphicBuffer: Invalid buffer.");
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h
new file mode 100644
index 0000000..8b2bf91
--- /dev/null
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h
@@ -0,0 +1,89 @@
+#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_
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index 088a235..e163216 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -1,11 +1,11 @@
#ifndef ANDROID_DVR_BUFFERHUB_RPC_H_
#define ANDROID_DVR_BUFFERHUB_RPC_H_
+#include "buffer_hub_defs.h"
+
#include <cutils/native_handle.h>
-#include <sys/types.h>
#include <ui/BufferQueueDefs.h>
-#include <dvr/dvr_api.h>
#include <pdx/channel_handle.h>
#include <pdx/file_handle.h>
#include <pdx/rpc/remote_method.h>
@@ -15,71 +15,6 @@
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);
-}
-
-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>
class NativeBufferHandle {
public:
@@ -450,6 +385,7 @@
kOpCreate = kOpDetachedBufferBase,
kOpImport,
kOpPromote,
+ kOpDuplicate,
};
public:
@@ -459,8 +395,9 @@
size_t user_metadata_size));
PDX_REMOTE_METHOD(Import, kOpImport, BufferDescription<LocalHandle>(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
diff --git a/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h b/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h
index 6d0b502..376b53e 100644
--- a/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h
@@ -57,6 +57,9 @@
// return. Further IPCs towards this channel will return error.
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
// immediately invalidates this DetachedBuffer object and transfers the
// underlying pdx::LocalChannelHandle into the GraphicBuffer.