summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2017-09-13 07:32:29 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2017-09-13 07:32:29 +0000
commit4578c1e41513695378a61894abc279098c02b883 (patch)
tree309c5125b23788f8518c8d2ad970d44c476c9d9c
parentd67d725e32a2bdc89054e5a26bfbe59cdf582b99 (diff)
parentfcc70bdc9e380ef1a652b229910c6e333cf575c5 (diff)
downloadnative-4578c1e41513695378a61894abc279098c02b883.tar.gz
release-request-b613f8ce-05b5-465e-b783-c1b87f3c1e95-for-git_oc-mr1-release-4332123 snap-temp-L59300000101925107
Change-Id: I503fd7810cf68282db9ce3c87e2d202e839f7d8a
-rw-r--r--libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h7
-rw-r--r--libs/vr/libdvr/dvr_buffer.cpp18
-rw-r--r--libs/vr/libdvr/dvr_buffer_queue.cpp233
-rw-r--r--libs/vr/libdvr/dvr_buffer_queue_internal.h24
-rw-r--r--libs/vr/libdvr/dvr_internal.h10
-rw-r--r--libs/vr/libdvr/include/dvr/dvr_api.h15
-rw-r--r--libs/vr/libdvr/include/dvr/dvr_api_entries.h6
-rw-r--r--libs/vr/libdvr/include/dvr/dvr_buffer_queue.h72
-rw-r--r--libs/vr/libdvr/tests/Android.bp1
-rw-r--r--libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp273
-rw-r--r--libs/vr/libvrflinger/hardware_composer.cpp110
-rw-r--r--libs/vr/libvrflinger/hardware_composer.h7
12 files changed, 474 insertions, 302 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<BufferHubBuffer> 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<std::shared_ptr<BufferHubBuffer>> buffers_{kMaxQueueCapacity};
+ std::array<std::shared_ptr<BufferHubBuffer>, kMaxQueueCapacity> buffers_;
// Buffers and related data that are available for dequeue.
RingBuffer<Entry> 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<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(
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 <private/dvr/buffer_hub_queue_client.h>
#include <sys/cdefs.h>
+#include <array>
#include <memory>
+#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<ProducerQueue> producer_queue_;
+ std::array<std::unique_ptr<DvrWriteBuffer>, BufferHubQueue::kMaxQueueCapacity>
+ write_buffers_;
uint32_t width_;
uint32_t height_;
uint32_t format_;
+
android::sp<android::Surface> 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<ConsumerQueue> consumer_queue_;
+ std::array<std::unique_ptr<DvrReadBuffer>, 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<android::dvr::BufferProducer> 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<android::dvr::BufferConsumer> 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<DvrReadBuffer*, kQueueCapacity> rbs;
// Write buffers.
std::array<DvrWriteBuffer*, kQueueCapacity> wbs;
+ // Buffer metadata.
+ std::array<DvrNativeBufferMetadata, kQueueCapacity> metas;
// Hardware buffers for Read buffers.
std::unordered_map<int, AHardwareBuffer*> rhbs;
// Hardware buffers for Write buffers.
std::unordered_map<int, AHardwareBuffer*> 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<void(size_t i)> 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<void(size_t i)> 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<void(size_t i)> 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<void(size_t i)> 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
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index c19fb249dd..0bf1d2b5a7 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -44,9 +44,8 @@ namespace {
const char kBacklightBrightnessSysFile[] =
"/sys/class/leds/lcd-backlight/brightness";
-const char kPrimaryDisplayWaitPPEventFile[] = "/sys/class/graphics/fb0/wait_pp";
-
const char kDvrPerformanceProperty[] = "sys.dvr.performance";
+const char kDvrStandaloneProperty[] = "ro.boot.vr";
const char kRightEyeOffsetProperty[] = "dvr.right_eye_offset_ns";
@@ -101,6 +100,8 @@ bool HardwareComposer::Initialize(
return false;
}
+ is_standalone_device_ = property_get_bool(kDvrStandaloneProperty, false);
+
request_display_callback_ = request_display_callback;
HWC::Error error = HWC::Error::None;
@@ -198,10 +199,17 @@ void HardwareComposer::UpdatePostThreadState(PostThreadStateType state,
}
void HardwareComposer::OnPostThreadResumed() {
- composer_.reset(new Hwc2::Composer(false));
- composer_callback_ = new ComposerCallback;
- composer_->registerCallback(composer_callback_);
- Layer::SetComposer(composer_.get());
+ // Phones create a new composer client on resume and destroy it on pause.
+ // Standalones only create the composer client once and then use SetPowerMode
+ // to control the screen on pause/resume.
+ if (!is_standalone_device_ || !composer_) {
+ composer_.reset(new Hwc2::Composer(false));
+ composer_callback_ = new ComposerCallback;
+ composer_->registerCallback(composer_callback_);
+ Layer::SetComposer(composer_.get());
+ } else {
+ SetPowerMode(true);
+ }
EnableVsync(true);
@@ -224,9 +232,13 @@ void HardwareComposer::OnPostThreadPaused() {
EnableVsync(false);
}
- composer_callback_ = nullptr;
- composer_.reset(nullptr);
- Layer::SetComposer(nullptr);
+ if (!is_standalone_device_) {
+ composer_callback_ = nullptr;
+ composer_.reset(nullptr);
+ Layer::SetComposer(nullptr);
+ } else {
+ SetPowerMode(false);
+ }
// Trigger target-specific performance mode change.
property_set(kDvrPerformanceProperty, "idle");
@@ -256,6 +268,12 @@ HWC::Error HardwareComposer::EnableVsync(bool enabled) {
: HWC2_VSYNC_DISABLE));
}
+HWC::Error HardwareComposer::SetPowerMode(bool active) {
+ HWC::PowerMode power_mode = active ? HWC::PowerMode::On : HWC::PowerMode::Off;
+ return composer_->setPowerMode(
+ HWC_DISPLAY_PRIMARY, power_mode.cast<Hwc2::IComposerClient::PowerMode>());
+}
+
HWC::Error HardwareComposer::Present(hwc2_display_t display) {
int32_t present_fence;
HWC::Error error = composer_->presentDisplay(display, &present_fence);
@@ -459,7 +477,7 @@ void HardwareComposer::SetDisplaySurfaces(
pending_surfaces_ = std::move(surfaces);
}
- if (request_display_callback_)
+ if (request_display_callback_ && (!is_standalone_device_ || !composer_))
request_display_callback_(!display_idle);
// Set idle state based on whether there are any surfaces to handle.
@@ -569,48 +587,6 @@ int HardwareComposer::PostThreadPollInterruptible(
}
}
-// Reads the value of the display driver wait_pingpong state. Returns 0 or 1
-// (the value of the state) on success or a negative error otherwise.
-// TODO(eieio): This is pretty driver specific, this should be moved to a
-// separate class eventually.
-int HardwareComposer::ReadWaitPPState() {
- // Gracefully handle when the kernel does not support this feature.
- if (!primary_display_wait_pp_fd_)
- return 0;
-
- const int wait_pp_fd = primary_display_wait_pp_fd_.Get();
- int ret, error;
-
- ret = lseek(wait_pp_fd, 0, SEEK_SET);
- if (ret < 0) {
- error = errno;
- ALOGE("HardwareComposer::ReadWaitPPState: Failed to seek wait_pp fd: %s",
- strerror(error));
- return -error;
- }
-
- char data = -1;
- ret = read(wait_pp_fd, &data, sizeof(data));
- if (ret < 0) {
- error = errno;
- ALOGE("HardwareComposer::ReadWaitPPState: Failed to read wait_pp state: %s",
- strerror(error));
- return -error;
- }
-
- switch (data) {
- case '0':
- return 0;
- case '1':
- return 1;
- default:
- ALOGE(
- "HardwareComposer::ReadWaitPPState: Unexpected value for wait_pp: %d",
- data);
- return -EINVAL;
- }
-}
-
// Waits for the next vsync and returns the timestamp of the vsync event. If
// vsync already passed since the last call, returns the latest vsync timestamp
// instead of blocking.
@@ -640,8 +616,8 @@ int HardwareComposer::SleepUntil(int64_t wakeup_timestamp) {
return -error;
}
- return PostThreadPollInterruptible(
- vsync_sleep_timer_fd_, POLLIN, /*timeout_ms*/ -1);
+ return PostThreadPollInterruptible(vsync_sleep_timer_fd_, POLLIN,
+ /*timeout_ms*/ -1);
}
void HardwareComposer::PostThread() {
@@ -664,15 +640,6 @@ void HardwareComposer::PostThread() {
strerror(errno));
#endif // ENABLE_BACKLIGHT_BRIGHTNESS
- // Open the wait pingpong status node for the primary display.
- // TODO(eieio): Move this into a platform-specific class.
- primary_display_wait_pp_fd_ =
- LocalHandle(kPrimaryDisplayWaitPPEventFile, O_RDONLY);
- ALOGW_IF(
- !primary_display_wait_pp_fd_,
- "HardwareComposer: Failed to open wait_pp node for primary display: %s",
- strerror(errno));
-
// Create a timerfd based on CLOCK_MONOTINIC.
vsync_sleep_timer_fd_.Reset(timerfd_create(CLOCK_MONOTONIC, 0));
LOG_ALWAYS_FATAL_IF(
@@ -895,15 +862,12 @@ void HardwareComposer::SetBacklightBrightness(int brightness) {
HardwareComposer::ComposerCallback::ComposerCallback() {
vsync_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
- LOG_ALWAYS_FATAL_IF(
- !vsync_event_fd_,
- "Failed to create vsync event fd : %s",
- strerror(errno));
+ LOG_ALWAYS_FATAL_IF(!vsync_event_fd_, "Failed to create vsync event fd : %s",
+ strerror(errno));
}
Return<void> HardwareComposer::ComposerCallback::onHotplug(
- Hwc2::Display /*display*/,
- IComposerCallback::Connection /*conn*/) {
+ Hwc2::Display /*display*/, IComposerCallback::Connection /*conn*/) {
return Void();
}
@@ -912,8 +876,8 @@ Return<void> HardwareComposer::ComposerCallback::onRefresh(
return hardware::Void();
}
-Return<void> HardwareComposer::ComposerCallback::onVsync(
- Hwc2::Display display, int64_t timestamp) {
+Return<void> HardwareComposer::ComposerCallback::onVsync(Hwc2::Display display,
+ int64_t timestamp) {
if (display == HWC_DISPLAY_PRIMARY) {
std::lock_guard<std::mutex> lock(vsync_mutex_);
vsync_time_ = timestamp;
@@ -923,8 +887,8 @@ Return<void> HardwareComposer::ComposerCallback::onVsync(
return Void();
}
-const pdx::LocalHandle&
-HardwareComposer::ComposerCallback::GetVsyncEventFd() const {
+const pdx::LocalHandle& HardwareComposer::ComposerCallback::GetVsyncEventFd()
+ const {
return vsync_event_fd_;
}
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index 550e6877f5..793c3e887c 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -336,6 +336,7 @@ class HardwareComposer {
HWCDisplayMetrics* out_metrics) const;
HWC::Error EnableVsync(bool enabled);
+ HWC::Error SetPowerMode(bool active);
class ComposerCallback : public Hwc2::IComposerCallback {
public:
@@ -394,7 +395,7 @@ class HardwareComposer {
int WaitForVSync(int64_t* timestamp);
int SleepUntil(int64_t wakeup_timestamp);
- bool IsFramePendingInDriver() { return ReadWaitPPState() == 1; }
+ bool IsFramePendingInDriver() { return false; }
// Reconfigures the layer stack if the display surfaces changed since the last
// frame. Called only from the post thread.
@@ -413,6 +414,7 @@ class HardwareComposer {
void UpdateConfigBuffer();
bool initialized_;
+ bool is_standalone_device_;
std::unique_ptr<Hwc2::Composer> composer_;
sp<ComposerCallback> composer_callback_;
@@ -455,9 +457,6 @@ class HardwareComposer {
// Backlight LED brightness sysfs node.
pdx::LocalHandle backlight_brightness_fd_;
- // Primary display wait_pingpong state sysfs node.
- pdx::LocalHandle primary_display_wait_pp_fd_;
-
// VSync sleep timerfd.
pdx::LocalHandle vsync_sleep_timer_fd_;