From 638b7f747df50374d1e91c2496da41f293394e19 Mon Sep 17 00:00:00 2001 From: Jiwen 'Steve' Cai Date: Fri, 8 Sep 2017 11:10:29 -0700 Subject: [PATCH] Overhual DvrBuffer and DvrBufferQueue API: Step 1 Adding new APIs: dvrWriteBufferQueueGainBuffer dvrWriteBufferQueuePostBuffer dvrReadBufferQueueAcquireBuffer dvrReadBufferQueueReleaseBuffer Those new APIs streamlines DVR buffer operations: 1/ It allows static Dvr{Read,Write}Buffer objects to be statically allocated with the queue. 2/ Symentric Gain/Post on WriteBufferQueue and Acquire/Release on ReadBufferQueue. 3/ Use fixed buffer metadata. 4/ This is also a prerequisite to using shared memory based metadata and async buffer IPC. More details and discussion at: go/gvr-async-bufferhub Special note regarding DVR API order in this CL: The new buffer queue API entries are inserted before new PoseClient API as the PoseClient is still blocked from being released and the new BufferQueue APIs are expected to be released sooner than that. Bug: 65455724 Bug: 65468551 Bug: 65458332 Bug: 65165821 Test: dvr_api-test Change-Id: Iae8e7787d696d72ebf7457df9f98f4467cd20932 --- .../include/private/dvr/buffer_hub_queue_client.h | 7 +- libs/vr/libdvr/dvr_buffer.cpp | 18 +- libs/vr/libdvr/dvr_buffer_queue.cpp | 233 +++++++++++++++++- libs/vr/libdvr/dvr_buffer_queue_internal.h | 24 +- libs/vr/libdvr/dvr_internal.h | 10 + libs/vr/libdvr/include/dvr/dvr_api.h | 15 ++ libs/vr/libdvr/include/dvr/dvr_api_entries.h | 6 + libs/vr/libdvr/include/dvr/dvr_buffer_queue.h | 72 ++++-- libs/vr/libdvr/tests/Android.bp | 1 + libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp | 273 ++++++--------------- 10 files changed, 434 insertions(+), 225 deletions(-) diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h index 3e93788521..0699fefd38 100644 --- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h +++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h @@ -66,6 +66,11 @@ class BufferHubQueue : public pdx::Client { explicit operator bool() const { return epoll_fd_.IsValid(); } + int GetBufferId(size_t slot) const { + return (slot < buffers_.size() && buffers_[slot]) ? buffers_[slot]->id() + : -1; + } + std::shared_ptr GetBuffer(size_t slot) const { return buffers_[slot]; } @@ -218,7 +223,7 @@ class BufferHubQueue : public pdx::Client { // 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 // queue regardless of its queue position or presence in the ring buffer. - std::vector> buffers_{kMaxQueueCapacity}; + std::array, kMaxQueueCapacity> buffers_; // Buffers and related data that are available for dequeue. RingBuffer available_buffers_{kMaxQueueCapacity}; diff --git a/libs/vr/libdvr/dvr_buffer.cpp b/libs/vr/libdvr/dvr_buffer.cpp index 4d9b215361..1a9923444e 100644 --- a/libs/vr/libdvr/dvr_buffer.cpp +++ b/libs/vr/libdvr/dvr_buffer.cpp @@ -44,7 +44,13 @@ void dvrWriteBufferCreateEmpty(DvrWriteBuffer** write_buffer) { } void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer) { - delete write_buffer; + if (write_buffer != nullptr) { + ALOGW_IF( + write_buffer->slot != -1, + "dvrWriteBufferDestroy: Destroying a buffer associated with a valid " + "buffer queue slot. This may indicate possible leaks."); + delete write_buffer; + } } int dvrWriteBufferIsValid(DvrWriteBuffer* write_buffer) { @@ -107,7 +113,15 @@ void dvrReadBufferCreateEmpty(DvrReadBuffer** read_buffer) { *read_buffer = new DvrReadBuffer; } -void dvrReadBufferDestroy(DvrReadBuffer* read_buffer) { delete read_buffer; } +void dvrReadBufferDestroy(DvrReadBuffer* read_buffer) { + if (read_buffer != nullptr) { + ALOGW_IF( + read_buffer->slot != -1, + "dvrReadBufferDestroy: Destroying a buffer associated with a valid " + "buffer queue slot. This may indicate possible leaks."); + delete read_buffer; + } +} int dvrReadBufferIsValid(DvrReadBuffer* read_buffer) { return read_buffer && read_buffer->read_buffer; diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp index 4adb5d2da1..035252d0b9 100644 --- a/libs/vr/libdvr/dvr_buffer_queue.cpp +++ b/libs/vr/libdvr/dvr_buffer_queue.cpp @@ -63,7 +63,7 @@ int DvrWriteBufferQueue::CreateReadQueue(DvrReadBufferQueue** out_read_queue) { } int DvrWriteBufferQueue::Dequeue(int timeout, DvrWriteBuffer* write_buffer, - int* out_fence_fd) { + int* out_fence_fd, size_t* out_slot) { size_t slot; pdx::LocalHandle fence; std::shared_ptr buffer_producer; @@ -141,6 +141,86 @@ int DvrWriteBufferQueue::Dequeue(int timeout, DvrWriteBuffer* write_buffer, write_buffer->write_buffer = std::move(buffer_producer); *out_fence_fd = fence.Release(); + if (out_slot) { + // TODO(b/65469368): Remove this null check once dvrWriteBufferQueueDequeue + // is deprecated. + *out_slot = slot; + } + return 0; +} + +int DvrWriteBufferQueue::GainBuffer(int timeout, + DvrWriteBuffer** out_write_buffer, + DvrNativeBufferMetadata* out_meta, + int* out_fence_fd) { + DvrWriteBuffer write_buffer; + int fence_fd; + size_t slot; + const int ret = Dequeue(timeout, &write_buffer, &fence_fd, &slot); + if (ret < 0) { + ALOGE_IF( + ret != -ETIMEDOUT, + "DvrWriteBufferQueue::GainBuffer: Failed to dequeue buffer, ret=%d", + ret); + return ret; + } + + if (write_buffers_[slot] == nullptr) { + // Lazy initialization of a write_buffers_ slot. Note that a slot will only + // be dynamically allocated once during the entire cycle life of a queue. + write_buffers_[slot] = std::make_unique(); + write_buffers_[slot]->slot = slot; + } + + LOG_ALWAYS_FATAL_IF( + write_buffers_[slot]->write_buffer, + "DvrWriteBufferQueue::GainBuffer: Buffer slot is not empty: %zu", slot); + write_buffers_[slot]->write_buffer = std::move(write_buffer.write_buffer); + + *out_write_buffer = write_buffers_[slot].release(); + *out_fence_fd = fence_fd; + + return 0; +} + +int DvrWriteBufferQueue::PostBuffer(DvrWriteBuffer* write_buffer, + const DvrNativeBufferMetadata* meta, + int ready_fence_fd) { + LOG_FATAL_IF( + (write_buffers->slot < 0 || write_buffers->slot >= write_buffers_.size()), + "DvrWriteBufferQueue::ReleaseBuffer: Invalid slot: %zu", slot); + + // Some basic sanity checks before we put the buffer back into a slot. + size_t slot = static_cast(write_buffer->slot); + if (write_buffers_[slot] != nullptr) { + ALOGE("DvrWriteBufferQueue::PostBuffer: Slot is not empty: %zu", slot); + return -EINVAL; + } + if (write_buffer->write_buffer == nullptr) { + ALOGE("DvrWriteBufferQueue::PostBuffer: Invalid write buffer."); + return -EINVAL; + } + if (write_buffer->write_buffer->id() != producer_queue_->GetBufferId(slot)) { + ALOGE( + "DvrWriteBufferQueue::PostBuffer: Buffer to be released does not " + "belong to this buffer queue."); + return -EINVAL; + } + + pdx::LocalHandle fence(ready_fence_fd); + // TODO(b/65455724): All BufferHub operations should be async. + const int ret = write_buffer->write_buffer->Post(fence, meta, sizeof(*meta)); + if (ret < 0) { + ALOGE("DvrWriteBufferQueue::PostBuffer: Failed to post buffer, ret=%d", + ret); + return ret; + } + + // Put the DvrWriteBuffer pointer back into its slot for reuse. + write_buffers_[slot].reset(write_buffer); + // It's import to reset the write buffer client now. It should stay invalid + // until next GainBuffer on the same slot. + write_buffers_[slot]->write_buffer = nullptr; return 0; } @@ -236,7 +316,29 @@ int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout, if (!write_queue || !write_buffer || !out_fence_fd) return -EINVAL; - return write_queue->Dequeue(timeout, write_buffer, out_fence_fd); + // TODO(b/65469368): Deprecate this API once new GainBuffer API is in use. + return write_queue->Dequeue(timeout, write_buffer, out_fence_fd, nullptr); +} + +int dvrWriteBufferQueueGainBuffer(DvrWriteBufferQueue* write_queue, int timeout, + DvrWriteBuffer** out_write_buffer, + DvrNativeBufferMetadata* out_meta, + int* out_fence_fd) { + if (!write_queue || !out_write_buffer || !out_meta || !out_fence_fd) + return -EINVAL; + + return write_queue->GainBuffer(timeout, out_write_buffer, out_meta, + out_fence_fd); +} + +int dvrWriteBufferQueuePostBuffer(DvrWriteBufferQueue* write_queue, + DvrWriteBuffer* write_buffer, + const DvrNativeBufferMetadata* meta, + int ready_fence_fd) { + if (!write_queue || !write_buffer || !write_buffer->write_buffer || !meta) + return -EINVAL; + + return write_queue->PostBuffer(write_buffer, meta, ready_fence_fd); } int dvrWriteBufferQueueResizeBuffer(DvrWriteBufferQueue* write_queue, @@ -268,8 +370,8 @@ int DvrReadBufferQueue::CreateReadQueue(DvrReadBufferQueue** out_read_queue) { } int DvrReadBufferQueue::Dequeue(int timeout, DvrReadBuffer* read_buffer, - int* out_fence_fd, void* out_meta, - size_t meta_size_bytes) { + int* out_fence_fd, size_t* out_slot, + void* out_meta, size_t meta_size_bytes) { if (meta_size_bytes != consumer_queue_->metadata_size()) { ALOGE( "DvrReadBufferQueue::Dequeue: Invalid metadata size, expected (%zu), " @@ -291,6 +393,95 @@ int DvrReadBufferQueue::Dequeue(int timeout, DvrReadBuffer* read_buffer, read_buffer->read_buffer = buffer_status.take(); *out_fence_fd = acquire_fence.Release(); + + if (out_slot) { + // TODO(b/65469368): Remove this null check once dvrReadBufferQueueDequeue + // is deprecated. + *out_slot = slot; + } + return 0; +} + +int DvrReadBufferQueue::AcquireBuffer(int timeout, + DvrReadBuffer** out_read_buffer, + DvrNativeBufferMetadata* out_meta, + int* out_fence_fd) { + DvrReadBuffer read_buffer; + int fence_fd; + size_t slot; + const int ret = Dequeue(timeout, &read_buffer, &fence_fd, &slot, out_meta, + sizeof(*out_meta)); + if (ret < 0) { + ALOGE_IF( + ret != -ETIMEDOUT, + "DvrReadBufferQueue::AcquireBuffer: Failed to dequeue buffer, error=%d", + ret); + return ret; + } + + if (read_buffers_[slot] == nullptr) { + // Lazy initialization of a read_buffers_ slot. Note that a slot will only + // be dynamically allocated once during the entire cycle life of a queue. + read_buffers_[slot] = std::make_unique(); + read_buffers_[slot]->slot = slot; + } + + LOG_FATAL_IF( + read_buffers_[slot]->read_buffer, + "DvrReadBufferQueue::AcquireBuffer: Buffer slot is not empty: %zu", slot); + read_buffers_[slot]->read_buffer = std::move(read_buffer.read_buffer); + + *out_read_buffer = read_buffers_[slot].release(); + *out_fence_fd = fence_fd; + + return 0; +} + +int DvrReadBufferQueue::ReleaseBuffer(DvrReadBuffer* read_buffer, + const DvrNativeBufferMetadata* meta, + int release_fence_fd) { + LOG_FATAL_IF( + (read_buffers->slot < 0 || read_buffers->slot >= read_buffers_size()), + "DvrReadBufferQueue::ReleaseBuffer: Invalid slot: %zu", slot); + + // Some basic sanity checks before we put the buffer back into a slot. + size_t slot = static_cast(read_buffer->slot); + if (read_buffers_[slot] != nullptr) { + ALOGE("DvrReadBufferQueue::ReleaseBuffer: Slot is not empty: %zu", slot); + return -EINVAL; + } + if (read_buffer->read_buffer == nullptr) { + ALOGE("DvrReadBufferQueue::ReleaseBuffer: Invalid read buffer."); + return -EINVAL; + } + if (read_buffer->read_buffer->id() != consumer_queue_->GetBufferId(slot)) { + ALOGE( + "DvrReadBufferQueue::ReleaseBuffer: Buffer to be released does not " + "belong to this buffer queue."); + return -EINVAL; + } + + pdx::LocalHandle fence(release_fence_fd); + int ret = 0; + if (fence) { + ret = read_buffer->read_buffer->Release(fence); + } else { + // TODO(b/65458354): Send metadata back to producer once shared memory based + // metadata is implemented. + // TODO(b/65455724): All BufferHub operations should be async. + ret = read_buffer->read_buffer->ReleaseAsync(); + } + if (ret < 0) { + ALOGE("DvrReadBufferQueue::ReleaseBuffer: Failed to release buffer, ret=%d", + ret); + return ret; + } + + // Put the DvrReadBuffer pointer back into its slot for reuse. + read_buffers_[slot].reset(read_buffer); + // It's import to reset the read buffer client now. It should stay invalid + // until next AcquireBuffer on the same slot. + read_buffers_[slot]->read_buffer = nullptr; return 0; } @@ -311,9 +502,11 @@ void DvrReadBufferQueue::SetBufferRemovedCallback( } else { consumer_queue_->SetBufferRemovedCallback( [callback, context](const std::shared_ptr& buffer) { - DvrReadBuffer read_buffer{ - std::static_pointer_cast(buffer)}; - callback(&read_buffer, context); + // When buffer is removed from the queue, the slot is already invalid. + auto read_buffer = std::make_unique(); + read_buffer->read_buffer = + std::static_pointer_cast(buffer); + callback(read_buffer.release(), context); }); } } @@ -366,8 +559,30 @@ int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout, if (meta_size_bytes != 0 && !out_meta) return -EINVAL; - return read_queue->Dequeue(timeout, read_buffer, out_fence_fd, out_meta, - meta_size_bytes); + // TODO(b/65469368): Deprecate this API once new AcquireBuffer API is in use. + return read_queue->Dequeue(timeout, read_buffer, out_fence_fd, nullptr, + out_meta, meta_size_bytes); +} + +int dvrReadBufferQueueAcquireBuffer(DvrReadBufferQueue* read_queue, int timeout, + DvrReadBuffer** out_read_buffer, + DvrNativeBufferMetadata* out_meta, + int* out_fence_fd) { + if (!read_queue || !out_read_buffer || !out_meta || !out_fence_fd) + return -EINVAL; + + return read_queue->AcquireBuffer(timeout, out_read_buffer, out_meta, + out_fence_fd); +} + +int dvrReadBufferQueueReleaseBuffer(DvrReadBufferQueue* read_queue, + DvrReadBuffer* read_buffer, + const DvrNativeBufferMetadata* meta, + int release_fence_fd) { + if (!read_queue || !read_buffer || !read_buffer->read_buffer || !meta) + return -EINVAL; + + return read_queue->ReleaseBuffer(read_buffer, meta, release_fence_fd); } int dvrReadBufferQueueSetBufferAvailableCallback( diff --git a/libs/vr/libdvr/dvr_buffer_queue_internal.h b/libs/vr/libdvr/dvr_buffer_queue_internal.h index 795d6cdc25..f9c0bfd7c7 100644 --- a/libs/vr/libdvr/dvr_buffer_queue_internal.h +++ b/libs/vr/libdvr/dvr_buffer_queue_internal.h @@ -5,10 +5,14 @@ #include #include +#include #include +#include "dvr_internal.h" + struct ANativeWindow; +typedef struct DvrNativeBufferMetadata DvrNativeBufferMetadata; typedef struct DvrReadBuffer DvrReadBuffer; typedef struct DvrReadBufferQueue DvrReadBufferQueue; typedef struct DvrWriteBuffer DvrWriteBuffer; @@ -17,6 +21,7 @@ typedef void (*DvrReadBufferQueueBufferRemovedCallback)(DvrReadBuffer* buffer, void* context); struct DvrWriteBufferQueue { + using BufferHubQueue = android::dvr::BufferHubQueue; using ProducerQueue = android::dvr::ProducerQueue; // Create a concrete object for DvrWriteBufferQueue. @@ -37,19 +42,28 @@ struct DvrWriteBufferQueue { int GetNativeWindow(ANativeWindow** out_window); int CreateReadQueue(DvrReadBufferQueue** out_read_queue); - int Dequeue(int timeout, DvrWriteBuffer* write_buffer, int* out_fence_fd); + int Dequeue(int timeout, DvrWriteBuffer* write_buffer, int* out_fence_fd, + size_t* out_slot); + int GainBuffer(int timeout, DvrWriteBuffer** out_write_buffer, + DvrNativeBufferMetadata* out_meta, int* out_fence_fd); + int PostBuffer(DvrWriteBuffer* write_buffer, + const DvrNativeBufferMetadata* meta, int ready_fence_fd); int ResizeBuffer(uint32_t width, uint32_t height); private: std::shared_ptr producer_queue_; + std::array, BufferHubQueue::kMaxQueueCapacity> + write_buffers_; uint32_t width_; uint32_t height_; uint32_t format_; + android::sp native_window_; }; struct DvrReadBufferQueue { + using BufferHubQueue = android::dvr::BufferHubQueue; using ConsumerQueue = android::dvr::ConsumerQueue; explicit DvrReadBufferQueue( @@ -61,7 +75,11 @@ struct DvrReadBufferQueue { int CreateReadQueue(DvrReadBufferQueue** out_read_queue); int Dequeue(int timeout, DvrReadBuffer* read_buffer, int* out_fence_fd, - void* out_meta, size_t meta_size_bytes); + size_t* out_slot, void* out_meta, size_t meta_size_bytes); + int AcquireBuffer(int timeout, DvrReadBuffer** out_read_buffer, + DvrNativeBufferMetadata* out_meta, int* out_fence_fd); + int ReleaseBuffer(DvrReadBuffer* read_buffer, + const DvrNativeBufferMetadata* meta, int release_fence_fd); void SetBufferAvailableCallback( DvrReadBufferQueueBufferAvailableCallback callback, void* context); void SetBufferRemovedCallback( @@ -70,6 +88,8 @@ struct DvrReadBufferQueue { private: std::shared_ptr consumer_queue_; + std::array, BufferHubQueue::kMaxQueueCapacity> + read_buffers_; }; #endif // ANDROID_DVR_BUFFER_QUEUE_INTERNAL_H_ diff --git a/libs/vr/libdvr/dvr_internal.h b/libs/vr/libdvr/dvr_internal.h index 28b6c28e9f..de8bb96aec 100644 --- a/libs/vr/libdvr/dvr_internal.h +++ b/libs/vr/libdvr/dvr_internal.h @@ -34,10 +34,20 @@ DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer( extern "C" { struct DvrWriteBuffer { + // The slot nubmer of the buffer, a valid slot number must be in the range of + // [0, android::BufferQueueDefs::NUM_BUFFER_SLOTS). This is only valid for + // DvrWriteBuffer acquired from a DvrWriteBufferQueue. + int32_t slot = -1; + std::shared_ptr write_buffer; }; struct DvrReadBuffer { + // The slot nubmer of the buffer, a valid slot number must be in the range of + // [0, android::BufferQueueDefs::NUM_BUFFER_SLOTS). This is only valid for + // DvrReadBuffer acquired from a DvrReadBufferQueue. + int32_t slot = -1; + std::shared_ptr read_buffer; }; diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h index 6daf157f36..8f45ce7e40 100644 --- a/libs/vr/libdvr/include/dvr/dvr_api.h +++ b/libs/vr/libdvr/include/dvr/dvr_api.h @@ -34,6 +34,7 @@ typedef struct AHardwareBuffer AHardwareBuffer; typedef struct DvrReadBufferQueue DvrReadBufferQueue; typedef struct DvrWriteBufferQueue DvrWriteBufferQueue; +typedef struct DvrNativeBufferMetadata DvrNativeBufferMetadata; typedef struct DvrSurface DvrSurface; typedef uint64_t DvrSurfaceAttributeType; @@ -180,6 +181,13 @@ typedef int (*DvrWriteBufferQueueDequeuePtr)(DvrWriteBufferQueue* write_queue, int timeout, DvrWriteBuffer* out_buffer, int* out_fence_fd); +typedef int (*DvrWriteBufferQueueGainBufferPtr)( + DvrWriteBufferQueue* write_queue, int timeout, + DvrWriteBuffer** out_write_buffer, DvrNativeBufferMetadata* out_meta, + int* out_fence_fd); +typedef int (*DvrWriteBufferQueuePostBufferPtr)( + DvrWriteBufferQueue* write_queue, DvrWriteBuffer* write_buffer, + const DvrNativeBufferMetadata* meta, int ready_fence_fd); typedef int (*DvrWriteBufferQueueResizeBufferPtr)( DvrWriteBufferQueue* write_queue, uint32_t width, uint32_t height); typedef void (*DvrReadBufferQueueDestroyPtr)(DvrReadBufferQueue* read_queue); @@ -194,6 +202,13 @@ typedef int (*DvrReadBufferQueueDequeuePtr)(DvrReadBufferQueue* read_queue, DvrReadBuffer* out_buffer, int* out_fence_fd, void* out_meta, size_t meta_size_bytes); +typedef int (*DvrReadBufferQueueAcquireBufferPtr)( + DvrReadBufferQueue* read_queue, int timeout, + DvrReadBuffer** out_read_buffer, DvrNativeBufferMetadata* out_meta, + int* out_fence_fd); +typedef int (*DvrReadBufferQueueReleaseBufferPtr)( + DvrReadBufferQueue* read_queue, DvrReadBuffer* read_buffer, + const DvrNativeBufferMetadata* meta, int release_fence_fd); typedef void (*DvrReadBufferQueueBufferAvailableCallback)(void* context); typedef int (*DvrReadBufferQueueSetBufferAvailableCallbackPtr)( DvrReadBufferQueue* read_queue, diff --git a/libs/vr/libdvr/include/dvr/dvr_api_entries.h b/libs/vr/libdvr/include/dvr/dvr_api_entries.h index 9036773464..cce8c7ee40 100644 --- a/libs/vr/libdvr/include/dvr/dvr_api_entries.h +++ b/libs/vr/libdvr/include/dvr/dvr_api_entries.h @@ -167,6 +167,12 @@ DVR_V1_API_ENTRY(WriteBufferQueueCreate); // Gets an ANativeWindow from DvrWriteBufferQueue. DVR_V1_API_ENTRY(WriteBufferQueueGetANativeWindow); +// Dvr{Read,Write}BufferQueue API for asynchronous IPC. +DVR_V1_API_ENTRY(WriteBufferQueueGainBuffer); +DVR_V1_API_ENTRY(WriteBufferQueuePostBuffer); +DVR_V1_API_ENTRY(ReadBufferQueueAcquireBuffer); +DVR_V1_API_ENTRY(ReadBufferQueueReleaseBuffer); + // Pose client DVR_V1_API_ENTRY(PoseClientGetDataReader); DVR_V1_API_ENTRY(PoseClientDataCapture); diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h index 8b9e0482d9..bf695c7dbc 100644 --- a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h +++ b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h @@ -89,21 +89,44 @@ int dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue, int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue, DvrReadBufferQueue** out_read_queue); -// Dequeue a buffer to write into. +// @deprecated Please use dvrWriteBufferQueueGainBuffer instead. +int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout, + DvrWriteBuffer* out_buffer, int* out_fence_fd); + +// Gains a buffer to write into. // -// @param write_queue The DvrWriteBufferQueue of interest. +// @param write_queue The DvrWriteBufferQueue to gain buffer from. // @param timeout Specifies the number of milliseconds that the method will // block. Specifying a timeout of -1 causes it to block indefinitely, // while specifying a timeout equal to zero cause it to return immediately, // even if no buffers are available. // @param out_buffer A targeting DvrWriteBuffer object to hold the output of the -// dequeue operation. Must be created by |dvrWriteBufferCreateEmpty|. +// dequeue operation. +// @param out_meta A DvrNativeBufferMetadata object populated by the +// corresponding dvrReadBufferQueueReleaseBuffer API. // @param out_fence_fd A sync fence fd defined in NDK's sync.h API, which // signals the release of underlying buffer. The producer should wait until // this fence clears before writing data into it. // @return Zero on success, or negative error code. -int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout, - DvrWriteBuffer* out_buffer, int* out_fence_fd); +int dvrWriteBufferQueueGainBuffer(DvrWriteBufferQueue* write_queue, int timeout, + DvrWriteBuffer** out_write_buffer, + DvrNativeBufferMetadata* out_meta, + int* out_fence_fd); + +// Posts a buffer and signals its readiness to be read from. +// +// @param write_queue The DvrWriteBufferQueue to post buffer into. +// @param write_buffer The buffer to be posted. +// @param meta The buffer metadata describing the buffer. +// @param ready_fence_fd A sync fence fd defined in NDK's sync.h API, which +// signals the readdiness of underlying buffer. When a valid fence gets +// passed in, the consumer will wait the fence to be ready before it starts +// to ready from the buffer. +// @return Zero on success, or negative error code. +int dvrWriteBufferQueuePostBuffer(DvrWriteBufferQueue* write_queue, + DvrWriteBuffer* write_buffer, + const DvrNativeBufferMetadata* meta, + int ready_fence_fd); // Overrides buffer dimension with new width and height. // @@ -153,28 +176,45 @@ int dvrReadBufferQueueGetEventFd(DvrReadBufferQueue* read_queue); int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue, DvrReadBufferQueue** out_read_queue); -// Dequeue a buffer to read from. +// @deprecated Please use dvrReadBufferQueueAcquireBuffer instead. +int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout, + DvrReadBuffer* out_buffer, int* out_fence_fd, + void* out_meta, size_t meta_size_bytes); + +// Dequeues a buffer to read from. // -// @param read_queue The DvrReadBufferQueue of interest. +// @param read_queue The DvrReadBufferQueue to acquire buffer from. // @param timeout Specifies the number of milliseconds that the method will // block. Specifying a timeout of -1 causes it to block indefinitely, // while specifying a timeout equal to zero cause it to return immediately, // even if no buffers are available. // @param out_buffer A targeting DvrReadBuffer object to hold the output of the // dequeue operation. Must be created by |dvrReadBufferCreateEmpty|. +// @param out_meta A DvrNativeBufferMetadata object populated by the +// corresponding dvrWriteBufferQueuePostBuffer API. // @param out_fence_fd A sync fence fd defined in NDK's sync.h API, which // signals the release of underlying buffer. The consumer should wait until // this fence clears before reading data from it. -// @param out_meta The memory area where a metadata object will be filled. -// Can be nullptr iff |meta_size_bytes| is zero (i.e., there is no -// metadata). -// @param meta_size_bytes Size of the metadata object caller expects. If it -// doesn't match the size of actually metadata transported by the buffer -// queue, the method returns -EINVAL. // @return Zero on success, or negative error code. -int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout, - DvrReadBuffer* out_buffer, int* out_fence_fd, - void* out_meta, size_t meta_size_bytes); +int dvrReadBufferQueueAcquireBuffer(DvrReadBufferQueue* read_queue, int timeout, + DvrReadBuffer** out_read_buffer, + DvrNativeBufferMetadata* out_meta, + int* out_fence_fd); + +// Releases a buffer and signals its readiness to be written into. +// +// @param read_queue The DvrReadBufferQueue to release buffer into. +// @param read_buffer The buffer to be released. +// @param meta The buffer metadata describing the buffer. +// @param release_fence_fd A sync fence fd defined in NDK's sync.h API, which +// signals the readdiness of underlying buffer. When a valid fence gets +// passed in, the producer will wait the fence to be ready before it starts +// to write into the buffer again. +// @return Zero on success, or negative error code. +int dvrReadBufferQueueReleaseBuffer(DvrReadBufferQueue* read_queue, + DvrReadBuffer* read_buffer, + const DvrNativeBufferMetadata* meta, + int release_fence_fd); // Callback function which will be called when a buffer is avaiable. // diff --git a/libs/vr/libdvr/tests/Android.bp b/libs/vr/libdvr/tests/Android.bp index ab2ee75a3e..a9302a7561 100644 --- a/libs/vr/libdvr/tests/Android.bp +++ b/libs/vr/libdvr/tests/Android.bp @@ -47,6 +47,7 @@ cc_test { cflags: [ "-DLOG_TAG=\"dvr_api-test\"", "-DTRACE=0", + "-Wno-missing-field-initializers", "-O0", "-g", ], diff --git a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp index 0b30c3869a..f1c5e48916 100644 --- a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp +++ b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp @@ -27,8 +27,6 @@ static constexpr uint32_t kBufferFormat = AHARDWAREBUFFER_FORMAT_BLOB; static constexpr uint64_t kBufferUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN; static constexpr size_t kQueueCapacity = 3; -typedef uint64_t TestMeta; - class DvrBufferQueueTest : public ::testing::Test { public: static void BufferAvailableCallback(void* context) { @@ -65,20 +63,20 @@ class DvrBufferQueueTest : public ::testing::Test { int buffer_removed_count_{0}; }; -TEST_F(DvrBufferQueueTest, TestWrite_QueueCreateDestroy) { +TEST_F(DvrBufferQueueTest, WriteQueueCreateDestroy) { int ret = dvrWriteBufferQueueCreate( kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, - /*capacity=*/0, sizeof(TestMeta), &write_queue_); + /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_); ASSERT_EQ(0, ret); dvrWriteBufferQueueDestroy(write_queue_); write_queue_ = nullptr; } -TEST_F(DvrBufferQueueTest, TestWrite_QueueGetCapacity) { +TEST_F(DvrBufferQueueTest, WriteQueueGetCapacity) { int ret = dvrWriteBufferQueueCreate( kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, - kQueueCapacity, sizeof(TestMeta), &write_queue_); + kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_); ASSERT_EQ(0, ret); size_t capacity = dvrWriteBufferQueueGetCapacity(write_queue_); @@ -87,10 +85,10 @@ TEST_F(DvrBufferQueueTest, TestWrite_QueueGetCapacity) { ASSERT_EQ(kQueueCapacity, capacity); } -TEST_F(DvrBufferQueueTest, TestCreateReadQueueFromWriteQueue) { +TEST_F(DvrBufferQueueTest, CreateReadQueueFromWriteQueue) { int ret = dvrWriteBufferQueueCreate( kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, - /*capacity=*/0, sizeof(TestMeta), &write_queue_); + /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_); ASSERT_EQ(0, ret); DvrReadBufferQueue* read_queue = nullptr; @@ -102,10 +100,10 @@ TEST_F(DvrBufferQueueTest, TestCreateReadQueueFromWriteQueue) { dvrReadBufferQueueDestroy(read_queue); } -TEST_F(DvrBufferQueueTest, TestCreateReadQueueFromReadQueue) { +TEST_F(DvrBufferQueueTest, CreateReadQueueFromReadQueue) { int ret = dvrWriteBufferQueueCreate( kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, - /*capacity=*/0, sizeof(TestMeta), &write_queue_); + /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_); ASSERT_EQ(0, ret); DvrReadBufferQueue* read_queue1 = nullptr; @@ -124,102 +122,86 @@ TEST_F(DvrBufferQueueTest, TestCreateReadQueueFromReadQueue) { dvrReadBufferQueueDestroy(read_queue2); } -TEST_F(DvrBufferQueueTest, CreateEmptyBuffer) { +TEST_F(DvrBufferQueueTest, GainBuffer) { int ret = dvrWriteBufferQueueCreate( kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, - kQueueCapacity, sizeof(TestMeta), &write_queue_); - ASSERT_EQ(0, ret); - - DvrReadBuffer* read_buffer = nullptr; - DvrWriteBuffer* write_buffer = nullptr; - - EXPECT_FALSE(dvrReadBufferIsValid(read_buffer)); - EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer)); - - dvrReadBufferCreateEmpty(&read_buffer); - ASSERT_NE(nullptr, read_buffer); - - dvrWriteBufferCreateEmpty(&write_buffer); - ASSERT_NE(nullptr, write_buffer); - - EXPECT_FALSE(dvrReadBufferIsValid(read_buffer)); - EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer)); + kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_); + ASSERT_EQ(ret, 0); - DvrReadBufferQueue* read_queue = nullptr; - - ASSERT_EQ(0, dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue)); + DvrWriteBuffer* wb = nullptr; + EXPECT_FALSE(dvrWriteBufferIsValid(wb)); - const int kTimeoutMs = 0; + DvrNativeBufferMetadata meta = {0}; int fence_fd = -1; - ASSERT_EQ(0, dvrWriteBufferQueueDequeue(write_queue_, kTimeoutMs, - write_buffer, &fence_fd)); - EXPECT_EQ(-1, fence_fd); - EXPECT_TRUE(dvrWriteBufferIsValid(write_buffer)); - - ASSERT_EQ(0, dvrWriteBufferClear(write_buffer)); - EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer)); + ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb, &meta, + &fence_fd); + ASSERT_EQ(ret, 0); + EXPECT_EQ(fence_fd, -1); + EXPECT_NE(wb, nullptr); + EXPECT_TRUE(dvrWriteBufferIsValid(wb)); } -TEST_F(DvrBufferQueueTest, TestDequeuePostDequeueRelease) { +TEST_F(DvrBufferQueueTest, AcquirePostGainRelease) { int ret = dvrWriteBufferQueueCreate( kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, - kQueueCapacity, sizeof(TestMeta), &write_queue_); - ASSERT_EQ(0, ret); + kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_); + ASSERT_EQ(ret, 0); - static constexpr int kTimeout = 0; DvrReadBufferQueue* read_queue = nullptr; DvrReadBuffer* rb = nullptr; DvrWriteBuffer* wb = nullptr; + DvrNativeBufferMetadata meta1 = {0}; + DvrNativeBufferMetadata meta2 = {0}; int fence_fd = -1; ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue); - ASSERT_EQ(0, ret); - ASSERT_NE(nullptr, read_queue); + ASSERT_EQ(ret, 0); + ASSERT_NE(read_queue, nullptr); dvrReadBufferQueueSetBufferAvailableCallback(read_queue, &BufferAvailableCallback, this); - dvrWriteBufferCreateEmpty(&wb); - ASSERT_NE(nullptr, wb); - - dvrReadBufferCreateEmpty(&rb); - ASSERT_NE(nullptr, rb); - // Gain buffer for writing. - ret = dvrWriteBufferQueueDequeue(write_queue_, kTimeout, wb, &fence_fd); - ASSERT_EQ(0, ret); + ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb, &meta1, + &fence_fd); + ASSERT_EQ(ret, 0); + ASSERT_NE(wb, nullptr); ASSERT_TRUE(dvrWriteBufferIsValid(wb)); ALOGD_IF(TRACE, "TestDequeuePostDequeueRelease, gain buffer %p, fence_fd=%d", wb, fence_fd); android::base::unique_fd release_fence(fence_fd); // Post buffer to the read_queue. - TestMeta seq = 42U; - ret = dvrWriteBufferPost(wb, /* fence */ -1, &seq, sizeof(seq)); - ASSERT_EQ(0, ret); - dvrWriteBufferDestroy(wb); + meta1.timestamp = 42; + ret = dvrWriteBufferQueuePostBuffer(write_queue_, wb, &meta1, /*fence=*/-1); + ASSERT_EQ(ret, 0); + ASSERT_FALSE(dvrWriteBufferIsValid(wb)); wb = nullptr; // Acquire buffer for reading. - TestMeta acquired_seq = 0U; - ret = dvrReadBufferQueueDequeue(read_queue, kTimeout, rb, &fence_fd, - &acquired_seq, sizeof(acquired_seq)); - ASSERT_EQ(0, ret); + ret = dvrReadBufferQueueAcquireBuffer(read_queue, /*timeout=*/0, &rb, &meta2, + &fence_fd); + ASSERT_EQ(ret, 0); + ASSERT_NE(rb, nullptr); // Dequeue is successfully, BufferAvailableCallback should be fired once. - ASSERT_EQ(1, buffer_available_count_); + ASSERT_EQ(buffer_available_count_, 1); ASSERT_TRUE(dvrReadBufferIsValid(rb)); - ASSERT_EQ(seq, acquired_seq); + + // Metadata should be passed along from producer to consumer properly. + ASSERT_EQ(meta1.timestamp, meta2.timestamp); + ALOGD_IF(TRACE, "TestDequeuePostDequeueRelease, acquire buffer %p, fence_fd=%d", rb, fence_fd); android::base::unique_fd acquire_fence(fence_fd); // Release buffer to the write_queue. - ret = dvrReadBufferRelease(rb, -1); - ASSERT_EQ(0, ret); - dvrReadBufferDestroy(rb); + ret = dvrReadBufferQueueReleaseBuffer(read_queue, rb, &meta2, + /*release_fence_fd=*/-1); + ASSERT_EQ(ret, 0); + ASSERT_FALSE(dvrReadBufferIsValid(rb)); rb = nullptr; // TODO(b/34387835) Currently buffer allocation has to happen after all queues @@ -232,37 +214,18 @@ TEST_F(DvrBufferQueueTest, TestDequeuePostDequeueRelease) { dvrReadBufferQueueDestroy(read_queue); } -TEST_F(DvrBufferQueueTest, TestGetANativeWindow) { +TEST_F(DvrBufferQueueTest, GetANativeWindow) { int ret = dvrWriteBufferQueueCreate( kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, - /*capacity=*/0, sizeof(TestMeta), &write_queue_); - ASSERT_EQ(0, ret); - - ANativeWindow* window = nullptr; - - // The |write_queue_| doesn't have proper metadata (must be - // DvrNativeBufferMetadata) configured during creation. - ret = dvrWriteBufferQueueGetANativeWindow(write_queue_, &window); - ASSERT_EQ(-EINVAL, ret); - ASSERT_EQ(nullptr, window); - dvrWriteBufferQueueDestroy(write_queue_); - write_queue_ = nullptr; - - // A write queue with DvrNativeBufferMetadata should work fine. - ASSERT_EQ(nullptr, write_queue_); - - ret = dvrWriteBufferQueueCreate( - kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_); ASSERT_EQ(0, ret); ASSERT_NE(nullptr, write_queue_); + ANativeWindow* window = nullptr; ret = dvrWriteBufferQueueGetANativeWindow(write_queue_, &window); ASSERT_EQ(0, ret); ASSERT_NE(nullptr, window); - // TODO(b/64723700): Remove dependencies of Android platform bits so that we - // can run dvr_buffer_queue-test in DTS. uint32_t width = ANativeWindow_getWidth(window); uint32_t height = ANativeWindow_getHeight(window); uint32_t format = ANativeWindow_getFormat(window); @@ -274,15 +237,15 @@ TEST_F(DvrBufferQueueTest, TestGetANativeWindow) { // Create buffer queue of three buffers and dequeue three buffers out of it. // Before each dequeue operation, we resize the buffer queue and expect the // queue always return buffer with desired dimension. -TEST_F(DvrBufferQueueTest, TestResizeBuffer) { +TEST_F(DvrBufferQueueTest, ResizeBuffer) { int ret = dvrWriteBufferQueueCreate( kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, - kQueueCapacity, sizeof(TestMeta), &write_queue_); + kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_); ASSERT_EQ(0, ret); - static constexpr int kTimeout = 0; int fence_fd = -1; + DvrNativeBufferMetadata meta = {0}; DvrReadBufferQueue* read_queue = nullptr; DvrWriteBuffer* wb1 = nullptr; DvrWriteBuffer* wb2 = nullptr; @@ -300,13 +263,6 @@ TEST_F(DvrBufferQueueTest, TestResizeBuffer) { dvrReadBufferQueueSetBufferRemovedCallback(read_queue, &BufferRemovedCallback, this); - dvrWriteBufferCreateEmpty(&wb1); - ASSERT_NE(nullptr, wb1); - dvrWriteBufferCreateEmpty(&wb2); - ASSERT_NE(nullptr, wb2); - dvrWriteBufferCreateEmpty(&wb3); - ASSERT_NE(nullptr, wb3); - // Handle all pending events on the read queue. ret = dvrReadBufferQueueHandleEvents(read_queue); ASSERT_EQ(0, ret); @@ -321,7 +277,8 @@ TEST_F(DvrBufferQueueTest, TestResizeBuffer) { ASSERT_EQ(0, ret); // Gain first buffer for writing. All buffers will be resized. - ret = dvrWriteBufferQueueDequeue(write_queue_, kTimeout, wb1, &fence_fd); + ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb1, &meta, + &fence_fd); ASSERT_EQ(0, ret); ASSERT_TRUE(dvrWriteBufferIsValid(wb1)); ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p", wb1); @@ -347,7 +304,8 @@ TEST_F(DvrBufferQueueTest, TestResizeBuffer) { ASSERT_EQ(0, ret); // The next buffer we dequeued should have new width. - ret = dvrWriteBufferQueueDequeue(write_queue_, kTimeout, wb2, &fence_fd); + ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb2, &meta, + &fence_fd); ASSERT_EQ(0, ret); ASSERT_TRUE(dvrWriteBufferIsValid(wb2)); ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p, fence_fd=%d", wb2, @@ -373,7 +331,8 @@ TEST_F(DvrBufferQueueTest, TestResizeBuffer) { ASSERT_EQ(0, ret); // The next buffer we dequeued should have new width. - ret = dvrWriteBufferQueueDequeue(write_queue_, kTimeout, wb3, &fence_fd); + ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb3, &meta, + &fence_fd); ASSERT_EQ(0, ret); ASSERT_TRUE(dvrWriteBufferIsValid(wb3)); ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p, fence_fd=%d", wb3, @@ -396,78 +355,10 @@ TEST_F(DvrBufferQueueTest, TestResizeBuffer) { dvrReadBufferQueueDestroy(read_queue); } -TEST_F(DvrBufferQueueTest, DequeueEmptyMetadata) { - // Overrides default queue parameters: Empty metadata. +TEST_F(DvrBufferQueueTest, ReadQueueEventFd) { int ret = dvrWriteBufferQueueCreate( kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, - /*capacity=*/1, /*metadata_size=*/0, &write_queue_); - ASSERT_EQ(0, ret); - - DvrReadBuffer* rb = nullptr; - DvrWriteBuffer* wb = nullptr; - dvrReadBufferCreateEmpty(&rb); - dvrWriteBufferCreateEmpty(&wb); - - DvrReadBufferQueue* read_queue = nullptr; - EXPECT_EQ(0, dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue)); - - const int kTimeoutMs = 0; - int fence_fd = -1; - EXPECT_EQ(0, dvrWriteBufferQueueDequeue(write_queue_, 0, wb, &fence_fd)); - - EXPECT_EQ(0, dvrWriteBufferPost(wb, /*fence=*/-1, nullptr, 0)); - EXPECT_EQ(0, dvrWriteBufferClear(wb)); - dvrWriteBufferDestroy(wb); - wb = nullptr; - - // When acquire buffer, it's legit to pass nullptr as out_meta iff metadata - // size is Zero. - EXPECT_EQ(0, dvrReadBufferQueueDequeue(read_queue, kTimeoutMs, rb, &fence_fd, - nullptr, 0)); - EXPECT_TRUE(dvrReadBufferIsValid(rb)); -} - -TEST_F(DvrBufferQueueTest, DequeueMismatchMetadata) { - int ret = dvrWriteBufferQueueCreate( - kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, - /*capacity=*/1, sizeof(TestMeta), &write_queue_); - ASSERT_EQ(0, ret); - - DvrReadBuffer* rb = nullptr; - DvrWriteBuffer* wb = nullptr; - dvrReadBufferCreateEmpty(&rb); - dvrWriteBufferCreateEmpty(&wb); - - DvrReadBufferQueue* read_queue = nullptr; - EXPECT_EQ(0, dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue)); - - const int kTimeoutMs = 0; - int fence_fd = -1; - EXPECT_EQ(0, dvrWriteBufferQueueDequeue(write_queue_, 0, wb, &fence_fd)); - - TestMeta seq = 42U; - EXPECT_EQ(0, dvrWriteBufferPost(wb, /*fence=*/-1, &seq, sizeof(seq))); - EXPECT_EQ(0, dvrWriteBufferClear(wb)); - dvrWriteBufferDestroy(wb); - wb = nullptr; - - // Dequeue with wrong metadata will cause EINVAL. - int8_t wrong_metadata; - EXPECT_EQ(-EINVAL, - dvrReadBufferQueueDequeue(read_queue, kTimeoutMs, rb, &fence_fd, - &wrong_metadata, sizeof(wrong_metadata))); - EXPECT_FALSE(dvrReadBufferIsValid(rb)); - - // Dequeue with empty metadata will cause EINVAL. - EXPECT_EQ(-EINVAL, dvrReadBufferQueueDequeue(read_queue, kTimeoutMs, rb, - &fence_fd, nullptr, 0)); - EXPECT_FALSE(dvrReadBufferIsValid(rb)); -} - -TEST_F(DvrBufferQueueTest, TestReadQueueEventFd) { - int ret = dvrWriteBufferQueueCreate( - kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, - kQueueCapacity, sizeof(TestMeta), &write_queue_); + kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_); ASSERT_EQ(0, ret); DvrReadBufferQueue* read_queue = nullptr; @@ -483,10 +374,10 @@ TEST_F(DvrBufferQueueTest, TestReadQueueEventFd) { // Verifies a Dvr{Read,Write}BufferQueue contains the same set of // Dvr{Read,Write}Buffer(s) during their lifecycles. And for the same buffer_id, // the corresponding AHardwareBuffer handle stays the same. -TEST_F(DvrBufferQueueTest, TestStableBufferIdAndHardwareBuffer) { +TEST_F(DvrBufferQueueTest, StableBufferIdAndHardwareBuffer) { int ret = dvrWriteBufferQueueCreate( kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage, - kQueueCapacity, sizeof(TestMeta), &write_queue_); + kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_); ASSERT_EQ(0, ret); int fence_fd = -1; @@ -497,25 +388,21 @@ TEST_F(DvrBufferQueueTest, TestStableBufferIdAndHardwareBuffer) { std::array rbs; // Write buffers. std::array wbs; + // Buffer metadata. + std::array metas; // Hardware buffers for Read buffers. std::unordered_map rhbs; // Hardware buffers for Write buffers. std::unordered_map whbs; - for (size_t i = 0; i < kQueueCapacity; i++) { - dvrReadBufferCreateEmpty(&rbs[i]); - dvrWriteBufferCreateEmpty(&wbs[i]); - } - constexpr int kNumTests = 100; - constexpr int kTimeout = 0; - TestMeta seq = 0U; // This test runs the following operations many many times. Thus we prefer to // use ASSERT_XXX rather than EXPECT_XXX to avoid spamming the output. std::function Gain = [&](size_t i) { - ASSERT_EQ(0, dvrWriteBufferQueueDequeue(write_queue_, kTimeout, wbs[i], - &fence_fd)); + int ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, + &wbs[i], &metas[i], &fence_fd); + ASSERT_EQ(ret, 0); ASSERT_LT(fence_fd, 0); // expect invalid fence. ASSERT_TRUE(dvrWriteBufferIsValid(wbs[i])); int buffer_id = dvrWriteBufferGetId(wbs[i]); @@ -540,15 +427,16 @@ TEST_F(DvrBufferQueueTest, TestStableBufferIdAndHardwareBuffer) { std::function Post = [&](size_t i) { ASSERT_TRUE(dvrWriteBufferIsValid(wbs[i])); - seq++; - ASSERT_EQ(0, dvrWriteBufferPost(wbs[i], /*fence=*/-1, &seq, sizeof(seq))); + metas[i].timestamp++; + int ret = dvrWriteBufferQueuePostBuffer(write_queue_, wbs[i], &metas[i], + /*fence=*/-1); + ASSERT_EQ(ret, 0); }; std::function Acquire = [&](size_t i) { - TestMeta out_seq = 0U; - ASSERT_EQ(0, - dvrReadBufferQueueDequeue(read_queue, kTimeout, rbs[i], &fence_fd, - &out_seq, sizeof(out_seq))); + int ret = dvrReadBufferQueueAcquireBuffer(read_queue, /*timeout=*/0, + &rbs[i], &metas[i], &fence_fd); + ASSERT_EQ(ret, 0); ASSERT_LT(fence_fd, 0); // expect invalid fence. ASSERT_TRUE(dvrReadBufferIsValid(rbs[i])); @@ -574,8 +462,9 @@ TEST_F(DvrBufferQueueTest, TestStableBufferIdAndHardwareBuffer) { std::function Release = [&](size_t i) { ASSERT_TRUE(dvrReadBufferIsValid(rbs[i])); - seq++; - ASSERT_EQ(0, dvrReadBufferRelease(rbs[i], /*fence=*/-1)); + int ret = dvrReadBufferQueueReleaseBuffer(read_queue, rbs[i], &metas[i], + /*release_fence_fd=*/-1); + ASSERT_EQ(ret, 0); }; // Scenario one: @@ -630,12 +519,6 @@ TEST_F(DvrBufferQueueTest, TestStableBufferIdAndHardwareBuffer) { ASSERT_NO_FATAL_FAILURE(Release(kQueueCapacity - 1 - i)); } } - - // Clean up all read buffers and write buffers. - for (size_t i = 0; i < kQueueCapacity; i++) { - dvrReadBufferDestroy(rbs[i]); - dvrWriteBufferDestroy(wbs[i]); - } } } // namespace -- 2.11.0