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

Commit 9c2422bd authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add more attribute when creating ProducerQueue"

parents e0c8f8e4 6bffc67c
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