1 #ifndef ANDROID_DVR_BUFFER_HUB_QUEUE_CLIENT_H_
2 #define ANDROID_DVR_BUFFER_HUB_QUEUE_CLIENT_H_
4 #include <gui/BufferQueueDefs.h>
6 #include <pdx/client.h>
7 #include <pdx/status.h>
8 #include <private/dvr/bufferhub_rpc.h>
9 #include <private/dvr/buffer_hub_client.h>
10 #include <private/dvr/epoll_file_descriptor.h>
11 #include <private/dvr/ring_buffer.h>
21 // |BufferHubQueue| manages a queue of |BufferHubBuffer|s. Buffers are
22 // automatically re-requeued when released by the remote side.
23 class BufferHubQueue : public pdx::Client {
25 using BufferAvailableCallback = std::function<void()>;
26 using BufferRemovedCallback =
27 std::function<void(const std::shared_ptr<BufferHubBuffer>&)>;
29 virtual ~BufferHubQueue() {}
31 // Creates a new consumer queue that is attached to the producer. Returns
32 // a new consumer queue client or nullptr on failure.
33 std::unique_ptr<ConsumerQueue> CreateConsumerQueue();
35 // Creates a new consumer queue that is attached to the producer. This queue
36 // sets each of its imported consumer buffers to the ignored state to avoid
37 // participation in lifecycle events.
38 std::unique_ptr<ConsumerQueue> CreateSilentConsumerQueue();
40 // Returns whether the buffer queue is in async mode.
41 bool is_async() const { return is_async_; }
43 // Returns the default buffer width of this buffer queue.
44 uint32_t default_width() const { return default_width_; }
46 // Returns the default buffer height of this buffer queue.
47 uint32_t default_height() const { return default_height_; }
49 // Returns the default buffer format of this buffer queue.
50 uint32_t default_format() const { return default_format_; }
52 // Creates a new consumer in handle form for immediate transport over RPC.
53 pdx::Status<pdx::LocalChannelHandle> CreateConsumerQueueHandle();
55 // Returns the number of buffers avaiable for dequeue.
56 size_t count() const { return available_buffers_.GetSize(); }
58 // Returns the total number of buffers that the queue is tracking.
59 size_t capacity() const { return capacity_; }
61 // Returns the size of metadata structure associated with this queue.
62 size_t metadata_size() const { return meta_size_; }
64 // Returns whether the buffer queue is full.
65 bool is_full() const { return available_buffers_.IsFull(); }
67 explicit operator bool() const { return epoll_fd_.IsValid(); }
69 std::shared_ptr<BufferHubBuffer> GetBuffer(size_t slot) const {
70 return buffers_[slot];
73 pdx::Status<int> GetEventMask(int events) {
74 if (auto* client_channel = GetChannel()) {
75 return client_channel->GetEventMask(events);
77 return pdx::ErrorStatus(EINVAL);
81 // Returns an fd that signals pending queue events using
82 // EPOLLIN/POLLIN/readible. Either HandleQueueEvents or WaitForBuffers may be
83 // called to handle pending queue events.
84 int queue_fd() const { return epoll_fd_.Get(); }
86 // Handles any pending events, returning available buffers to the queue and
87 // reaping disconnected buffers. Returns true if successful, false if an error
89 bool HandleQueueEvents() { return WaitForBuffers(0); }
91 // Set buffer event callbacks, which are std::function wrappers. The caller is
92 // responsible for ensuring the validity of these callbacks' callable targets.
93 void SetBufferAvailableCallback(BufferAvailableCallback callback);
94 void SetBufferRemovedCallback(BufferRemovedCallback callback);
96 // The queue tracks at most this many buffers.
97 static constexpr size_t kMaxQueueCapacity =
98 android::BufferQueueDefs::NUM_BUFFER_SLOTS;
100 static constexpr int kNoTimeOut = -1;
102 int id() const { return id_; }
103 bool hung_up() const { return hung_up_; }
106 BufferHubQueue(pdx::LocalChannelHandle channel);
107 BufferHubQueue(const std::string& endpoint_path);
109 // Imports the queue parameters by querying BufferHub for the parameters for
111 pdx::Status<void> ImportQueue();
113 // Sets up the queue with the given parameters.
114 void SetupQueue(const QueueInfo& queue_info);
116 // Register a buffer for management by the queue. Used by subclasses to add a
117 // buffer to internal bookkeeping.
118 pdx::Status<void> AddBuffer(const std::shared_ptr<BufferHubBuffer>& buffer,
121 // Called by ProducerQueue::RemoveBuffer and ConsumerQueue::RemoveBuffer only
122 // to deregister a buffer for epoll and internal bookkeeping.
123 virtual pdx::Status<void> RemoveBuffer(size_t slot);
125 // Dequeue a buffer from the free queue, blocking until one is available. The
126 // timeout argument specifies the number of milliseconds that |Dequeue()| will
127 // block. Specifying a timeout of -1 causes Dequeue() to block indefinitely,
128 // while specifying a timeout equal to zero cause Dequeue() to return
129 // immediately, even if no buffers are available.
130 pdx::Status<std::shared_ptr<BufferHubBuffer>> Dequeue(
131 int timeout, size_t* slot, void* meta, pdx::LocalHandle* fence);
133 // Waits for buffers to become available and adds them to the available queue.
134 bool WaitForBuffers(int timeout);
136 pdx::Status<void> HandleBufferEvent(size_t slot, int event_fd,
138 pdx::Status<void> HandleQueueEvent(int poll_events);
140 // Entry in the ring buffer of available buffers that stores related
144 Entry(const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot)
145 : buffer(buffer), slot(slot) {}
146 Entry(const std::shared_ptr<BufferHubBuffer>& buffer,
147 std::unique_ptr<uint8_t[]> metadata, pdx::LocalHandle fence,
150 metadata(std::move(metadata)),
151 fence(std::move(fence)),
153 Entry(Entry&&) = default;
154 Entry& operator=(Entry&&) = default;
156 std::shared_ptr<BufferHubBuffer> buffer;
157 std::unique_ptr<uint8_t[]> metadata;
158 pdx::LocalHandle fence;
162 // Enqueues a buffer to the available list (Gained for producer or Acquireed
164 pdx::Status<void> Enqueue(Entry entry);
166 virtual pdx::Status<Entry> OnBufferReady(
167 const std::shared_ptr<BufferHubBuffer>& buf, size_t slot) = 0;
169 // Called when a buffer is allocated remotely.
170 virtual pdx::Status<void> OnBufferAllocated() { return {}; }
172 // Size of the metadata that buffers in this queue cary.
173 size_t meta_size_{0};
178 // Special epoll data field indicating that the epoll event refers to the
180 static constexpr int64_t kEpollQueueEventIndex = -1;
182 static constexpr size_t kMaxEvents = 128;
184 // The u64 data field of an epoll event is interpreted as int64_t:
185 // When |index| >= 0 and |index| < kMaxQueueCapacity it refers to a specific
186 // element of |buffers_| as a direct index;
187 static bool is_buffer_event_index(int64_t index) {
189 index < static_cast<int64_t>(BufferHubQueue::kMaxQueueCapacity);
192 // When |index| == kEpollQueueEventIndex it refers to the queue itself.
193 static bool is_queue_event_index(int64_t index) {
194 return index == BufferHubQueue::kEpollQueueEventIndex;
197 // Whether the buffer queue is operating in Async mode.
198 // From GVR's perspective of view, this means a buffer can be acquired
199 // asynchronously by the compositor.
200 // From Android Surface's perspective of view, this is equivalent to
201 // IGraphicBufferProducer's async mode. When in async mode, a producer
202 // will never block even if consumer is running slow.
203 bool is_async_{false};
205 // Default buffer width that is set during ProducerQueue's creation.
206 size_t default_width_{1};
208 // Default buffer height that is set during ProducerQueue's creation.
209 size_t default_height_{1};
211 // Default buffer format that is set during ProducerQueue's creation.
212 int32_t default_format_{1}; // PIXEL_FORMAT_RGBA_8888
214 // Tracks the buffers belonging to this queue. Buffers are stored according to
215 // "slot" in this vector. Each slot is a logical id of the buffer within this
216 // queue regardless of its queue position or presence in the ring buffer.
217 std::vector<std::shared_ptr<BufferHubBuffer>> buffers_{kMaxQueueCapacity};
219 // Buffers and related data that are available for dequeue.
220 RingBuffer<Entry> available_buffers_{kMaxQueueCapacity};
222 // Keeps track with how many buffers have been added into the queue.
225 // Epoll fd used to manage buffer events.
226 EpollFileDescriptor epoll_fd_;
228 // Flag indicating that the other side hung up. For ProducerQueues this
229 // triggers when BufferHub dies or explicitly closes the queue channel. For
230 // ConsumerQueues this can either mean the same or that the ProducerQueue on
231 // the other end hung up.
232 bool hung_up_{false};
234 // Global id for the queue that is consistent across processes.
237 // Buffer event callbacks
238 BufferAvailableCallback on_buffer_available_;
239 BufferRemovedCallback on_buffer_removed_;
241 BufferHubQueue(const BufferHubQueue&) = delete;
242 void operator=(BufferHubQueue&) = delete;
245 class ProducerQueue : public pdx::ClientBase<ProducerQueue, BufferHubQueue> {
247 // Usage bits in |usage_set_mask| will be automatically masked on. Usage bits
248 // in |usage_clear_mask| will be automatically masked off. Note that
249 // |usage_set_mask| and |usage_clear_mask| may conflict with each other, but
250 // |usage_set_mask| takes precedence over |usage_clear_mask|. All buffer
251 // allocation through this producer queue shall not have any of the usage bits
252 // in |usage_deny_set_mask| set. Allocation calls violating this will be
253 // rejected. All buffer allocation through this producer queue must have all
254 // the usage bits in |usage_deny_clear_mask| set. Allocation calls violating
255 // this will be rejected. Note that |usage_deny_set_mask| and
256 // |usage_deny_clear_mask| shall not conflict with each other. Such
257 // configuration will be treated as invalid input on creation.
258 static std::unique_ptr<ProducerQueue> Create(
259 const ProducerQueueConfig& config, const UsagePolicy& usage) {
260 return BASE::Create(config, usage);
263 // Import a ProducerQueue from a channel handle.
264 static std::unique_ptr<ProducerQueue> Import(pdx::LocalChannelHandle handle) {
265 return BASE::Create(std::move(handle));
268 // Get a buffer producer. Note that the method doesn't check whether the
269 // buffer slot has a valid buffer that has been allocated already. When no
270 // buffer has been imported before it returns nullptr; otherwise it returns
271 // a shared pointer to a BufferProducer.
272 std::shared_ptr<BufferProducer> GetBuffer(size_t slot) const {
273 return std::static_pointer_cast<BufferProducer>(
274 BufferHubQueue::GetBuffer(slot));
277 // Batch allocate buffers. Once allocated, producer buffers are automatically
278 // enqueue'd into the ProducerQueue and available to use (i.e. in GAINED
279 // state). Upon success, returns a list of slots for each buffer allocated.
280 pdx::Status<std::vector<size_t>> AllocateBuffers(
281 uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
282 uint64_t usage, size_t buffer_count);
284 // Allocate producer buffer to populate the queue. Once allocated, a producer
285 // buffer is automatically enqueue'd into the ProducerQueue and available to
286 // use (i.e. in GAINED state). Upon success, returns the slot number for the
288 pdx::Status<size_t> AllocateBuffer(uint32_t width, uint32_t height,
289 uint32_t layer_count, uint32_t format,
292 // Add a producer buffer to populate the queue. Once added, a producer buffer
293 // is available to use (i.e. in GAINED state).
294 pdx::Status<void> AddBuffer(const std::shared_ptr<BufferProducer>& buffer,
297 // Remove producer buffer from the queue.
298 pdx::Status<void> RemoveBuffer(size_t slot) override;
300 // Dequeue a producer buffer to write. The returned buffer in |Gain|'ed mode,
301 // and caller should call Post() once it's done writing to release the buffer
302 // to the consumer side.
303 pdx::Status<std::shared_ptr<BufferProducer>> Dequeue(
304 int timeout, size_t* slot, pdx::LocalHandle* release_fence);
306 // Enqueues a producer buffer in the queue.
307 pdx::Status<void> Enqueue(const std::shared_ptr<BufferProducer>& buffer,
309 return BufferHubQueue::Enqueue({buffer, slot});
315 // Constructors are automatically exposed through ProducerQueue::Create(...)
316 // static template methods inherited from ClientBase, which take the same
317 // arguments as the constructors.
318 explicit ProducerQueue(pdx::LocalChannelHandle handle);
319 ProducerQueue(const ProducerQueueConfig& config, const UsagePolicy& usage);
321 pdx::Status<Entry> OnBufferReady(
322 const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) override;
325 class ConsumerQueue : public BufferHubQueue {
327 // Get a buffer consumer. Note that the method doesn't check whether the
328 // buffer slot has a valid buffer that has been imported already. When no
329 // buffer has been imported before it returns nullptr; otherwise returns a
330 // shared pointer to a BufferConsumer.
331 std::shared_ptr<BufferConsumer> GetBuffer(size_t slot) const {
332 return std::static_pointer_cast<BufferConsumer>(
333 BufferHubQueue::GetBuffer(slot));
336 // Import a ConsumerQueue from a channel handle. |ignore_on_import| controls
337 // whether or not buffers are set to be ignored when imported. This may be
338 // used to avoid participation in the buffer lifecycle by a consumer queue
339 // that is only used to spawn other consumer queues, such as in an
340 // intermediate service.
341 static std::unique_ptr<ConsumerQueue> Import(pdx::LocalChannelHandle handle,
342 bool ignore_on_import = false) {
343 return std::unique_ptr<ConsumerQueue>(
344 new ConsumerQueue(std::move(handle), ignore_on_import));
347 // Import newly created buffers from the service side.
348 // Returns number of buffers successfully imported or an error.
349 pdx::Status<size_t> ImportBuffers();
351 // Dequeue a consumer buffer to read. The returned buffer in |Acquired|'ed
352 // mode, and caller should call Releasse() once it's done writing to release
353 // the buffer to the producer side. |meta| is passed along from BufferHub,
354 // The user of BufferProducer is responsible with making sure that the
355 // Dequeue() is done with the corect metadata type and size with those used
356 // when the buffer is orignally created.
357 template <typename Meta>
358 pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
359 int timeout, size_t* slot, Meta* meta, pdx::LocalHandle* acquire_fence) {
360 return Dequeue(timeout, slot, meta, sizeof(*meta), acquire_fence);
362 pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
363 int timeout, size_t* slot, pdx::LocalHandle* acquire_fence) {
364 return Dequeue(timeout, slot, nullptr, 0, acquire_fence);
367 pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
368 int timeout, size_t* slot, void* meta, size_t meta_size,
369 pdx::LocalHandle* acquire_fence);
372 friend BufferHubQueue;
374 ConsumerQueue(pdx::LocalChannelHandle handle, bool ignore_on_import = false);
376 // Add a consumer buffer to populate the queue. Once added, a consumer buffer
377 // is NOT available to use until the producer side |Post| it. |WaitForBuffers|
378 // will catch the |Post| and |Acquire| the buffer to make it available for
380 pdx::Status<void> AddBuffer(const std::shared_ptr<BufferConsumer>& buffer,
383 pdx::Status<Entry> OnBufferReady(
384 const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) override;
386 pdx::Status<void> OnBufferAllocated() override;
388 // Flag indicating that imported (consumer) buffers should be ignored when
389 // imported to avoid participating in the buffer ownership flow.
390 bool ignore_on_import_;
394 } // namespace android
396 #endif // ANDROID_DVR_BUFFER_HUB_QUEUE_CLIENT_H_