summaryrefslogtreecommitdiff
path: root/libs/vr/libdvr/dvr_buffer_queue.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/vr/libdvr/dvr_buffer_queue.cpp')
-rw-r--r--libs/vr/libdvr/dvr_buffer_queue.cpp233
1 files changed, 224 insertions, 9 deletions
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<BufferProducer> 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<DvrWriteBuffer>();
+ 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<size_t>(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<DvrReadBuffer>();
+ 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<size_t>(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<BufferHubBuffer>& buffer) {
- DvrReadBuffer read_buffer{
- std::static_pointer_cast<BufferConsumer>(buffer)};
- callback(&read_buffer, context);
+ // When buffer is removed from the queue, the slot is already invalid.
+ auto read_buffer = std::make_unique<DvrReadBuffer>();
+ read_buffer->read_buffer =
+ std::static_pointer_cast<BufferConsumer>(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(