Refactor VrFlinger to use BufferHubQueue
1/ Remove DisplayRPC::AllocateBuffer, as individual buffer allocation
is now handled by BufferHubQueue.
2/ Reimplement native_buffer_queue using bufferhubqueue.
3/ Hook up consumer queue in DisplaySurface.
4/ Remove epoll_event_dispatcher as its no longer being used.
Bug: 36033302
Test: Built and ran particles.apk
Change-Id: I38ee1c57195888ede935ebc50119bcb7e4ab4e36
diff --git a/libs/vr/libdisplay/display_client.cpp b/libs/vr/libdisplay/display_client.cpp
index 54098e8..dcdd994 100644
--- a/libs/vr/libdisplay/display_client.cpp
+++ b/libs/vr/libdisplay/display_client.cpp
@@ -148,18 +148,22 @@
}
}
-std::shared_ptr<BufferProducer> DisplaySurfaceClient::AllocateBuffer(
- uint32_t* buffer_index) {
- auto status = InvokeRemoteMethod<DisplayRPC::AllocateBuffer>();
- if (!status) {
- ALOGE("DisplaySurfaceClient::AllocateBuffer: Failed to allocate buffer: %s",
+std::shared_ptr<ProducerQueue> DisplaySurfaceClient::GetProducerQueue() {
+ if (producer_queue_ == nullptr) {
+ // Create producer queue through DisplayRPC
+ auto status = InvokeRemoteMethod<DisplayRPC::CreateBufferQueue>();
+ if (!status) {
+ ALOGE(
+ "DisplaySurfaceClient::GetProducerQueue: failed to create producer "
+ "queue: %s",
status.GetErrorMessage().c_str());
- return nullptr;
- }
+ return nullptr;
+ }
- if (buffer_index)
- *buffer_index = status.get().first;
- return BufferProducer::Import(status.take().second);
+ producer_queue_ =
+ ProducerQueue::Import<DisplaySurfaceMetadata>(status.take());
+ }
+ return producer_queue_;
}
volatile DisplaySurfaceMetadata* DisplaySurfaceClient::GetMetadataBufferPtr() {
diff --git a/libs/vr/libdisplay/include/private/dvr/display_client.h b/libs/vr/libdisplay/include/private/dvr/display_client.h
index 034b7b4..e1471c3 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_client.h
@@ -5,6 +5,7 @@
#include <pdx/client.h>
#include <pdx/file_handle.h>
#include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/buffer_hub_queue_client.h>
#include <private/dvr/display_rpc.h>
namespace android {
@@ -62,13 +63,9 @@
void SetBlurBehind(bool blur_behind);
void SetAttributes(const DisplaySurfaceAttributes& attributes);
- // |out_buffer_index| will receive a unique index for this buffer within the
- // surface. The first buffer gets 0, second gets 1, and so on. This index
- // can be used to deliver metadata for buffers that are queued for display.
- std::shared_ptr<BufferProducer> AllocateBuffer(uint32_t* out_buffer_index);
- std::shared_ptr<BufferProducer> AllocateBuffer() {
- return AllocateBuffer(nullptr);
- }
+ // Get the producer end of the buffer queue that transports graphics buffer
+ // from the application side to the compositor side.
+ std::shared_ptr<ProducerQueue> GetProducerQueue();
// Get the shared memory metadata buffer for this display surface. If it is
// not yet allocated, this will allocate it.
@@ -93,6 +90,9 @@
bool blur_behind_;
DisplaySurfaceMetadata* mapped_metadata_buffer_;
+ // TODO(jwcai) Add support for multiple queues.
+ std::shared_ptr<ProducerQueue> producer_queue_;
+
DisplaySurfaceClient(const DisplaySurfaceClient&) = delete;
void operator=(const DisplaySurfaceClient&) = delete;
};
diff --git a/libs/vr/libdisplay/include/private/dvr/display_rpc.h b/libs/vr/libdisplay/include/private/dvr/display_rpc.h
index d37aed7..465fbae 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_rpc.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_rpc.h
@@ -212,7 +212,7 @@
kOpGetMetrics = 0,
kOpGetEdsCapture,
kOpCreateSurface,
- kOpAllocateBuffer,
+ kOpCreateBufferQueue,
kOpSetAttributes,
kOpGetMetadataBuffer,
kOpCreateVideoMeshSurface,
@@ -233,8 +233,8 @@
PDX_REMOTE_METHOD(CreateSurface, kOpCreateSurface,
int(int width, int height, int format, int usage,
DisplaySurfaceFlags flags));
- PDX_REMOTE_METHOD(AllocateBuffer, kOpAllocateBuffer,
- std::pair<std::uint32_t, LocalChannelHandle>(Void));
+ PDX_REMOTE_METHOD(CreateBufferQueue, kOpCreateBufferQueue,
+ LocalChannelHandle(Void));
PDX_REMOTE_METHOD(SetAttributes, kOpSetAttributes,
int(const DisplaySurfaceAttributes& attributes));
PDX_REMOTE_METHOD(GetMetadataBuffer, kOpGetMetadataBuffer,
diff --git a/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h b/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h
index 87e9c9f..4b1fa98 100644
--- a/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h
+++ b/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h
@@ -14,57 +14,27 @@
namespace android {
namespace dvr {
-// NativeBufferQueue manages a queue of NativeBufferProducers allocated from a
-// DisplaySurfaceClient. Buffers are automatically re-enqueued when released by
-// the consumer side.
+// A wrapper over dvr::ProducerQueue that caches EGLImage.
class NativeBufferQueue {
public:
// Create a queue with the given number of free buffers.
- NativeBufferQueue(const std::shared_ptr<DisplaySurfaceClient>& surface,
- size_t capacity);
NativeBufferQueue(EGLDisplay display,
const std::shared_ptr<DisplaySurfaceClient>& surface,
size_t capacity);
- ~NativeBufferQueue();
- std::shared_ptr<DisplaySurfaceClient> surface() const { return surface_; }
+ size_t GetQueueCapacity() const { return producer_queue_->capacity(); }
// Dequeue a buffer from the free queue, blocking until one is available.
NativeBufferProducer* Dequeue();
- // Enqueue a buffer at the end of the free queue.
- void Enqueue(NativeBufferProducer* buf);
-
- // Get the number of free buffers in the queue.
- size_t GetFreeBufferCount() const;
-
- // Get the total number of buffers managed by this queue.
- size_t GetQueueCapacity() const;
-
- // Accessors for display surface buffer attributes.
- int width() const { return surface_->width(); }
- int height() const { return surface_->height(); }
- int format() const { return surface_->format(); }
- int usage() const { return surface_->usage(); }
+ // An noop here to keep Vulkan path in GraphicsContext happy.
+ // TODO(jwcai, cort) Move Vulkan path into GVR/Google3.
+ void Enqueue(NativeBufferProducer* buffer) {}
private:
- // Wait for buffers to be released and enqueue them.
- bool WaitForBuffers();
-
- std::shared_ptr<DisplaySurfaceClient> surface_;
-
- // A list of strong pointers to the buffers, used for managing buffer
- // lifetime.
- std::vector<android::sp<NativeBufferProducer>> buffers_;
-
- // Used to implement queue semantics.
- RingBuffer<NativeBufferProducer*> buffer_queue_;
-
- // Epoll fd used to wait for BufferHub events.
- int epoll_fd_;
-
- NativeBufferQueue(const NativeBufferQueue&) = delete;
- void operator=(NativeBufferQueue&) = delete;
+ EGLDisplay display_;
+ std::shared_ptr<ProducerQueue> producer_queue_;
+ std::vector<sp<NativeBufferProducer>> buffers_;
};
} // namespace dvr
diff --git a/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h b/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h
index e52d0b9..3a7f125 100644
--- a/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h
@@ -25,7 +25,7 @@
private:
friend BASE;
- std::shared_ptr<android::dvr::ProducerQueue> producer_queue_;
+ std::shared_ptr<ProducerQueue> producer_queue_;
VideoMeshSurfaceMetadata* mapped_metadata_buffer_;
explicit VideoMeshSurfaceClient(LocalChannelHandle handle);
diff --git a/libs/vr/libdisplay/native_buffer_queue.cpp b/libs/vr/libdisplay/native_buffer_queue.cpp
index 8dd0ee0..d516d63 100644
--- a/libs/vr/libdisplay/native_buffer_queue.cpp
+++ b/libs/vr/libdisplay/native_buffer_queue.cpp
@@ -13,138 +13,51 @@
namespace dvr {
NativeBufferQueue::NativeBufferQueue(
- const std::shared_ptr<DisplaySurfaceClient>& surface, size_t capacity)
- : NativeBufferQueue(nullptr, surface, capacity) {}
-
-NativeBufferQueue::NativeBufferQueue(
EGLDisplay display, const std::shared_ptr<DisplaySurfaceClient>& surface,
size_t capacity)
- : surface_(surface),
- buffers_(capacity),
- buffer_queue_(capacity) {
- LOG_ALWAYS_FATAL_IF(!surface);
-
- epoll_fd_ = epoll_create(64);
- if (epoll_fd_ < 0) {
- ALOGE("NativeBufferQueue::NativeBufferQueue: Failed to create epoll fd: %s",
- strerror(errno));
- return;
- }
-
- // The kSurfaceBufferMaxCount must be >= the capacity so that shader code
- // can bind surface buffer array data.
- LOG_ALWAYS_FATAL_IF(kSurfaceBufferMaxCount < capacity);
+ : display_(display), buffers_(capacity) {
+ std::shared_ptr<ProducerQueue> queue = surface->GetProducerQueue();
for (size_t i = 0; i < capacity; i++) {
- uint32_t buffer_index = 0;
- auto buffer = surface_->AllocateBuffer(&buffer_index);
- if (!buffer) {
- ALOGE("NativeBufferQueue::NativeBufferQueue: Failed to allocate buffer!");
- return;
- }
-
- // TODO(jbates): store an index associated with each buffer so that we can
- // determine which index in DisplaySurfaceMetadata it is associated
- // with.
- buffers_.push_back(new NativeBufferProducer(buffer, display, buffer_index));
- NativeBufferProducer* native_buffer = buffers_.back().get();
-
- epoll_event event = {.events = EPOLLIN | EPOLLET,
- .data = {.ptr = native_buffer}};
- if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, buffer->event_fd(), &event) <
- 0) {
+ size_t slot;
+ // TODO(jwcai) Should change to use BufferViewPort's spec to config.
+ int ret =
+ queue->AllocateBuffer(surface->width(), surface->height(),
+ surface->format(), surface->usage(), 1, &slot);
+ if (ret < 0) {
ALOGE(
- "NativeBufferQueue::NativeBufferQueue: Failed to add buffer producer "
- "to epoll set: %s",
- strerror(errno));
+ "NativeBufferQueue::NativeBufferQueue: Failed to allocate buffer, "
+ "error=%d",
+ ret);
return;
}
- Enqueue(native_buffer);
- }
-}
-
-NativeBufferQueue::~NativeBufferQueue() {
- if (epoll_fd_ >= 0)
- close(epoll_fd_);
-}
-
-bool NativeBufferQueue::WaitForBuffers() {
- ATRACE_NAME("NativeBufferQueue::WaitForBuffers");
- // Intentionally set this to one so that we don't waste time retrieving too
- // many buffers.
- constexpr size_t kMaxEvents = 1;
- std::array<epoll_event, kMaxEvents> events;
-
- while (buffer_queue_.IsEmpty()) {
- int num_events = epoll_wait(epoll_fd_, events.data(), events.size(), -1);
- if (num_events < 0 && errno != EINTR) {
- ALOGE("NativeBufferQueue:WaitForBuffers: Failed to wait for buffers: %s",
- strerror(errno));
- return false;
- }
-
- ALOGD_IF(TRACE, "NativeBufferQueue::WaitForBuffers: num_events=%d",
- num_events);
-
- for (int i = 0; i < num_events; i++) {
- NativeBufferProducer* buffer =
- static_cast<NativeBufferProducer*>(events[i].data.ptr);
- ALOGD_IF(TRACE,
- "NativeBufferQueue::WaitForBuffers: event %d: buffer_id=%d "
- "events=0x%x",
- i, buffer->buffer()->id(), events[i].events);
-
- if (events[i].events & EPOLLIN) {
- const int ret = buffer->GainAsync();
- if (ret < 0) {
- ALOGE("NativeBufferQueue::WaitForBuffers: Failed to gain buffer: %s",
- strerror(-ret));
- continue;
- }
-
- Enqueue(buffer);
- }
- }
+ ALOGD_IF(TRACE,
+ "NativeBufferQueue::NativeBufferQueue: New buffer allocated at "
+ "slot=%zu",
+ slot);
}
- return true;
-}
-
-void NativeBufferQueue::Enqueue(NativeBufferProducer* buf) {
- ATRACE_NAME("NativeBufferQueue::Enqueue");
- if (buffer_queue_.IsFull()) {
- ALOGE("NativeBufferQueue::Enqueue: Queue is full!");
- return;
- }
-
- buffer_queue_.Append(buf);
+ producer_queue_ = std::move(queue);
}
NativeBufferProducer* NativeBufferQueue::Dequeue() {
ATRACE_NAME("NativeBufferQueue::Dequeue");
- ALOGD_IF(TRACE, "NativeBufferQueue::Dequeue: count=%zd",
- buffer_queue_.GetSize());
- if (buffer_queue_.IsEmpty() && !WaitForBuffers())
- return nullptr;
+ // This never times out.
+ size_t slot;
+ pdx::LocalHandle fence;
+ std::shared_ptr<BufferProducer> buffer =
+ producer_queue_->Dequeue(-1, &slot, &fence);
- NativeBufferProducer* buf = buffer_queue_.Front();
- buffer_queue_.PopFront();
- if (buf == nullptr) {
- ALOGE("NativeBufferQueue::Dequeue: Buffer at tail was nullptr!!!");
- return nullptr;
+ if (buffers_[slot] == nullptr) {
+ buffers_[slot] = new NativeBufferProducer(buffer, display_, slot);
}
- return buf;
-}
-
-size_t NativeBufferQueue::GetFreeBufferCount() const {
- return buffer_queue_.GetSize();
-}
-
-size_t NativeBufferQueue::GetQueueCapacity() const {
- return buffer_queue_.GetCapacity();
+ ALOGD_IF(TRACE,
+ "NativeBufferQueue::Dequeue: dequeue buffer at slot=%zu, buffer=%p",
+ slot, buffers_[slot].get());
+ return buffers_[slot].get();
}
} // namespace dvr