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

Commit 6bffc67c authored by Jiwen 'Steve' Cai's avatar Jiwen 'Steve' Cai
Browse files

Add more attribute when creating ProducerQueue

Add `is_async`, `default_width`, `default_height` and
`default_format`. Note that these attributes are currently treated as
immutable after queue gets created.

Bug: 38324405
Bug: 38430974
Bug: 36724099
Test: buffer_hub_queue_producer-test, buffer_hub_queue-test, dvr_api-test
Change-Id: Id242a15388a1f1457ad89d11336f5643685e8361
parent e4108256
Loading
Loading
Loading
Loading
+78 −2
Original line number Diff line number Diff line
@@ -130,12 +130,88 @@ using LocalFence = FenceHandle<pdx::LocalHandle>;
using BorrowedFence = FenceHandle<pdx::BorrowedHandle>;

struct ProducerQueueConfig {
  // Whether the buffer queue is operating in Async mode.
  // From GVR's perspective of view, this means a buffer can be acquired
  // asynchronously by the compositor.
  // From Android Surface's perspective of view, this is equivalent to
  // IGraphicBufferProducer's async mode. When in async mode, a producer
  // will never block even if consumer is running slow.
  bool is_async;

  // Default buffer width that is set during ProducerQueue's creation.
  uint32_t default_width;

  // Default buffer height that is set during ProducerQueue's creation.
  uint32_t default_height;

  // Default buffer format that is set during ProducerQueue's creation.
  uint32_t default_format;

  // Size of the meta data associated with all the buffers allocated from the
  // queue.
  size_t meta_size_bytes;

 private:
  PDX_SERIALIZABLE_MEMBERS(ProducerQueueConfig, meta_size_bytes);
  PDX_SERIALIZABLE_MEMBERS(ProducerQueueConfig, is_async, default_width,
                           default_height, default_format, meta_size_bytes);
};

class ProducerQueueConfigBuilder {
 public:
  // Build a ProducerQueueConfig object.
  ProducerQueueConfig Build() {
    return {is_async_, default_width_, default_height_, default_format_,
            meta_size_bytes_};
  }

  ProducerQueueConfigBuilder& SetIsAsync(bool is_async) {
    is_async_ = is_async;
    return *this;
  }

  ProducerQueueConfigBuilder& SetDefaultWidth(uint32_t width) {
    default_width_ = width;
    return *this;
  }

  ProducerQueueConfigBuilder& SetDefaultHeight(uint32_t height) {
    default_height_ = height;
    return *this;
  }

  ProducerQueueConfigBuilder& SetDefaultFormat(uint32_t format) {
    default_format_ = format;
    return *this;
  }

  template <typename Meta>
  ProducerQueueConfigBuilder& SetMetadata() {
    meta_size_bytes_ = sizeof(Meta);
    return *this;
  }

  ProducerQueueConfigBuilder& SetMetadataSize(size_t meta_size_bytes) {
    meta_size_bytes_ = meta_size_bytes;
    return *this;
  }

 private:
  bool is_async_{false};
  uint32_t default_width_{1};
  uint32_t default_height_{1};
  uint32_t default_format_{1};  // PIXEL_FORMAT_RGBA_8888
  size_t meta_size_bytes_{0};
};

// Explicit specializations of ProducerQueueConfigBuilder::Build for void
// metadata type.
template <>
inline ProducerQueueConfigBuilder&
ProducerQueueConfigBuilder::SetMetadata<void>() {
  meta_size_bytes_ = 0;
  return *this;
}

