1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#ifndef ANDROID_DVR_BUFFER_HUB_QUEUE_CLIENT_H_
2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#define ANDROID_DVR_BUFFER_HUB_QUEUE_CLIENT_H_
3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <gui/BufferQueueDefs.h>
5e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/client.h>
71db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka#include <pdx/status.h>
8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <private/dvr/buffer_hub_client.h>
952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka#include <private/dvr/bufferhub_rpc.h>
10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <private/dvr/epoll_file_descriptor.h>
11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <private/dvr/ring_buffer.h>
12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <memory>
1452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka#include <queue>
15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <vector>
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android {
18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace dvr {
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass ConsumerQueue;
21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// |BufferHubQueue| manages a queue of |BufferHubBuffer|s. Buffers are
23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// automatically re-requeued when released by the remote side.
24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass BufferHubQueue : public pdx::Client {
25e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
260b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai  using BufferAvailableCallback = std::function<void()>;
270b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai  using BufferRemovedCallback =
280b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai      std::function<void(const std::shared_ptr<BufferHubBuffer>&)>;
290b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai
30e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  virtual ~BufferHubQueue() {}
31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
32b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Creates a new consumer queue that is attached to the producer. Returns
33e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // a new consumer queue client or nullptr on failure.
34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::unique_ptr<ConsumerQueue> CreateConsumerQueue();
35e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
36b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Creates a new consumer queue that is attached to the producer. This queue
378a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  // sets each of its imported consumer buffers to the ignored state to avoid
388a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  // participation in lifecycle events.
398a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  std::unique_ptr<ConsumerQueue> CreateSilentConsumerQueue();
408a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka
416bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  // Returns whether the buffer queue is in async mode.
426bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  bool is_async() const { return is_async_; }
436bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai
44b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Returns the default buffer width of this buffer queue.
456bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  uint32_t default_width() const { return default_width_; }
461601bcfa9cdc07cea8f5980349608e1526690db5Jiwen 'Steve' Cai
47b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Returns the default buffer height of this buffer queue.
486bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  uint32_t default_height() const { return default_height_; }
491601bcfa9cdc07cea8f5980349608e1526690db5Jiwen 'Steve' Cai
50b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Returns the default buffer format of this buffer queue.
516bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  uint32_t default_format() const { return default_format_; }
521601bcfa9cdc07cea8f5980349608e1526690db5Jiwen 'Steve' Cai
53b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Creates a new consumer in handle form for immediate transport over RPC.
5452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  pdx::Status<pdx::LocalChannelHandle> CreateConsumerQueueHandle(
5552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka      bool silent = false);
561db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka
57b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Returns the number of buffers avaiable for dequeue.
5852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  size_t count() const { return available_buffers_.size(); }
59e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
60b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Returns the total number of buffers that the queue is tracking.
61e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  size_t capacity() const { return capacity_; }
62e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
63b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Returns the size of metadata structure associated with this queue.
6452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  size_t metadata_size() const { return user_metadata_size_; }
65e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
66b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Returns whether the buffer queue is full.
6752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  bool is_full() const {
6852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    return available_buffers_.size() >= kMaxQueueCapacity;
6952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  }
70e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
71e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  explicit operator bool() const { return epoll_fd_.IsValid(); }
72e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
73638b7f747df50374d1e91c2496da41f293394e19Jiwen 'Steve' Cai  int GetBufferId(size_t slot) const {
74638b7f747df50374d1e91c2496da41f293394e19Jiwen 'Steve' Cai    return (slot < buffers_.size() && buffers_[slot]) ? buffers_[slot]->id()
75638b7f747df50374d1e91c2496da41f293394e19Jiwen 'Steve' Cai                                                      : -1;
76638b7f747df50374d1e91c2496da41f293394e19Jiwen 'Steve' Cai  }
77638b7f747df50374d1e91c2496da41f293394e19Jiwen 'Steve' Cai
78e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::shared_ptr<BufferHubBuffer> GetBuffer(size_t slot) const {
79e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return buffers_[slot];
80e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
81e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
82b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  pdx::Status<int> GetEventMask(int events) {
83dc14e5bf86b6999a290b64deb44418a8f205296cJiwen 'Steve' Cai    if (auto* client_channel = GetChannel()) {
84dc14e5bf86b6999a290b64deb44418a8f205296cJiwen 'Steve' Cai      return client_channel->GetEventMask(events);
85dc14e5bf86b6999a290b64deb44418a8f205296cJiwen 'Steve' Cai    } else {
86dc14e5bf86b6999a290b64deb44418a8f205296cJiwen 'Steve' Cai      return pdx::ErrorStatus(EINVAL);
87dc14e5bf86b6999a290b64deb44418a8f205296cJiwen 'Steve' Cai    }
88dc14e5bf86b6999a290b64deb44418a8f205296cJiwen 'Steve' Cai  }
89dc14e5bf86b6999a290b64deb44418a8f205296cJiwen 'Steve' Cai
908a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  // Returns an fd that signals pending queue events using
918a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  // EPOLLIN/POLLIN/readible. Either HandleQueueEvents or WaitForBuffers may be
928a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  // called to handle pending queue events.
938a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  int queue_fd() const { return epoll_fd_.Get(); }
948a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka
958a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  // Handles any pending events, returning available buffers to the queue and
968a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  // reaping disconnected buffers. Returns true if successful, false if an error
978a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  // occurred.
988a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  bool HandleQueueEvents() { return WaitForBuffers(0); }
998a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka
1000b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai  // Set buffer event callbacks, which are std::function wrappers. The caller is
1010b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai  // responsible for ensuring the validity of these callbacks' callable targets.
1020b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai  void SetBufferAvailableCallback(BufferAvailableCallback callback);
1030b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai  void SetBufferRemovedCallback(BufferRemovedCallback callback);
1040b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai
105b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // The queue tracks at most this many buffers.
106e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  static constexpr size_t kMaxQueueCapacity =
107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      android::BufferQueueDefs::NUM_BUFFER_SLOTS;
108e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
109e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  static constexpr int kNoTimeOut = -1;
110e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
1111db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka  int id() const { return id_; }
1128a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  bool hung_up() const { return hung_up_; }
1131db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka
114e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko protected:
115b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  BufferHubQueue(pdx::LocalChannelHandle channel);
1161db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka  BufferHubQueue(const std::string& endpoint_path);
1171db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka
1181db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka  // Imports the queue parameters by querying BufferHub for the parameters for
1191db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka  // this channel.
120b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  pdx::Status<void> ImportQueue();
1211db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka
1221db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka  // Sets up the queue with the given parameters.
1236bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  void SetupQueue(const QueueInfo& queue_info);
124e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
125b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Register a buffer for management by the queue. Used by subclasses to add a
126b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // buffer to internal bookkeeping.
127b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  pdx::Status<void> AddBuffer(const std::shared_ptr<BufferHubBuffer>& buffer,
128b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka                              size_t slot);
129e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
130bb701dbac7c9c9eb2a7d0ec48c5e020f1272de13Jiwen 'Steve' Cai  // Called by ProducerQueue::RemoveBuffer and ConsumerQueue::RemoveBuffer only
131e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // to deregister a buffer for epoll and internal bookkeeping.
132bb701dbac7c9c9eb2a7d0ec48c5e020f1272de13Jiwen 'Steve' Cai  virtual pdx::Status<void> RemoveBuffer(size_t slot);
133e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
134005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  // Free all buffers that belongs to this queue. Can only be called from
135005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  // producer side.
136005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  virtual pdx::Status<void> FreeAllBuffers();
137005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai
138e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Dequeue a buffer from the free queue, blocking until one is available. The
139e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // timeout argument specifies the number of milliseconds that |Dequeue()| will
140b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // block. Specifying a timeout of -1 causes Dequeue() to block indefinitely,
141b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // while specifying a timeout equal to zero cause Dequeue() to return
142e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // immediately, even if no buffers are available.
14352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  pdx::Status<std::shared_ptr<BufferHubBuffer>> Dequeue(int timeout,
14452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka                                                        size_t* slot);
145e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
146b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Waits for buffers to become available and adds them to the available queue.
147e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  bool WaitForBuffers(int timeout);
148dc14e5bf86b6999a290b64deb44418a8f205296cJiwen 'Steve' Cai
149b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  pdx::Status<void> HandleBufferEvent(size_t slot, int event_fd,
150b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka                                      int poll_events);
151b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  pdx::Status<void> HandleQueueEvent(int poll_events);
152b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
153b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Entry in the ring buffer of available buffers that stores related
154b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // per-buffer data.
155b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  struct Entry {
156b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    Entry() : slot(0) {}
15752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    Entry(const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot,
15852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka          uint64_t index)
15952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka        : buffer(buffer), slot(slot), index(index) {}
160b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    Entry(const std::shared_ptr<BufferHubBuffer>& buffer,
161b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka          std::unique_ptr<uint8_t[]> metadata, pdx::LocalHandle fence,
162b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka          size_t slot)
163b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka        : buffer(buffer),
164b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka          metadata(std::move(metadata)),
165b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka          fence(std::move(fence)),
166b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka          slot(slot) {}
167b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    Entry(Entry&&) = default;
168b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    Entry& operator=(Entry&&) = default;
169e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
170b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    std::shared_ptr<BufferHubBuffer> buffer;
171b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    std::unique_ptr<uint8_t[]> metadata;
172b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    pdx::LocalHandle fence;
173b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka    size_t slot;
17452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    uint64_t index;
17552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  };
17652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
17752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  struct EntryComparator {
17852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    bool operator()(const Entry& lhs, const Entry& rhs) {
17952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka      return lhs.index > rhs.index;
18052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    }
181b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  };
182b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
183b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Enqueues a buffer to the available list (Gained for producer or Acquireed
184b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // for consumer).
185b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  pdx::Status<void> Enqueue(Entry entry);
186e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
187b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Called when a buffer is allocated remotely.
188b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  virtual pdx::Status<void> OnBufferAllocated() { return {}; }
189e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
190b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Size of the metadata that buffers in this queue cary.
19152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  size_t user_metadata_size_{0};
192e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
193e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private:
194b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  void Initialize();
195b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
196b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Special epoll data field indicating that the epoll event refers to the
197b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // queue.
198b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  static constexpr int64_t kEpollQueueEventIndex = -1;
199b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
200e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  static constexpr size_t kMaxEvents = 128;
201e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
202b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // The u64 data field of an epoll event is interpreted as int64_t:
203e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // When |index| >= 0 and |index| < kMaxQueueCapacity it refers to a specific
204e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // element of |buffers_| as a direct index;
205e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  static bool is_buffer_event_index(int64_t index) {
206e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return index >= 0 &&
207e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko           index < static_cast<int64_t>(BufferHubQueue::kMaxQueueCapacity);
208e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
209e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
210b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // When |index| == kEpollQueueEventIndex it refers to the queue itself.
211e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  static bool is_queue_event_index(int64_t index) {
212e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return index == BufferHubQueue::kEpollQueueEventIndex;
213e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
214e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
2156bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  // Whether the buffer queue is operating in Async mode.
2166bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  // From GVR's perspective of view, this means a buffer can be acquired
2176bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  // asynchronously by the compositor.
2186bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  // From Android Surface's perspective of view, this is equivalent to
2196bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  // IGraphicBufferProducer's async mode. When in async mode, a producer
2206bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  // will never block even if consumer is running slow.
2216bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  bool is_async_{false};
2226bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai
2236bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  // Default buffer width that is set during ProducerQueue's creation.
2241601bcfa9cdc07cea8f5980349608e1526690db5Jiwen 'Steve' Cai  size_t default_width_{1};
2251601bcfa9cdc07cea8f5980349608e1526690db5Jiwen 'Steve' Cai
2266bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  // Default buffer height that is set during ProducerQueue's creation.
2271601bcfa9cdc07cea8f5980349608e1526690db5Jiwen 'Steve' Cai  size_t default_height_{1};
2281601bcfa9cdc07cea8f5980349608e1526690db5Jiwen 'Steve' Cai
2296bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  // Default buffer format that is set during ProducerQueue's creation.
2306bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  int32_t default_format_{1};  // PIXEL_FORMAT_RGBA_8888
2311601bcfa9cdc07cea8f5980349608e1526690db5Jiwen 'Steve' Cai
232b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Tracks the buffers belonging to this queue. Buffers are stored according to
233b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // "slot" in this vector. Each slot is a logical id of the buffer within this
234b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // queue regardless of its queue position or presence in the ring buffer.
235638b7f747df50374d1e91c2496da41f293394e19Jiwen 'Steve' Cai  std::array<std::shared_ptr<BufferHubBuffer>, kMaxQueueCapacity> buffers_;
236b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
237b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Buffers and related data that are available for dequeue.
23852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // RingBuffer<Entry> available_buffers_{kMaxQueueCapacity};
23952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  std::priority_queue<Entry, std::vector<Entry>, EntryComparator>
24052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka      available_buffers_;
241b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
242b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Keeps track with how many buffers have been added into the queue.
243b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  size_t capacity_{0};
244b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
245b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Epoll fd used to manage buffer events.
246e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EpollFileDescriptor epoll_fd_;
247e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
2488a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  // Flag indicating that the other side hung up. For ProducerQueues this
2498a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  // triggers when BufferHub dies or explicitly closes the queue channel. For
2508a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  // ConsumerQueues this can either mean the same or that the ProducerQueue on
2518a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  // the other end hung up.
2528a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  bool hung_up_{false};
2538a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka
2541db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka  // Global id for the queue that is consistent across processes.
255b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  int id_{-1};
2561db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka
2570b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai  // Buffer event callbacks
2580b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai  BufferAvailableCallback on_buffer_available_;
2590b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai  BufferRemovedCallback on_buffer_removed_;
2600b80155bf5c27b47c160d1904ad442842dc8f0c5Jiwen 'Steve' Cai
261e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  BufferHubQueue(const BufferHubQueue&) = delete;
262e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void operator=(BufferHubQueue&) = delete;
263e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
264e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
265e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass ProducerQueue : public pdx::ClientBase<ProducerQueue, BufferHubQueue> {
266e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
267e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Usage bits in |usage_set_mask| will be automatically masked on. Usage bits
268e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // in |usage_clear_mask| will be automatically masked off. Note that
269e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // |usage_set_mask| and |usage_clear_mask| may conflict with each other, but
270e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // |usage_set_mask| takes precedence over |usage_clear_mask|. All buffer
271e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // allocation through this producer queue shall not have any of the usage bits
272e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // in |usage_deny_set_mask| set. Allocation calls violating this will be
273e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // rejected. All buffer allocation through this producer queue must have all
274e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // the usage bits in |usage_deny_clear_mask| set. Allocation calls violating
275e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // this will be rejected. Note that |usage_deny_set_mask| and
276e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // |usage_deny_clear_mask| shall not conflict with each other. Such
277e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // configuration will be treated as invalid input on creation.
2786bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  static std::unique_ptr<ProducerQueue> Create(
2796bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai      const ProducerQueueConfig& config, const UsagePolicy& usage) {
2806bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai    return BASE::Create(config, usage);
2812b99ee560ba14b617ebb4c1997e8b8004f2de22fCorey Tabaka  }
282e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
283b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Import a ProducerQueue from a channel handle.
284b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  static std::unique_ptr<ProducerQueue> Import(pdx::LocalChannelHandle handle) {
2851db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka    return BASE::Create(std::move(handle));
286e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
287e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
288e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Get a buffer producer. Note that the method doesn't check whether the
289e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // buffer slot has a valid buffer that has been allocated already. When no
290b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // buffer has been imported before it returns nullptr; otherwise it returns
291b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // a shared pointer to a BufferProducer.
292e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::shared_ptr<BufferProducer> GetBuffer(size_t slot) const {
293e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return std::static_pointer_cast<BufferProducer>(
294e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        BufferHubQueue::GetBuffer(slot));
295e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
296e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
2978fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai  // Batch allocate buffers. Once allocated, producer buffers are automatically
2988fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai  // enqueue'd into the ProducerQueue and available to use (i.e. in GAINED
2998fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai  // state). Upon success, returns a list of slots for each buffer allocated.
3008fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai  pdx::Status<std::vector<size_t>> AllocateBuffers(
3018fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai      uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
3028fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai      uint64_t usage, size_t buffer_count);
3038fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai
304e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Allocate producer buffer to populate the queue. Once allocated, a producer
305e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // buffer is automatically enqueue'd into the ProducerQueue and available to
3068fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai  // use (i.e. in GAINED state). Upon success, returns the slot number for the
3078fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai  // buffer allocated.
3088fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai  pdx::Status<size_t> AllocateBuffer(uint32_t width, uint32_t height,
3098fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai                                     uint32_t layer_count, uint32_t format,
3108fa4e107ab6cbc24c0e54d44db3341f006fe939aJiwen 'Steve' Cai                                     uint64_t usage);
311e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
312e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Add a producer buffer to populate the queue. Once added, a producer buffer
313b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // is available to use (i.e. in GAINED state).
314b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  pdx::Status<void> AddBuffer(const std::shared_ptr<BufferProducer>& buffer,
315b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka                              size_t slot);
316e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
317bb701dbac7c9c9eb2a7d0ec48c5e020f1272de13Jiwen 'Steve' Cai  // Remove producer buffer from the queue.
318bb701dbac7c9c9eb2a7d0ec48c5e020f1272de13Jiwen 'Steve' Cai  pdx::Status<void> RemoveBuffer(size_t slot) override;
319e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
320005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  // Free all buffers on this producer queue.
321005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  pdx::Status<void> FreeAllBuffers() override {
322005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai    return BufferHubQueue::FreeAllBuffers();
323005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai  }
324005f45d7bb059c0ef8d69f1cac81bca4f70852afJiwen 'Steve' Cai
325e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Dequeue a producer buffer to write. The returned buffer in |Gain|'ed mode,
326e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // and caller should call Post() once it's done writing to release the buffer
327e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // to the consumer side.
3289d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  pdx::Status<std::shared_ptr<BufferProducer>> Dequeue(
329b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka      int timeout, size_t* slot, pdx::LocalHandle* release_fence);
33052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  pdx::Status<std::shared_ptr<BufferProducer>> Dequeue(
33152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka      int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
33252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka      pdx::LocalHandle* release_fence);
333b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka
334b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  // Enqueues a producer buffer in the queue.
335b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  pdx::Status<void> Enqueue(const std::shared_ptr<BufferProducer>& buffer,
33652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka                            size_t slot, uint64_t index) {
33752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    return BufferHubQueue::Enqueue({buffer, slot, index});
338b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  }
339e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
340e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private:
341e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  friend BASE;
342e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
343e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Constructors are automatically exposed through ProducerQueue::Create(...)
344e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // static template methods inherited from ClientBase, which take the same
345e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // arguments as the constructors.
346b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  explicit ProducerQueue(pdx::LocalChannelHandle handle);
3476bffc67cec8bd8ad086d5a6265dedb737073bdeaJiwen 'Steve' Cai  ProducerQueue(const ProducerQueueConfig& config, const UsagePolicy& usage);
348e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
349e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
3501db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabakaclass ConsumerQueue : public BufferHubQueue {
351e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
352e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Get a buffer consumer. Note that the method doesn't check whether the
353e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // buffer slot has a valid buffer that has been imported already. When no
3548a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  // buffer has been imported before it returns nullptr; otherwise returns a
3558a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  // shared pointer to a BufferConsumer.
356e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::shared_ptr<BufferConsumer> GetBuffer(size_t slot) const {
357e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return std::static_pointer_cast<BufferConsumer>(
358e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        BufferHubQueue::GetBuffer(slot));
359e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
360e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
3618a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  // Import a ConsumerQueue from a channel handle. |ignore_on_import| controls
3628a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  // whether or not buffers are set to be ignored when imported. This may be
3638a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  // used to avoid participation in the buffer lifecycle by a consumer queue
3648a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  // that is only used to spawn other consumer queues, such as in an
3658a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  // intermediate service.
36652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  static std::unique_ptr<ConsumerQueue> Import(pdx::LocalChannelHandle handle) {
3678a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka    return std::unique_ptr<ConsumerQueue>(
36852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka        new ConsumerQueue(std::move(handle)));
3691db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka  }
3701db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka
371e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Import newly created buffers from the service side.
3721db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka  // Returns number of buffers successfully imported or an error.
373b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  pdx::Status<size_t> ImportBuffers();
374e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
375e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Dequeue a consumer buffer to read. The returned buffer in |Acquired|'ed
376e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // mode, and caller should call Releasse() once it's done writing to release
377e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // the buffer to the producer side. |meta| is passed along from BufferHub,
378e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // The user of BufferProducer is responsible with making sure that the
379e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Dequeue() is done with the corect metadata type and size with those used
380e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // when the buffer is orignally created.
381e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  template <typename Meta>
3829d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
383b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka      int timeout, size_t* slot, Meta* meta, pdx::LocalHandle* acquire_fence) {
384ed6543224138fd753eeea909918bb8d1d2efb1e6Jiwen 'Steve' Cai    return Dequeue(timeout, slot, meta, sizeof(*meta), acquire_fence);
385e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
3869d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
387b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka      int timeout, size_t* slot, pdx::LocalHandle* acquire_fence) {
3888a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka    return Dequeue(timeout, slot, nullptr, 0, acquire_fence);
3898a4e6a90e6b7edf73fa0d79dd5b439f8e52eb9f0Corey Tabaka  }
390e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
3919d8bd09569322f452fddf91e581904f1e8f6849cCorey Tabaka  pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
39252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka      int timeout, size_t* slot, void* meta, size_t user_metadata_size,
39352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka      pdx::LocalHandle* acquire_fence);
39452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
39552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka      int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
396b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka      pdx::LocalHandle* acquire_fence);
3971db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka
398e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private:
3991db8a5d7e3b0565b976e77859e28d77f6a451a2bCorey Tabaka  friend BufferHubQueue;
400e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
40152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  ConsumerQueue(pdx::LocalChannelHandle handle);
402e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
403e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Add a consumer buffer to populate the queue. Once added, a consumer buffer
404e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // is NOT available to use until the producer side |Post| it. |WaitForBuffers|
405e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // will catch the |Post| and |Acquire| the buffer to make it available for
406e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // consumer.
407b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  pdx::Status<void> AddBuffer(const std::shared_ptr<BufferConsumer>& buffer,
408b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka                              size_t slot);
409e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
410b7ca5dee2045d9426e68f863b244012a2b223ea8Corey Tabaka  pdx::Status<void> OnBufferAllocated() override;
411e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
412e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
413e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace dvr
414e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
415e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
416e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#endif  // ANDROID_DVR_BUFFER_HUB_QUEUE_CLIENT_H_
417