Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2e06c1cb authored by Jiwen 'Steve' Cai's avatar Jiwen 'Steve' Cai
Browse files

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
parent aac3a45b
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -945,3 +945,35 @@ TEST_F(LibBufferHubTest, TestDetachThenPromote) {
  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);
}
+14 −0
Original line number Diff line number Diff line
@@ -104,6 +104,20 @@ Status<LocalChannelHandle> DetachedBuffer::Promote() {
  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.");
+89 −0
Original line number 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_
+5 −68
Original line number Diff line number Diff line
#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 @@ struct DetachedBufferRPC final : public BufferHubRPC {
    kOpCreate = kOpDetachedBufferBase,
    kOpImport,
    kOpPromote,
    kOpDuplicate,
  };

 public:
@@ -459,8 +395,9 @@ struct DetachedBufferRPC final : public BufferHubRPC {
                         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
+3 −0
Original line number Diff line number Diff line
@@ -57,6 +57,9 @@ class DetachedBuffer {
  // 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.
Loading