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/libvrflinger/display_surface.cpp b/libs/vr/libvrflinger/display_surface.cpp
index d427ea6..66808ca 100644
--- a/libs/vr/libvrflinger/display_surface.cpp
+++ b/libs/vr/libvrflinger/display_surface.cpp
@@ -26,7 +26,7 @@
: SurfaceChannel(service, surface_id, SurfaceTypeEnum::Normal,
sizeof(DisplaySurfaceMetadata)),
process_id_(process_id),
- posted_buffers_(kMaxPostedBuffers),
+ acquired_buffers_(kMaxPostedBuffers),
video_mesh_surfaces_updated_(false),
width_(width),
height_(height),
@@ -40,7 +40,6 @@
manager_visible_(false),
manager_z_order_(0),
manager_blur_(0.0f),
- allocated_buffer_index_(0),
layer_order_(0) {}
DisplaySurface::~DisplaySurface() {
@@ -84,71 +83,107 @@
client_blur_behind_ = blur_behind;
}
+void DisplaySurface::DequeueBuffersLocked() {
+ if (consumer_queue_ == nullptr) {
+ ALOGE(
+ "DisplaySurface::DequeueBuffersLocked: Consumer queue is not "
+ "initialized.");
+ return;
+ }
+
+ size_t slot;
+ uint64_t sequence;
+ while (true) {
+ LocalHandle acquire_fence;
+ auto buffer_consumer =
+ consumer_queue_->Dequeue(0, &slot, &sequence, &acquire_fence);
+ if (!buffer_consumer) {
+ ALOGD_IF(TRACE,
+ "DisplaySurface::DequeueBuffersLocked: We have dequeued all "
+ "available buffers.");
+ return;
+ }
+
+ if (!IsVisible()) {
+ ATRACE_NAME("DropFrameOnInvisibleSurface");
+ ALOGD_IF(TRACE,
+ "DisplaySurface::DequeueBuffersLocked: Discarding buffer_id=%d "
+ "on invisible surface.",
+ buffer_consumer->id());
+ buffer_consumer->Discard();
+ continue;
+ }
+
+ if (acquired_buffers_.IsFull()) {
+ ALOGE(
+ "DisplaySurface::DequeueBuffersLocked: Posted buffers full, "
+ "overwriting.");
+ acquired_buffers_.PopBack();
+ }
+
+ acquired_buffers_.Append(
+ AcquiredBuffer(buffer_consumer, std::move(acquire_fence), sequence));
+ }
+}
+
+AcquiredBuffer DisplaySurface::AcquireCurrentBuffer() {
+ std::lock_guard<std::mutex> autolock(lock_);
+ DequeueBuffersLocked();
+
+ if (acquired_buffers_.IsEmpty()) {
+ ALOGE(
+ "DisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer when "
+ "none are posted.");
+ return AcquiredBuffer();
+ }
+ AcquiredBuffer buffer = std::move(acquired_buffers_.Front());
+ acquired_buffers_.PopFront();
+ ALOGD_IF(TRACE, "DisplaySurface::AcquireCurrentBuffer: buffer: %p",
+ buffer.buffer().get());
+ return buffer;
+}
+
AcquiredBuffer DisplaySurface::AcquireNewestAvailableBuffer(
AcquiredBuffer* skipped_buffer) {
std::lock_guard<std::mutex> autolock(lock_);
+ DequeueBuffersLocked();
+
AcquiredBuffer buffer;
int frames = 0;
// Basic latency stopgap for when the application misses a frame:
// If the application recovers on the 2nd or 3rd (etc) frame after
// missing, this code will skip frames to catch up by checking if
// the next frame is also available.
- while (!posted_buffers_.IsEmpty() && posted_buffers_.Front().IsAvailable()) {
+ while (!acquired_buffers_.IsEmpty() &&
+ acquired_buffers_.Front().IsAvailable()) {
// Capture the skipped buffer into the result parameter.
// Note that this API only supports skipping one buffer per vsync.
if (frames > 0 && skipped_buffer)
*skipped_buffer = std::move(buffer);
++frames;
- buffer = std::move(posted_buffers_.Front());
- posted_buffers_.PopFront();
+ buffer = std::move(acquired_buffers_.Front());
+ acquired_buffers_.PopFront();
if (frames == 2)
break;
}
+ ALOGD_IF(TRACE, "DisplaySurface::AcquireNewestAvailableBuffer: buffer: %p",
+ buffer.buffer().get());
return buffer;
}
-bool DisplaySurface::IsBufferAvailable() const {
+bool DisplaySurface::IsBufferAvailable() {
std::lock_guard<std::mutex> autolock(lock_);
- return !posted_buffers_.IsEmpty() && posted_buffers_.Front().IsAvailable();
+ DequeueBuffersLocked();
+
+ return !acquired_buffers_.IsEmpty() &&
+ acquired_buffers_.Front().IsAvailable();
}
-bool DisplaySurface::IsBufferPosted() const {
+bool DisplaySurface::IsBufferPosted() {
std::lock_guard<std::mutex> autolock(lock_);
- return !posted_buffers_.IsEmpty();
-}
+ DequeueBuffersLocked();
-AcquiredBuffer DisplaySurface::AcquireCurrentBuffer() {
- std::lock_guard<std::mutex> autolock(lock_);
- if (posted_buffers_.IsEmpty()) {
- ALOGE("Error: attempt to acquire buffer when none are posted.");
- return AcquiredBuffer();
- }
- AcquiredBuffer buffer = std::move(posted_buffers_.Front());
- posted_buffers_.PopFront();
- return buffer;
-}
-
-int DisplaySurface::GetConsumers(std::vector<LocalChannelHandle>* consumers) {
- std::lock_guard<std::mutex> autolock(lock_);
- std::vector<LocalChannelHandle> items;
-
- for (auto pair : buffers_) {
- const auto& buffer = pair.second;
-
- Status<LocalChannelHandle> consumer_channel = buffer->CreateConsumer();
- if (!consumer_channel) {
- ALOGE(
- "DisplaySurface::GetConsumers: Failed to get a new consumer for "
- "buffer %d: %s",
- buffer->id(), consumer_channel.GetErrorMessage().c_str());
- return -consumer_channel.error();
- }
-
- items.push_back(consumer_channel.take());
- }
-
- *consumers = std::move(items);
- return 0;
+ return !acquired_buffers_.IsEmpty();
}
int DisplaySurface::HandleMessage(pdx::Message& message) {
@@ -158,9 +193,9 @@
*this, &DisplaySurface::OnClientSetAttributes, message);
break;
- case DisplayRPC::AllocateBuffer::Opcode:
- DispatchRemoteMethod<DisplayRPC::AllocateBuffer>(
- *this, &DisplaySurface::OnAllocateBuffer, message);
+ case DisplayRPC::CreateBufferQueue::Opcode:
+ DispatchRemoteMethod<DisplayRPC::CreateBufferQueue>(
+ *this, &DisplaySurface::OnCreateBufferQueue, message);
break;
case DisplayRPC::CreateVideoMeshSurface::Opcode:
@@ -226,58 +261,20 @@
return 0;
}
-// Allocates a new buffer for the DisplaySurface associated with this channel.
-std::pair<uint32_t, LocalChannelHandle> DisplaySurface::OnAllocateBuffer(
- pdx::Message& message) {
- // Inject flag to enable framebuffer compression for the application buffers.
- // TODO(eieio,jbates): Make this configurable per hardware platform.
- const int usage = usage_ | GRALLOC_USAGE_QCOM_FRAMEBUFFER_COMPRESSION;
- const int slice_count =
- (flags_ & static_cast<int>(DisplaySurfaceFlagsEnum::SeparateGeometry))
- ? 2
- : 1;
+LocalChannelHandle DisplaySurface::OnCreateBufferQueue(Message& message) {
+ ATRACE_NAME("DisplaySurface::OnCreateBufferQueue");
- ALOGI_IF(
- TRACE,
- "DisplaySurface::OnAllocateBuffer: width=%d height=%d format=%x usage=%x "
- "slice_count=%d",
- width_, height_, format_, usage, slice_count);
-
- // Create a producer buffer to hand back to the sender.
- auto producer = BufferProducer::Create(width_, height_, format_, usage,
- sizeof(uint64_t), slice_count);
- if (!producer)
- REPLY_ERROR_RETURN(message, EINVAL, {});
-
- // Create and import a consumer attached to the producer.
- Status<LocalChannelHandle> consumer_channel = producer->CreateConsumer();
- if (!consumer_channel)
- REPLY_ERROR_RETURN(message, consumer_channel.error(), {});
-
- std::shared_ptr<BufferConsumer> consumer =
- BufferConsumer::Import(consumer_channel.take());
- if (!consumer)
- REPLY_ERROR_RETURN(message, ENOMEM, {});
-
- // Add the consumer to this surface.
- int err = AddConsumer(consumer);
- if (err < 0) {
- ALOGE("DisplaySurface::OnAllocateBuffer: failed to add consumer: buffer=%d",
- consumer->id());
- REPLY_ERROR_RETURN(message, -err, {});
+ if (consumer_queue_ != nullptr) {
+ ALOGE(
+ "DisplaySurface::OnCreateBufferQueue: A ProdcuerQueue has already been "
+ "created and transported to DisplayClient.");
+ REPLY_ERROR_RETURN(message, EALREADY, {});
}
- // Move the channel handle so that it doesn't get closed when the producer
- // goes out of scope.
- std::pair<uint32_t, LocalChannelHandle> return_value(
- allocated_buffer_index_, std::move(producer->GetChannelHandle()));
+ auto producer = ProducerQueue::Create<uint64_t>();
+ consumer_queue_ = producer->CreateConsumerQueue();
- // Save buffer index, associated with the buffer id so that it can be looked
- // up later.
- buffer_id_to_index_[consumer->id()] = allocated_buffer_index_;
- ++allocated_buffer_index_;
-
- return return_value;
+ return std::move(producer->GetChannelHandle());
}
RemoteChannelHandle DisplaySurface::OnCreateVideoMeshSurface(
@@ -319,103 +316,6 @@
return status.take();
}
-int DisplaySurface::AddConsumer(
- const std::shared_ptr<BufferConsumer>& consumer) {
- ALOGD_IF(TRACE, "DisplaySurface::AddConsumer: buffer_id=%d", consumer->id());
- // Add the consumer to the epoll dispatcher, edge-triggered.
- int err = service()->dispatcher_.AddEventHandler(
- consumer->event_fd(), EPOLLET | EPOLLIN | EPOLLHUP,
- std::bind(&DisplaySurface::HandleConsumerEvents,
- std::static_pointer_cast<DisplaySurface>(shared_from_this()),
- consumer, std::placeholders::_1));
- if (err) {
- ALOGE(
- "DisplaySurface::AddConsumer: failed to add epoll event handler for "
- "consumer: %s",
- strerror(-err));
- return err;
- }
-
- // Add the consumer to the list of buffers for this surface.
- std::lock_guard<std::mutex> autolock(lock_);
- buffers_.insert(std::make_pair(consumer->id(), consumer));
- return 0;
-}
-
-void DisplaySurface::RemoveConsumer(
- const std::shared_ptr<BufferConsumer>& consumer) {
- ALOGD_IF(TRACE, "DisplaySurface::RemoveConsumer: buffer_id=%d",
- consumer->id());
- service()->dispatcher_.RemoveEventHandler(consumer->event_fd());
-
- std::lock_guard<std::mutex> autolock(lock_);
- buffers_.erase(consumer->id());
-}
-
-void DisplaySurface::RemoveConsumerUnlocked(
- const std::shared_ptr<BufferConsumer>& consumer) {
- ALOGD_IF(TRACE, "DisplaySurface::RemoveConsumerUnlocked: buffer_id=%d",
- consumer->id());
- service()->dispatcher_.RemoveEventHandler(consumer->event_fd());
- buffers_.erase(consumer->id());
-}
-
-void DisplaySurface::OnPostConsumer(
- const std::shared_ptr<BufferConsumer>& consumer) {
- ATRACE_NAME("DisplaySurface::OnPostConsumer");
- std::lock_guard<std::mutex> autolock(lock_);
-
- if (!IsVisible()) {
- ALOGD_IF(TRACE,
- "DisplaySurface::OnPostConsumer: Discarding buffer_id=%d on "
- "invisible surface.",
- consumer->id());
- consumer->Discard();
- return;
- }
-
- if (posted_buffers_.IsFull()) {
- ALOGE("Error: posted buffers full, overwriting");
- posted_buffers_.PopBack();
- }
-
- int error;
- posted_buffers_.Append(AcquiredBuffer(consumer, &error));
-
- // Remove the consumer if the other end was closed.
- if (posted_buffers_.Back().IsEmpty() && error == -EPIPE)
- RemoveConsumerUnlocked(consumer);
-}
-
-void DisplaySurface::HandleConsumerEvents(
- const std::shared_ptr<BufferConsumer>& consumer, int events) {
- auto status = consumer->GetEventMask(events);
- if (!status) {
- ALOGW(
- "DisplaySurface::HandleConsumerEvents: Failed to get event mask for "
- "consumer: %s",
- status.GetErrorMessage().c_str());
- return;
- }
-
- events = status.get();
- if (events & EPOLLHUP) {
- ALOGD_IF(TRACE,
- "DisplaySurface::HandleConsumerEvents: removing event handler for "
- "buffer=%d",
- consumer->id());
- RemoveConsumer(consumer);
- } else if (events & EPOLLIN) {
- // BufferHub uses EPOLLIN to signal consumer ownership.
- ALOGD_IF(TRACE,
- "DisplaySurface::HandleConsumerEvents: posting buffer=%d for "
- "process=%d",
- consumer->id(), process_id_);
-
- OnPostConsumer(consumer);
- }
-}
-
std::vector<std::shared_ptr<VideoMeshSurface>>
DisplaySurface::GetVideoMeshSurfaces() {
std::lock_guard<std::mutex> autolock(lock_);