struct QueueInfo {
  ProducerQueueConfig producer_config;
  int id;
@@ -226,7 +302,7 @@ struct BufferHubRPC {

  // Buffer Queue Methods.
  PDX_REMOTE_METHOD(CreateProducerQueue, kOpCreateProducerQueue,
                    QueueInfo(size_t meta_size_bytes,
                    QueueInfo(const ProducerQueueConfig& producer_config,
                              const UsagePolicy& usage_policy));
  PDX_REMOTE_METHOD(CreateConsumerQueue, kOpCreateConsumerQueue,
                    LocalChannelHandle(Void));
+12 −7
Original line number Diff line number Diff line
@@ -105,14 +105,18 @@ Status<void> BufferHubQueue::ImportQueue() {
          status.GetErrorMessage().c_str());
    return ErrorStatus(status.error());
  } else {
    SetupQueue(status.get().producer_config.meta_size_bytes, status.get().id);
    SetupQueue(status.get());
    return {};
  }
}

void BufferHubQueue::SetupQueue(size_t meta_size_bytes, int id) {
  meta_size_ = meta_size_bytes;
  id_ = id;
void BufferHubQueue::SetupQueue(const QueueInfo& queue_info) {
  is_async_ = queue_info.producer_config.is_async;
  default_width_ = queue_info.producer_config.default_width;
  default_height_ = queue_info.producer_config.default_height;
  default_format_ = queue_info.producer_config.default_format;
  meta_size_ = queue_info.producer_config.meta_size_bytes;
  id_ = queue_info.id;
}

std::unique_ptr<ConsumerQueue> BufferHubQueue::CreateConsumerQueue() {
@@ -405,10 +409,11 @@ ProducerQueue::ProducerQueue(LocalChannelHandle handle)
  }
}

ProducerQueue::ProducerQueue(size_t meta_size, const UsagePolicy& usage)
ProducerQueue::ProducerQueue(const ProducerQueueConfig& config,
                             const UsagePolicy& usage)
    : BASE(BufferHubRPC::kClientPath) {
  auto status =
      InvokeRemoteMethod<BufferHubRPC::CreateProducerQueue>(meta_size, usage);
      InvokeRemoteMethod<BufferHubRPC::CreateProducerQueue>(config, usage);
  if (!status) {
    ALOGE("ProducerQueue::ProducerQueue: Failed to create producer queue: %s",
          status.GetErrorMessage().c_str());
@@ -416,7 +421,7 @@ ProducerQueue::ProducerQueue(size_t meta_size, const UsagePolicy& usage)
    return;
  }

  SetupQueue(status.get().producer_config.meta_size_bytes, status.get().id);
  SetupQueue(status.get());
}

Status<void> ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
+4 −2
Original line number Diff line number Diff line
@@ -11,8 +11,10 @@ namespace dvr {
/* static */
sp<BufferHubQueueProducer> BufferHubQueueProducer::Create() {
  sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer;
  producer->queue_ =
      ProducerQueue::Create<DvrNativeBufferMetadata>(UsagePolicy{});
  auto config = ProducerQueueConfigBuilder()
                    .SetMetadata<DvrNativeBufferMetadata>()
                    .Build();
  producer->queue_ = ProducerQueue::Create(config, UsagePolicy{});
  return producer;
}

+23 −26
Original line number Diff line number Diff line
@@ -33,14 +33,17 @@ class BufferHubQueue : public pdx::Client {
  // participation in lifecycle events.
  std::unique_ptr<ConsumerQueue> CreateSilentConsumerQueue();

  // Returns whether the buffer queue is in async mode.
  bool is_async() const { return is_async_; }

  // Returns the default buffer width of this buffer queue.
  size_t default_width() const { return default_width_; }
  uint32_t default_width() const { return default_width_; }

  // Returns the default buffer height of this buffer queue.
  size_t default_height() const { return default_height_; }
  uint32_t default_height() const { return default_height_; }

  // Returns the default buffer format of this buffer queue.
  int32_t default_format() const { return default_format_; }
  uint32_t default_format() const { return default_format_; }

  // Creates a new consumer in handle form for immediate transport over RPC.
  pdx::Status<pdx::LocalChannelHandle> CreateConsumerQueueHandle();
@@ -99,7 +102,7 @@ class BufferHubQueue : public pdx::Client {
  pdx::Status<void> ImportQueue();

  // Sets up the queue with the given parameters.
  void SetupQueue(size_t meta_size_bytes_, int id);
  void SetupQueue(const QueueInfo& queue_info);

  // Register a buffer for management by the queue. Used by subclasses to add a
  // buffer to internal bookkeeping.
@@ -182,17 +185,22 @@ class BufferHubQueue : public pdx::Client {
    return index == BufferHubQueue::kEpollQueueEventIndex;
  }

  // Default buffer width that can be set to override the buffer width when a
  // width and height of 0 are specified in AllocateBuffer.
  // Whether the buffer queue is operating in Async mode.
  // From GVR's perspective of view, this means a buffer can be acquired
  // asynchronously by the compositor.
  // From Android Surface's perspective of view, this is equivalent to
  // IGraphicBufferProducer's async mode. When in async mode, a producer
  // will never block even if consumer is running slow.
  bool is_async_{false};

  // Default buffer width that is set during ProducerQueue's creation.
  size_t default_width_{1};

  // Default buffer height that can be set to override the buffer height when a
  // width and height of 0 are specified in AllocateBuffer.
  // Default buffer height that is set during ProducerQueue's creation.
  size_t default_height_{1};

  // Default buffer format that can be set to override the buffer format when it
  // isn't specified in AllocateBuffer.
  int32_t default_format_{PIXEL_FORMAT_RGBA_8888};
  // Default buffer format that is set during ProducerQueue's creation.
  int32_t default_format_{1};  // PIXEL_FORMAT_RGBA_8888

  // Tracks the buffers belonging to this queue. Buffers are stored according to
  // "slot" in this vector. Each slot is a logical id of the buffer within this
@@ -234,13 +242,9 @@ class ProducerQueue : public pdx::ClientBase<ProducerQueue, BufferHubQueue> {
  // this will be rejected. Note that |usage_deny_set_mask| and
  // |usage_deny_clear_mask| shall not conflict with each other. Such
  // configuration will be treated as invalid input on creation.
  template <typename Meta>
  static std::unique_ptr<ProducerQueue> Create(const UsagePolicy& usage) {
    return BASE::Create(sizeof(Meta), usage);
  }
  static std::unique_ptr<ProducerQueue> Create(size_t meta_size_bytes,
                                               const UsagePolicy& usage) {
    return BASE::Create(meta_size_bytes, usage);
  static std::unique_ptr<ProducerQueue> Create(
      const ProducerQueueConfig& config, const UsagePolicy& usage) {
    return BASE::Create(config, usage);
  }

  // Import a ProducerQueue from a channel handle.
@@ -291,19 +295,12 @@ class ProducerQueue : public pdx::ClientBase<ProducerQueue, BufferHubQueue> {
  // static template methods inherited from ClientBase, which take the same
  // arguments as the constructors.
  explicit ProducerQueue(pdx::LocalChannelHandle handle);
  ProducerQueue(size_t meta_size, const UsagePolicy& usage);
  ProducerQueue(const ProducerQueueConfig& config, const UsagePolicy& usage);

  pdx::Status<Entry> OnBufferReady(
      const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) override;
};

// Explicit specializations of ProducerQueue::Create for void metadata type.
template <>
inline std::unique_ptr<ProducerQueue> ProducerQueue::Create<void>(
    const UsagePolicy& usage) {
  return ProducerQueue::Create(0, usage);
}

class ConsumerQueue : public BufferHubQueue {
 public:
  // Get a buffer consumer. Note that the method doesn't check whether the
+58 −23
Original line number Diff line number Diff line
@@ -16,17 +16,17 @@ using pdx::LocalHandle;

namespace {

constexpr int kBufferWidth = 100;
constexpr int kBufferHeight = 1;
constexpr int kBufferLayerCount = 1;
constexpr int kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
constexpr int kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;
constexpr uint32_t kBufferWidth = 100;
constexpr uint32_t kBufferHeight = 1;
constexpr uint32_t kBufferLayerCount = 1;
constexpr uint32_t kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
constexpr uint64_t kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY;

class BufferHubQueueTest : public ::testing::Test {
 public:
  template <typename Meta>
  bool CreateProducerQueue(const UsagePolicy& usage) {
    producer_queue_ = ProducerQueue::Create<Meta>(usage);
  bool CreateProducerQueue(const ProducerQueueConfig& config,
                           const UsagePolicy& usage) {
    producer_queue_ = ProducerQueue::Create(config, usage);
    return producer_queue_ != nullptr;
  }

@@ -39,9 +39,9 @@ class BufferHubQueueTest : public ::testing::Test {
    }
  }

  template <typename Meta>
  bool CreateQueues(const UsagePolicy& usage) {
    return CreateProducerQueue<Meta>(usage) && CreateConsumerQueue();
  bool CreateQueues(const ProducerQueueConfig& config,
                    const UsagePolicy& usage) {
    return CreateProducerQueue(config, usage) && CreateConsumerQueue();
  }

  void AllocateBuffer(size_t* slot_out = nullptr) {
@@ -57,6 +57,7 @@ class BufferHubQueueTest : public ::testing::Test {
  }

 protected:
  ProducerQueueConfigBuilder config_builder_;
  std::unique_ptr<ProducerQueue> producer_queue_;
  std::unique_ptr<ConsumerQueue> consumer_queue_;
};
@@ -64,7 +65,8 @@ class BufferHubQueueTest : public ::testing::Test {
TEST_F(BufferHubQueueTest, TestDequeue) {
  const size_t nb_dequeue_times = 16;

  ASSERT_TRUE(CreateQueues<size_t>(UsagePolicy{}));
  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<size_t>().Build(),
                           UsagePolicy{}));

  // Allocate only one buffer.
  AllocateBuffer();
@@ -94,7 +96,8 @@ TEST_F(BufferHubQueueTest, TestProducerConsumer) {
  size_t slot;
  uint64_t seq;

  ASSERT_TRUE(CreateQueues<uint64_t>(UsagePolicy{}));
  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<uint64_t>().Build(),
                           UsagePolicy{}));

  for (size_t i = 0; i < kBufferCount; i++) {
    AllocateBuffer();
@@ -165,7 +168,7 @@ TEST_F(BufferHubQueueTest, TestProducerConsumer) {
}

TEST_F(BufferHubQueueTest, TestDetach) {
  ASSERT_TRUE(CreateProducerQueue<void>(UsagePolicy{}));
  ASSERT_TRUE(CreateProducerQueue(config_builder_.Build(), UsagePolicy{}));

  // Allocate buffers.
  const size_t kBufferCount = 4u;
@@ -268,7 +271,9 @@ TEST_F(BufferHubQueueTest, TestDetach) {
}

TEST_F(BufferHubQueueTest, TestMultipleConsumers) {
  ASSERT_TRUE(CreateProducerQueue<void>(UsagePolicy{}));
  // ProducerConfigureBuilder doesn't set Metadata{size}, which means there
  // is no metadata associated with this BufferQueue's buffer.
  ASSERT_TRUE(CreateProducerQueue(config_builder_.Build(), UsagePolicy{}));

  // Allocate buffers.
  const size_t kBufferCount = 4u;
@@ -346,7 +351,9 @@ struct TestMetadata {
};

TEST_F(BufferHubQueueTest, TestMetadata) {
  ASSERT_TRUE(CreateQueues<TestMetadata>(UsagePolicy{}));
  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<TestMetadata>().Build(),
                           UsagePolicy{}));

  AllocateBuffer();

  std::vector<TestMetadata> ms = {
@@ -372,7 +379,9 @@ TEST_F(BufferHubQueueTest, TestMetadata) {
}

TEST_F(BufferHubQueueTest, TestMetadataMismatch) {
  ASSERT_TRUE(CreateQueues<int64_t>(UsagePolicy{}));
  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
                           UsagePolicy{}));

  AllocateBuffer();

  int64_t mi = 3;
@@ -391,7 +400,8 @@ TEST_F(BufferHubQueueTest, TestMetadataMismatch) {
}

TEST_F(BufferHubQueueTest, TestEnqueue) {
  ASSERT_TRUE(CreateQueues<int64_t>(UsagePolicy{}));
  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
                           UsagePolicy{}));
  AllocateBuffer();

  size_t slot;
@@ -408,7 +418,8 @@ TEST_F(BufferHubQueueTest, TestEnqueue) {
}

TEST_F(BufferHubQueueTest, TestAllocateBuffer) {
  ASSERT_TRUE(CreateQueues<int64_t>(UsagePolicy{}));
  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
                           UsagePolicy{}));

  size_t s1;
  AllocateBuffer();
@@ -463,7 +474,8 @@ TEST_F(BufferHubQueueTest, TestAllocateBuffer) {

TEST_F(BufferHubQueueTest, TestUsageSetMask) {
  const uint32_t set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
  ASSERT_TRUE(CreateQueues<int64_t>(UsagePolicy{set_mask, 0, 0, 0}));
  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
                           UsagePolicy{set_mask, 0, 0, 0}));

  // When allocation, leave out |set_mask| from usage bits on purpose.
  size_t slot;
@@ -481,7 +493,8 @@ TEST_F(BufferHubQueueTest, TestUsageSetMask) {

TEST_F(BufferHubQueueTest, TestUsageClearMask) {
  const uint32_t clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
  ASSERT_TRUE(CreateQueues<int64_t>(UsagePolicy{0, clear_mask, 0, 0}));
  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
                           UsagePolicy{0, clear_mask, 0, 0}));

  // When allocation, add |clear_mask| into usage bits on purpose.
  size_t slot;
@@ -499,7 +512,8 @@ TEST_F(BufferHubQueueTest, TestUsageClearMask) {

TEST_F(BufferHubQueueTest, TestUsageDenySetMask) {
  const uint32_t deny_set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
  ASSERT_TRUE(CreateQueues<int64_t>(UsagePolicy{0, 0, deny_set_mask, 0}));
  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
                           UsagePolicy{0, 0, deny_set_mask, 0}));

  // Now that |deny_set_mask| is illegal, allocation without those bits should
  // be able to succeed.
@@ -519,7 +533,8 @@ TEST_F(BufferHubQueueTest, TestUsageDenySetMask) {

TEST_F(BufferHubQueueTest, TestUsageDenyClearMask) {
  const uint32_t deny_clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
  ASSERT_TRUE(CreateQueues<int64_t>(UsagePolicy{0, 0, 0, deny_clear_mask}));
  ASSERT_TRUE(CreateQueues(config_builder_.SetMetadata<int64_t>().Build(),
                           UsagePolicy{0, 0, 0, deny_clear_mask}));

  // Now that clearing |deny_clear_mask| is illegal (i.e. setting these bits are
  // mandatory), allocation with those bits should be able to succeed.
@@ -537,6 +552,26 @@ TEST_F(BufferHubQueueTest, TestUsageDenyClearMask) {
  ASSERT_EQ(EINVAL, status.error());
}

TEST_F(BufferHubQueueTest, TestQueueInfo) {
  static const bool kIsAsync = true;
  ASSERT_TRUE(CreateQueues(config_builder_.SetIsAsync(kIsAsync)
                               .SetDefaultWidth(kBufferWidth)
                               .SetDefaultHeight(kBufferHeight)
                               .SetDefaultFormat(kBufferFormat)
                               .Build(),
                           UsagePolicy{}));

  EXPECT_EQ(producer_queue_->default_width(), kBufferWidth);
  EXPECT_EQ(producer_queue_->default_height(), kBufferHeight);
  EXPECT_EQ(producer_queue_->default_format(), kBufferFormat);
  EXPECT_EQ(producer_queue_->is_async(), kIsAsync);

  EXPECT_EQ(consumer_queue_->default_width(), kBufferWidth);
  EXPECT_EQ(consumer_queue_->default_height(), kBufferHeight);
  EXPECT_EQ(consumer_queue_->default_format(), kBufferFormat);
  EXPECT_EQ(consumer_queue_->is_async(), kIsAsync);
}

}  // namespace

}  // namespace dvr
Loading