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

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

Merge "buffer_hub_queue_client: Batch allocate buffers"

parents 55f14c39 8fa4e107
Loading
Loading
Loading
Loading
+57 −25
Original line number Diff line number Diff line
@@ -442,46 +442,78 @@ ProducerQueue::ProducerQueue(const ProducerQueueConfig& config,
  SetupQueue(status.get());
}

Status<void> ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
                                           uint32_t layer_count,
                                           uint32_t format, uint64_t usage,
                                           size_t* out_slot) {
  if (out_slot == nullptr) {
    ALOGE("ProducerQueue::AllocateBuffer: Parameter out_slot cannot be null.");
    return ErrorStatus(EINVAL);
  }

  if (is_full()) {
    ALOGE("ProducerQueue::AllocateBuffer queue is at maximum capacity: %zu",
          capacity());
Status<std::vector<size_t>> ProducerQueue::AllocateBuffers(
    uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
    uint64_t usage, size_t buffer_count) {
  if (capacity() + buffer_count > kMaxQueueCapacity) {
    ALOGE(
        "ProducerQueue::AllocateBuffers: queue is at capacity: %zu, cannot "
        "allocate %zu more buffer(s).",
        capacity(), buffer_count);
    return ErrorStatus(E2BIG);
  }

  const size_t kBufferCount = 1u;
  Status<std::vector<std::pair<LocalChannelHandle, size_t>>> status =
      InvokeRemoteMethod<BufferHubRPC::ProducerQueueAllocateBuffers>(
          width, height, layer_count, format, usage, kBufferCount);
          width, height, layer_count, format, usage, buffer_count);
  if (!status) {
    ALOGE("ProducerQueue::AllocateBuffer failed to create producer buffer: %s",
    ALOGE("ProducerQueue::AllocateBuffers: failed to allocate buffers: %s",
          status.GetErrorMessage().c_str());
    return status.error_status();
  }

  auto buffer_handle_slots = status.take();
  LOG_ALWAYS_FATAL_IF(buffer_handle_slots.size() != kBufferCount,
  LOG_ALWAYS_FATAL_IF(buffer_handle_slots.size() != buffer_count,
                      "BufferHubRPC::ProducerQueueAllocateBuffers should "
                      "return one and only one buffer handle.");
                      "return %zu buffer handle(s), but returned %zu instead.",
                      buffer_count, buffer_handle_slots.size());

  std::vector<size_t> buffer_slots;
  buffer_slots.reserve(buffer_count);

  // Bookkeeping for each buffer.
  for (auto& hs : buffer_handle_slots) {
    auto& buffer_handle = hs.first;
    size_t buffer_slot = hs.second;

    // Note that import might (though very unlikely) fail. If so, buffer_handle
    // will be closed and included in returned buffer_slots.
    if (AddBuffer(BufferProducer::Import(std::move(buffer_handle)),
                  buffer_slot)) {
      ALOGD_IF(TRACE, "ProducerQueue::AllocateBuffers: new buffer at slot: %zu",
               buffer_slot);
      buffer_slots.push_back(buffer_slot);
    }
  }

  if (buffer_slots.size() == 0) {
    // Error out if no buffer is allocated and improted.
    ALOGE(TRACE, "ProducerQueue::AllocateBuffers: no buffer allocated.");
    ErrorStatus(ENOMEM);
  }

  return {std::move(buffer_slots)};
}

Status<size_t> ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
                                             uint32_t layer_count,
                                             uint32_t format, uint64_t usage) {
  // We only allocate one buffer at a time.
  auto& buffer_handle = buffer_handle_slots[0].first;
  size_t buffer_slot = buffer_handle_slots[0].second;
  ALOGD_IF(TRACE,
           "ProducerQueue::AllocateBuffer, new buffer, channel_handle: %d",
           buffer_handle.value());
  constexpr size_t buffer_count = 1;
  auto status =
      AllocateBuffers(width, height, layer_count, format, usage, buffer_count);
  if (!status) {
    ALOGE("ProducerQueue::AllocateBuffer: Failed to allocate buffer: %s",
          status.GetErrorMessage().c_str());
    return status.error_status();
  }

  *out_slot = buffer_slot;
  return AddBuffer(BufferProducer::Import(std::move(buffer_handle)),
                   buffer_slot);
  if (status.get().size() == 0) {
    ALOGE(TRACE, "ProducerQueue::AllocateBuffer: no buffer allocated.");
    ErrorStatus(ENOMEM);
  }

  return {status.get()[0]};
}

Status<void> ProducerQueue::AddBuffer(
+2 −2
Original line number Diff line number Diff line
@@ -612,9 +612,8 @@ status_t BufferHubQueueProducer::AllocateBuffer(uint32_t width, uint32_t height,
                                                uint32_t layer_count,
                                                PixelFormat format,
                                                uint64_t usage) {
  size_t slot;
  auto status =
      queue_->AllocateBuffer(width, height, layer_count, format, usage, &slot);
      queue_->AllocateBuffer(width, height, layer_count, format, usage);
  if (!status) {
    ALOGE(
        "BufferHubQueueProducer::AllocateBuffer: Failed to allocate buffer: %s",
@@ -622,6 +621,7 @@ status_t BufferHubQueueProducer::AllocateBuffer(uint32_t width, uint32_t height,
    return NO_MEMORY;
  }

  size_t slot = status.get();
  auto buffer_producer = queue_->GetBuffer(slot);

  LOG_ALWAYS_FATAL_IF(buffer_producer == nullptr,
+12 −4
Original line number Diff line number Diff line
@@ -274,12 +274,20 @@ class ProducerQueue : public pdx::ClientBase<ProducerQueue, BufferHubQueue> {
        BufferHubQueue::GetBuffer(slot));
  }

  // Batch allocate buffers. Once allocated, producer buffers are automatically
  // enqueue'd into the ProducerQueue and available to use (i.e. in GAINED
  // state). Upon success, returns a list of slots for each buffer allocated.
  pdx::Status<std::vector<size_t>> AllocateBuffers(
      uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
      uint64_t usage, size_t buffer_count);

  // Allocate producer buffer to populate the queue. Once allocated, a producer
  // buffer is automatically enqueue'd into the ProducerQueue and available to
  // use (i.e. in GAINED state).
  pdx::Status<void> AllocateBuffer(uint32_t width, uint32_t height,
  // use (i.e. in GAINED state). Upon success, returns the slot number for the
  // buffer allocated.
  pdx::Status<size_t> AllocateBuffer(uint32_t width, uint32_t height,
                                     uint32_t layer_count, uint32_t format,
                                   uint64_t usage, size_t* out_slot);
                                     uint64_t usage);

  // Add a producer buffer to populate the queue. Once added, a producer buffer
  // is available to use (i.e. in GAINED state).
+11 −13
Original line number Diff line number Diff line
@@ -46,12 +46,12 @@ class BufferHubQueueTest : public ::testing::Test {

  void AllocateBuffer(size_t* slot_out = nullptr) {
    // Create producer buffer.
    size_t slot;
    auto status = producer_queue_->AllocateBuffer(
        kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
        kBufferUsage, &slot);
    ASSERT_TRUE(status.ok());
        kBufferUsage);

    ASSERT_TRUE(status.ok());
    size_t slot = status.take();
    if (slot_out)
      *slot_out = slot;
  }
@@ -478,13 +478,13 @@ TEST_F(BufferHubQueueTest, TestUsageSetMask) {
                           UsagePolicy{set_mask, 0, 0, 0}));

  // When allocation, leave out |set_mask| from usage bits on purpose.
  size_t slot;
  auto status = producer_queue_->AllocateBuffer(
      kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
      kBufferUsage & ~set_mask, &slot);
      kBufferUsage & ~set_mask);
  ASSERT_TRUE(status.ok());

  LocalHandle fence;
  size_t slot;
  auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
  ASSERT_TRUE(p1_status.ok());
  auto p1 = p1_status.take();
@@ -497,13 +497,13 @@ TEST_F(BufferHubQueueTest, TestUsageClearMask) {
                           UsagePolicy{0, clear_mask, 0, 0}));

  // When allocation, add |clear_mask| into usage bits on purpose.
  size_t slot;
  auto status = producer_queue_->AllocateBuffer(
      kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
      kBufferUsage | clear_mask, &slot);
      kBufferUsage | clear_mask);
  ASSERT_TRUE(status.ok());

  LocalHandle fence;
  size_t slot;
  auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
  ASSERT_TRUE(p1_status.ok());
  auto p1 = p1_status.take();
@@ -517,16 +517,15 @@ TEST_F(BufferHubQueueTest, TestUsageDenySetMask) {

  // Now that |deny_set_mask| is illegal, allocation without those bits should
  // be able to succeed.
  size_t slot;
  auto status = producer_queue_->AllocateBuffer(
      kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
      kBufferUsage & ~deny_set_mask, &slot);
      kBufferUsage & ~deny_set_mask);
  ASSERT_TRUE(status.ok());

  // While allocation with those bits should fail.
  status = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
                                           kBufferLayerCount, kBufferFormat,
                                           kBufferUsage | deny_set_mask, &slot);
                                           kBufferUsage | deny_set_mask);
  ASSERT_FALSE(status.ok());
  ASSERT_EQ(EINVAL, status.error());
}
@@ -538,16 +537,15 @@ TEST_F(BufferHubQueueTest, TestUsageDenyClearMask) {

  // Now that clearing |deny_clear_mask| is illegal (i.e. setting these bits are
  // mandatory), allocation with those bits should be able to succeed.
  size_t slot;
  auto status = producer_queue_->AllocateBuffer(
      kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
      kBufferUsage | deny_clear_mask, &slot);
      kBufferUsage | deny_clear_mask);
  ASSERT_TRUE(status.ok());

  // While allocation without those bits should fail.
  status = producer_queue_->AllocateBuffer(
      kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
      kBufferUsage & ~deny_clear_mask, &slot);
      kBufferUsage & ~deny_clear_mask);
  ASSERT_FALSE(status.ok());
  ASSERT_EQ(EINVAL, status.error());
}
+5 −13
Original line number Diff line number Diff line
@@ -145,21 +145,13 @@ Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(
  auto producer_queue = status.take();

  ALOGD_IF(TRACE, "Surface::CreateQueue: Allocating %zu buffers...", capacity);
  for (size_t i = 0; i < capacity; i++) {
    size_t slot;
    auto allocate_status = producer_queue->AllocateBuffer(
        width, height, layer_count, format, usage, &slot);
  auto allocate_status = producer_queue->AllocateBuffers(
      width, height, layer_count, format, usage, capacity);
  if (!allocate_status) {
      ALOGE(
          "Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
    ALOGE("Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
          producer_queue->id(), allocate_status.GetErrorMessage().c_str());
    return allocate_status.error_status();
  }
    ALOGD_IF(
        TRACE,
        "Surface::CreateQueue: Allocated buffer at slot=%zu of capacity=%zu",
        slot, capacity);
  }

  return {std::move(producer_queue)};
}
Loading