#include "include/private/dvr/buffer_hub_queue_producer.h"
+#include <dvr/dvr_api.h>
#include <inttypes.h>
#include <log/log.h>
namespace android {
namespace dvr {
-BufferHubQueueProducer::BufferHubQueueProducer(
- const std::shared_ptr<BufferHubQueueCore>& core)
- : core_(core) {}
+/* static */
+sp<BufferHubQueueProducer> BufferHubQueueProducer::Create() {
+ sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer;
+ producer->queue_ = ProducerQueue::Create<DvrNativeBufferMetadata>();
+ return producer;
+}
+
+/* static */
+sp<BufferHubQueueProducer> BufferHubQueueProducer::Create(
+ const std::shared_ptr<ProducerQueue>& queue) {
+ if (queue->metadata_size() != sizeof(DvrNativeBufferMetadata)) {
+ ALOGE(
+ "BufferHubQueueProducer::Create producer's metadata size is different "
+ "than the size of DvrNativeBufferMetadata");
+ return nullptr;
+ }
+
+ sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer;
+ producer->queue_ = queue;
+ return producer;
+}
status_t BufferHubQueueProducer::requestBuffer(int slot,
sp<GraphicBuffer>* buf) {
ALOGD_IF(TRACE, "requestBuffer: slot=%d", slot);
- std::unique_lock<std::mutex> lock(core_->mutex_);
+ std::unique_lock<std::mutex> lock(mutex_);
- if (core_->connected_api_ == BufferHubQueueCore::kNoConnectedApi) {
+ if (connected_api_ == kNoConnectedApi) {
ALOGE("requestBuffer: BufferHubQueueProducer has no connected producer");
return NO_INIT;
}
ALOGE("requestBuffer: slot index %d out of range [0, %d)", slot,
max_buffer_count_);
return BAD_VALUE;
- } else if (!core_->buffers_[slot].mBufferState.isDequeued()) {
+ } else if (!buffers_[slot].mBufferState.isDequeued()) {
ALOGE("requestBuffer: slot %d is not owned by the producer (state = %s)",
- slot, core_->buffers_[slot].mBufferState.string());
+ slot, buffers_[slot].mBufferState.string());
return BAD_VALUE;
- } else if (core_->buffers_[slot].mGraphicBuffer != nullptr) {
+ } else if (buffers_[slot].mGraphicBuffer != nullptr) {
ALOGE("requestBuffer: slot %d is not empty.", slot);
return BAD_VALUE;
- } else if (core_->buffers_[slot].mBufferProducer == nullptr) {
+ } else if (buffers_[slot].mBufferProducer == nullptr) {
ALOGE("requestBuffer: slot %d is not dequeued.", slot);
return BAD_VALUE;
}
- const auto& buffer_producer = core_->buffers_[slot].mBufferProducer;
+ const auto& buffer_producer = buffers_[slot].mBufferProducer;
sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
- core_->buffers_[slot].mGraphicBuffer = graphic_buffer;
- core_->buffers_[slot].mRequestBufferCalled = true;
+ buffers_[slot].mGraphicBuffer = graphic_buffer;
+ buffers_[slot].mRequestBufferCalled = true;
*buf = graphic_buffer;
return NO_ERROR;
ALOGD_IF(TRACE, "setMaxDequeuedBufferCount: max_dequeued_buffers=%d",
max_dequeued_buffers);
- std::unique_lock<std::mutex> lock(core_->mutex_);
+ std::unique_lock<std::mutex> lock(mutex_);
if (max_dequeued_buffers <= 0 ||
max_dequeued_buffers >
static_cast<int>(BufferHubQueue::kMaxQueueCapacity -
- BufferHubQueueCore::kDefaultUndequeuedBuffers)) {
+ kDefaultUndequeuedBuffers)) {
ALOGE("setMaxDequeuedBufferCount: %d out of range (0, %zu]",
max_dequeued_buffers, BufferHubQueue::kMaxQueueCapacity);
return BAD_VALUE;
// The new dequeued_buffers count should not be violated by the number
// of currently dequeued buffers.
int dequeued_count = 0;
- for (const auto& buf : core_->buffers_) {
+ for (const auto& buf : buffers_) {
if (buf.mBufferState.isDequeued()) {
dequeued_count++;
}
height, format, usage);
status_t ret;
- std::unique_lock<std::mutex> lock(core_->mutex_);
+ std::unique_lock<std::mutex> lock(mutex_);
- if (core_->connected_api_ == BufferHubQueueCore::kNoConnectedApi) {
+ if (connected_api_ == kNoConnectedApi) {
ALOGE("dequeueBuffer: BufferQueue has no connected producer");
return NO_INIT;
}
const uint32_t kLayerCount = 1;
- if (static_cast<int32_t>(core_->producer_->capacity()) <
- max_dequeued_buffer_count_ +
- BufferHubQueueCore::kDefaultUndequeuedBuffers) {
- // Lazy allocation. When the capacity of |core_->producer_| has not reach
+ if (static_cast<int32_t>(queue_->capacity()) <
+ max_dequeued_buffer_count_ + kDefaultUndequeuedBuffers) {
+ // Lazy allocation. When the capacity of |queue_| has not reached
// |max_dequeued_buffer_count_|, allocate new buffer.
// TODO(jwcai) To save memory, the really reasonable thing to do is to go
// over existing slots and find first existing one to dequeue.
- ret = core_->AllocateBuffer(width, height, kLayerCount, format, usage);
+ ret = AllocateBuffer(width, height, kLayerCount, format, usage);
if (ret < 0)
return ret;
}
for (size_t retry = 0; retry < BufferHubQueue::kMaxQueueCapacity; retry++) {
LocalHandle fence;
- auto buffer_status =
- core_->producer_->Dequeue(core_->dequeue_timeout_ms_, &slot, &fence);
+ auto buffer_status = queue_->Dequeue(dequeue_timeout_ms_, &slot, &fence);
buffer_producer = buffer_status.take();
if (!buffer_producer)
buffer_producer->height(), buffer_producer->format());
// Mark the slot as reallocating, so that later we can set
// BUFFER_NEEDS_REALLOCATION when the buffer actually get dequeued.
- core_->buffers_[slot].mIsReallocating = true;
+ buffers_[slot].mIsReallocating = true;
- // Detach the old buffer once the allocation before allocating its
+ // Remove the old buffer once the allocation before allocating its
// replacement.
- core_->DetachBuffer(slot);
+ RemoveBuffer(slot);
// Allocate a new producer buffer with new buffer configs. Note that if
// there are already multiple buffers in the queue, the next one returned
- // from |core_->producer_->Dequeue| may not be the new buffer we just
- // reallocated. Retry up to BufferHubQueue::kMaxQueueCapacity times.
- ret = core_->AllocateBuffer(width, height, kLayerCount, format, usage);
+ // from |queue_->Dequeue| may not be the new buffer we just reallocated.
+ // Retry up to BufferHubQueue::kMaxQueueCapacity times.
+ ret = AllocateBuffer(width, height, kLayerCount, format, usage);
if (ret < 0)
return ret;
}
// With the BufferHub backed solution. Buffer slot returned from
- // |core_->producer_->Dequeue| is guaranteed to avaiable for producer's use.
+ // |queue_->Dequeue| is guaranteed to avaiable for producer's use.
// It's either in free state (if the buffer has never been used before) or
// in queued state (if the buffer has been dequeued and queued back to
// BufferHubQueue).
// TODO(jwcai) Clean this up, make mBufferState compatible with BufferHub's
// model.
- LOG_ALWAYS_FATAL_IF((!core_->buffers_[slot].mBufferState.isFree() &&
- !core_->buffers_[slot].mBufferState.isQueued()),
+ LOG_ALWAYS_FATAL_IF((!buffers_[slot].mBufferState.isFree() &&
+ !buffers_[slot].mBufferState.isQueued()),
"dequeueBuffer: slot %zu is not free or queued.", slot);
- core_->buffers_[slot].mBufferState.freeQueued();
- core_->buffers_[slot].mBufferState.dequeue();
+ buffers_[slot].mBufferState.freeQueued();
+ buffers_[slot].mBufferState.dequeue();
ALOGD_IF(TRACE, "dequeueBuffer: slot=%zu", slot);
// TODO(jwcai) Handle fence properly. |BufferHub| has full fence support, we
*out_slot = slot;
ret = NO_ERROR;
- if (core_->buffers_[slot].mIsReallocating) {
+ if (buffers_[slot].mIsReallocating) {
ret |= BUFFER_NEEDS_REALLOCATION;
- core_->buffers_[slot].mIsReallocating = false;
+ buffers_[slot].mIsReallocating = false;
}
return ret;
}
status_t ret;
- std::unique_lock<std::mutex> lock(core_->mutex_);
+ std::unique_lock<std::mutex> lock(mutex_);
- if (core_->connected_api_ == BufferHubQueueCore::kNoConnectedApi) {
+ if (connected_api_ == kNoConnectedApi) {
ALOGE("queueBuffer: BufferQueue has no connected producer");
return NO_INIT;
}
ALOGE("queueBuffer: slot index %d out of range [0, %d)", slot,
max_buffer_count_);
return BAD_VALUE;
- } else if (!core_->buffers_[slot].mBufferState.isDequeued()) {
+ } else if (!buffers_[slot].mBufferState.isDequeued()) {
ALOGE("queueBuffer: slot %d is not owned by the producer (state = %s)",
- slot, core_->buffers_[slot].mBufferState.string());
+ slot, buffers_[slot].mBufferState.string());
return BAD_VALUE;
- } else if ((!core_->buffers_[slot].mRequestBufferCalled ||
- core_->buffers_[slot].mGraphicBuffer == nullptr)) {
+ } else if ((!buffers_[slot].mRequestBufferCalled ||
+ buffers_[slot].mGraphicBuffer == nullptr)) {
ALOGE(
"queueBuffer: slot %d is not requested (mRequestBufferCalled=%d, "
"mGraphicBuffer=%p)",
- slot, core_->buffers_[slot].mRequestBufferCalled,
- core_->buffers_[slot].mGraphicBuffer.get());
+ slot, buffers_[slot].mRequestBufferCalled,
+ buffers_[slot].mGraphicBuffer.get());
return BAD_VALUE;
}
// Post the buffer producer with timestamp in the metadata.
- const auto& buffer_producer = core_->buffers_[slot].mBufferProducer;
+ const auto& buffer_producer = buffers_[slot].mBufferProducer;
// Check input crop is not out of boundary of current buffer.
Rect buffer_rect(buffer_producer->width(), buffer_producer->height());
LocalHandle fence_fd(fence->isValid() ? fence->dup() : -1);
- BufferHubQueueCore::NativeBufferMetadata meta_data = {};
+ DvrNativeBufferMetadata meta_data = {};
meta_data.timestamp = timestamp;
meta_data.is_auto_timestamp = static_cast<int32_t>(is_auto_timestamp);
meta_data.dataspace = static_cast<int32_t>(dataspace);
meta_data.transform = static_cast<int32_t>(transform);
buffer_producer->Post(fence_fd, &meta_data, sizeof(meta_data));
- core_->buffers_[slot].mBufferState.queue();
+ buffers_[slot].mBufferState.queue();
output->width = buffer_producer->width();
output->height = buffer_producer->height();
const sp<Fence>& fence) {
ALOGD_IF(TRACE, __FUNCTION__);
- std::unique_lock<std::mutex> lock(core_->mutex_);
+ std::unique_lock<std::mutex> lock(mutex_);
- if (core_->connected_api_ == BufferHubQueueCore::kNoConnectedApi) {
+ if (connected_api_ == kNoConnectedApi) {
ALOGE("cancelBuffer: BufferQueue has no connected producer");
return NO_INIT;
}
ALOGE("cancelBuffer: slot index %d out of range [0, %d)", slot,
max_buffer_count_);
return BAD_VALUE;
- } else if (!core_->buffers_[slot].mBufferState.isDequeued()) {
+ } else if (!buffers_[slot].mBufferState.isDequeued()) {
ALOGE("cancelBuffer: slot %d is not owned by the producer (state = %s)",
- slot, core_->buffers_[slot].mBufferState.string());
+ slot, buffers_[slot].mBufferState.string());
return BAD_VALUE;
} else if (fence == nullptr) {
ALOGE("cancelBuffer: fence is NULL");
return BAD_VALUE;
}
- auto buffer_producer = core_->buffers_[slot].mBufferProducer;
- core_->producer_->Enqueue(buffer_producer, slot);
- core_->buffers_[slot].mBufferState.cancel();
- core_->buffers_[slot].mFence = fence;
+ auto buffer_producer = buffers_[slot].mBufferProducer;
+ queue_->Enqueue(buffer_producer, slot);
+ buffers_[slot].mBufferState.cancel();
+ buffers_[slot].mFence = fence;
ALOGD_IF(TRACE, "cancelBuffer: slot %d", slot);
return NO_ERROR;
status_t BufferHubQueueProducer::query(int what, int* out_value) {
ALOGD_IF(TRACE, __FUNCTION__);
- std::unique_lock<std::mutex> lock(core_->mutex_);
+ std::unique_lock<std::mutex> lock(mutex_);
if (out_value == nullptr) {
ALOGE("query: out_value was NULL");
// TODO(b/36187402) This should be the maximum number of buffers that this
// producer queue's consumer can acquire. Set to be at least one. Need to
// find a way to set from the consumer side.
- value = BufferHubQueueCore::kDefaultUndequeuedBuffers;
+ value = kDefaultUndequeuedBuffers;
break;
case NATIVE_WINDOW_BUFFER_AGE:
value = 0;
break;
case NATIVE_WINDOW_WIDTH:
- value = core_->producer_->default_width();
+ value = queue_->default_width();
break;
case NATIVE_WINDOW_HEIGHT:
- value = core_->producer_->default_height();
+ value = queue_->default_height();
break;
case NATIVE_WINDOW_FORMAT:
- value = core_->producer_->default_format();
+ value = queue_->default_format();
break;
case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
// BufferHubQueue is always operating in async mode, thus semantically
// there is no way dvr::ConsumerQueue can set it.
value = 0;
break;
+ case NATIVE_WINDOW_CONSUMER_IS_PROTECTED:
+ // In Daydream's implementation, the consumer end (i.e. VR Compostior)
+ // knows how to handle protected buffers.
+ value = 1;
+ break;
default:
return BAD_VALUE;
}
return BAD_VALUE;
}
- std::unique_lock<std::mutex> lock(core_->mutex_);
+ std::unique_lock<std::mutex> lock(mutex_);
- if (core_->connected_api_ != BufferHubQueueCore::kNoConnectedApi) {
+ if (connected_api_ != kNoConnectedApi) {
return BAD_VALUE;
}
case NATIVE_WINDOW_API_CPU:
case NATIVE_WINDOW_API_MEDIA:
case NATIVE_WINDOW_API_CAMERA:
- core_->connected_api_ = api;
+ connected_api_ = api;
- output->width = core_->producer_->default_width();
- output->height = core_->producer_->default_height();
+ output->width = queue_->default_width();
+ output->height = queue_->default_height();
// default values, we don't use them yet.
output->transformHint = 0;
// parameter checks here.
ALOGD_IF(TRACE, __FUNCTION__);
- std::unique_lock<std::mutex> lock(core_->mutex_);
+ std::unique_lock<std::mutex> lock(mutex_);
- if (BufferHubQueueCore::kNoConnectedApi == core_->connected_api_) {
+ if (kNoConnectedApi == connected_api_) {
return NO_INIT;
- } else if (api != core_->connected_api_) {
+ } else if (api != connected_api_) {
return BAD_VALUE;
}
- core_->connected_api_ = BufferHubQueueCore::kNoConnectedApi;
+ connected_api_ = kNoConnectedApi;
return NO_ERROR;
}
uint32_t generation_number) {
ALOGD_IF(TRACE, __FUNCTION__);
- std::unique_lock<std::mutex> lock(core_->mutex_);
- core_->generation_number_ = generation_number;
+ std::unique_lock<std::mutex> lock(mutex_);
+ generation_number_ = generation_number;
return NO_ERROR;
}
status_t BufferHubQueueProducer::setDequeueTimeout(nsecs_t timeout) {
ALOGD_IF(TRACE, __FUNCTION__);
- std::unique_lock<std::mutex> lock(core_->mutex_);
- core_->dequeue_timeout_ms_ = static_cast<int>(timeout / (1000 * 1000));
+ std::unique_lock<std::mutex> lock(mutex_);
+ dequeue_timeout_ms_ = static_cast<int>(timeout / (1000 * 1000));
return NO_ERROR;
}
status_t BufferHubQueueProducer::getUniqueId(uint64_t* out_id) const {
ALOGD_IF(TRACE, __FUNCTION__);
- *out_id = core_->unique_id_;
+ *out_id = unique_id_;
+ return NO_ERROR;
+}
+
+status_t BufferHubQueueProducer::AllocateBuffer(uint32_t width, uint32_t height,
+ uint32_t layer_count,
+ PixelFormat format,
+ uint64_t usage) {
+ size_t slot;
+
+ if (queue_->AllocateBuffer(width, height, layer_count, format, usage, &slot) <
+ 0) {
+ ALOGE("Failed to allocate new buffer in BufferHub.");
+ return NO_MEMORY;
+ }
+
+ auto buffer_producer = queue_->GetBuffer(slot);
+
+ LOG_ALWAYS_FATAL_IF(buffer_producer == nullptr,
+ "Failed to get buffer producer at slot: %zu", slot);
+
+ buffers_[slot].mBufferProducer = buffer_producer;
+
return NO_ERROR;
}
-IBinder* BufferHubQueueProducer::onAsBinder() {
- // BufferHubQueueProducer is a non-binder implementation of
- // IGraphicBufferProducer.
- ALOGW("BufferHubQueueProducer::onAsBinder is not efficiently supported.");
- return this;
+status_t BufferHubQueueProducer::RemoveBuffer(size_t slot) {
+ int ret = queue_->DetachBuffer(slot);
+ if (ret < 0) {
+ ALOGE("BufferHubQueueProducer::RemoveBuffer failed through RPC, ret=%s",
+ strerror(-ret));
+ return ret;
+ }
+
+ // Reset in memory objects related the the buffer.
+ buffers_[slot].mBufferProducer = nullptr;
+ buffers_[slot].mGraphicBuffer = nullptr;
+ buffers_[slot].mBufferState.detachProducer();
+ return NO_ERROR;
}
} // namespace dvr
+++ /dev/null
-#ifndef ANDROID_DVR_BUFFER_HUB_QUEUE_CORE_H_
-#define ANDROID_DVR_BUFFER_HUB_QUEUE_CORE_H_
-
-#include <private/dvr/buffer_hub_queue_client.h>
-
-#include <gui/BufferSlot.h>
-#include <utils/Atomic.h>
-#include <utils/String8.h>
-
-#include <mutex>
-
-namespace android {
-namespace dvr {
-
-class BufferHubQueueCore {
- private:
- friend class BufferHubQueueProducer;
-
- public:
- static constexpr int kNoConnectedApi = -1;
-
- // TODO(b/36187402) The actual implementation of BufferHubQueue's consumer
- // side logic doesn't limit the number of buffer it can acquire
- // simultaneously. We need a way for consumer logic to configure and enforce
- // that.
- static constexpr int kDefaultUndequeuedBuffers = 1;
-
- // Create a BufferHubQueueCore instance by creating a new producer queue.
- static std::shared_ptr<BufferHubQueueCore> Create();
-
- // Create a BufferHubQueueCore instance by importing an existing prodcuer
- // queue.
- static std::shared_ptr<BufferHubQueueCore> Create(
- const std::shared_ptr<ProducerQueue>& producer);
-
- // The buffer metadata that an Android Surface (a.k.a. ANativeWindow)
- // will populate. This must be aligned with the |DvrNativeBufferMetadata|
- // defined in |dvr_buffer_queue.h|. Please do not remove, modify, or reorder
- // existing data members. If new fields need to be added, please take extra
- // care to make sure that new data field is padded properly the size of the
- // struct stays same.
- // TODO(b/37578558) Move |dvr_api.h| into a header library so that this
- // structure won't be copied between |dvr_api.h| and |buffer_hub_qeue_core.h|.
- struct NativeBufferMetadata {
- // Timestamp of the frame.
- int64_t timestamp;
-
- // Whether the buffer is using auto timestamp.
- int32_t is_auto_timestamp;
-
- // Must be one of the HAL_DATASPACE_XXX value defined in system/graphics.h
- int32_t dataspace;
-
- // Crop extracted from an ACrop or android::Crop object.
- int32_t crop_left;
- int32_t crop_top;
- int32_t crop_right;
- int32_t crop_bottom;
-
- // Must be one of the NATIVE_WINDOW_SCALING_MODE_XXX value defined in
- // system/window.h.
- int32_t scaling_mode;
-
- // Must be one of the ANATIVEWINDOW_TRANSFORM_XXX value defined in
- // android/native_window.h
- int32_t transform;
-
- // Reserved bytes for so that the struct is forward compatible.
- int32_t reserved[16];
- };
-
- class NativeBuffer
- : public ANativeObjectBase<ANativeWindowBuffer, NativeBuffer, RefBase> {
- public:
- explicit NativeBuffer(const std::shared_ptr<BufferHubBuffer>& buffer)
- : buffer_(buffer) {
- ANativeWindowBuffer::width = buffer_->width();
- ANativeWindowBuffer::height = buffer_->height();
- ANativeWindowBuffer::stride = buffer_->stride();
- ANativeWindowBuffer::format = buffer_->format();
- ANativeWindowBuffer::usage = buffer_->usage();
- ANativeWindowBuffer::handle = buffer_->buffer()->handle();
- }
-
- std::shared_ptr<BufferHubBuffer> buffer() { return buffer_; }
-
- private:
- std::shared_ptr<BufferHubBuffer> buffer_;
- };
-
- // Get the unique buffer producer queue backing this BufferHubQueue.
- std::shared_ptr<ProducerQueue> GetProducerQueue() { return producer_; }
-
- private:
- using LocalHandle = pdx::LocalHandle;
-
- struct BufferHubSlot : public BufferSlot {
- BufferHubSlot() : mBufferProducer(nullptr), mIsReallocating(false) {}
- // BufferSlot comes from android framework, using m prefix to comply with
- // the name convention with the reset of data fields from BufferSlot.
- std::shared_ptr<BufferProducer> mBufferProducer;
- bool mIsReallocating;
- };
-
- static String8 getUniqueName() {
- static volatile int32_t counter = 0;
- return String8::format("unnamed-%d-%d", getpid(),
- android_atomic_inc(&counter));
- }
-
- static uint64_t getUniqueId() {
- static std::atomic<uint32_t> counter{0};
- static uint64_t id = static_cast<uint64_t>(getpid()) << 32;
- return id | counter++;
- }
-
- // Private constructor to force use of |Create|.
- BufferHubQueueCore();
-
- // Allocate a new buffer producer through BufferHub.
- int AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count,
- PixelFormat format, uint64_t usage);
-
- // Detach a buffer producer through BufferHub.
- int DetachBuffer(size_t slot);
-
- // Mutex for thread safety.
- std::mutex mutex_;
-
- // Connect client API, should be one of the NATIVE_WINDOW_API_* flags.
- int connected_api_{kNoConnectedApi};
-
- // |buffers_| stores the buffers that have been dequeued from
- // |dvr::BufferHubQueue|, It is initialized to invalid buffers, and gets
- // filled in with the result of |Dequeue|.
- // TODO(jwcai) The buffer allocated to a slot will also be replaced if the
- // requested buffer usage or geometry differs from that of the buffer
- // allocated to a slot.
- BufferHubSlot buffers_[BufferHubQueue::kMaxQueueCapacity];
-
- // Concreate implementation backed by BufferHubBuffer.
- std::shared_ptr<ProducerQueue> producer_;
-
- // |generation_number_| stores the current generation number of the attached
- // producer. Any attempt to attach a buffer with a different generation
- // number will fail.
- uint32_t generation_number_;
-
- // Sets how long dequeueBuffer or attachBuffer will block if a buffer or
- // slot is not yet available. The timeout is stored in milliseconds.
- int dequeue_timeout_ms_;
-
- const uint64_t unique_id_;
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_BUFFER_HUB_QUEUE_CORE_H_
#ifndef ANDROID_DVR_BUFFER_HUB_QUEUE_PRODUCER_H_
#define ANDROID_DVR_BUFFER_HUB_QUEUE_PRODUCER_H_
-#include <private/dvr/buffer_hub_queue_core.h>
-
#include <gui/IGraphicBufferProducer.h>
+#include <private/dvr/buffer_hub_queue_client.h>
namespace android {
namespace dvr {
-class BufferHubQueueProducer : public BnInterface<IGraphicBufferProducer> {
+class BufferHubQueueProducer : public BnGraphicBufferProducer {
public:
- BufferHubQueueProducer(const std::shared_ptr<BufferHubQueueCore>& core);
+ static constexpr int kNoConnectedApi = -1;
+
+ // TODO(b/36187402) The actual implementation of BufferHubQueue's consumer
+ // side logic doesn't limit the number of buffer it can acquire
+ // simultaneously. We need a way for consumer logic to configure and enforce
+ // that.
+ static constexpr int kDefaultUndequeuedBuffers = 1;
+
+ // Create a BufferHubQueueProducer instance by creating a new producer queue.
+ static sp<BufferHubQueueProducer> Create();
+
+ // Create a BufferHubQueueProducer instance by importing an existing prodcuer
+ // queue.
+ static sp<BufferHubQueueProducer> Create(
+ const std::shared_ptr<ProducerQueue>& producer);
// See |IGraphicBufferProducer::requestBuffer|
status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override;
// See |IGraphicBufferProducer::getUniqueId|
status_t getUniqueId(uint64_t* out_id) const override;
- protected:
- IBinder* onAsBinder() override;
-
private:
using LocalHandle = pdx::LocalHandle;
- // |core_| holds the actually buffer slots.
- std::shared_ptr<BufferHubQueueCore> core_;
+ // Private constructor to force use of |Create|.
+ BufferHubQueueProducer() {}
+
+ static uint64_t genUniqueId() {
+ static std::atomic<uint32_t> counter{0};
+ static uint64_t id = static_cast<uint64_t>(getpid()) << 32;
+ return id | counter++;
+ }
+
+ // Allocate new buffer through BufferHub and add it into |queue_| for
+ // bookkeeping.
+ status_t AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count,
+ PixelFormat format, uint64_t usage);
+
+ // Remove a buffer via BufferHubRPC.
+ status_t RemoveBuffer(size_t slot);
+
+ // Concreate implementation backed by BufferHubBuffer.
+ std::shared_ptr<ProducerQueue> queue_;
+
+ // Mutex for thread safety.
+ std::mutex mutex_;
+
+ // Connect client API, should be one of the NATIVE_WINDOW_API_* flags.
+ int connected_api_{kNoConnectedApi};
// |max_buffer_count_| sets the capacity of the underlying buffer queue.
int32_t max_buffer_count_{BufferHubQueue::kMaxQueueCapacity};
// |max_dequeued_buffer_count_| set the maximum number of buffers that can
// be dequeued at the same momment.
int32_t max_dequeued_buffer_count_{1};
+
+ // Sets how long dequeueBuffer or attachBuffer will block if a buffer or
+ // slot is not yet available. The timeout is stored in milliseconds.
+ int dequeue_timeout_ms_{BufferHubQueue::kNoTimeOut};
+
+ // |generation_number_| stores the current generation number of the attached
+ // producer. Any attempt to attach a buffer with a different generation
+ // number will fail.
+ // TOOD(b/38137191) Currently not used as we don't support
+ // IGraphicBufferProducer::detachBuffer.
+ uint32_t generation_number_{0};
+
+ // |buffers_| stores the buffers that have been dequeued from
+ // |dvr::BufferHubQueue|, It is initialized to invalid buffers, and gets
+ // filled in with the result of |Dequeue|.
+ // TODO(jwcai) The buffer allocated to a slot will also be replaced if the
+ // requested buffer usage or geometry differs from that of the buffer
+ // allocated to a slot.
+ struct BufferHubSlot : public BufferSlot {
+ BufferHubSlot() : mBufferProducer(nullptr), mIsReallocating(false) {}
+ // BufferSlot comes from android framework, using m prefix to comply with
+ // the name convention with the reset of data fields from BufferSlot.
+ std::shared_ptr<BufferProducer> mBufferProducer;
+ bool mIsReallocating;
+ };
+ BufferHubSlot buffers_[BufferHubQueue::kMaxQueueCapacity];
+
+ // A uniqueId used by IGraphicBufferProducer interface.
+ const uint64_t unique_id_{genUniqueId()};
};
} // namespace dvr